Merge pull request #963 from ONLYOFFICE/feature/whitelabel

Feature/whitelabel
This commit is contained in:
Alexey Safronov 2022-11-03 20:10:06 +03:00 committed by GitHub
commit d7abe3b9da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 202 additions and 89 deletions

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

View File

@ -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"

View File

@ -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"

View File

@ -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 = () => {
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,7 +881,6 @@ const WhiteLabel = (props) => {
</div>
</div>
{isSettingPaid && (
<SaveCancelButtons
tabIndex={3}
className="save-cancel-buttons"
@ -847,25 +889,28 @@ const WhiteLabel = (props) => {
saveButtonLabel={t("Common:SaveButton")}
cancelButtonLabel={t("RestoreDefaultButton")}
displaySettings={true}
showReminder={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,

View File

@ -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);

View File

@ -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);
};

View File

@ -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")};
}

View File

@ -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 ? (
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="/static/images/logo.docspace.react.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));

View File

@ -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 () => {

View File

@ -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;
}
`;

View File

@ -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}

View File

@ -2879,7 +2879,7 @@ const Base = {
whiteLabel: {
borderImg: "1px solid #d1d1d1",
backgroundColor: "#0f4071",
backgroundColor: "#ECEEF1",
greenBackgroundColor: "#7e983f",
blueBackgroundColor: "#5170b5",
orangeBackgroundColor: "#e86e2e",

View File

@ -2885,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,
},
},

View File

@ -97,6 +97,7 @@ declare global {
match: MatchType;
currentColorScheme: ITheme;
isAuth: boolean;
logoUrls: any;
}
interface DevRequest {

View File

@ -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}

View File

@ -238,9 +238,11 @@ export const LoginContainer = styled.div`
height: 46px;
padding-bottom: 64px;
svg {
path:last-child {
fill: ${(props) => props.theme.client.home.logoColor};
}
}
@media ${hugeMobile} {
display: none;

View File

@ -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;