diff --git a/products/ASC.Files/Client/yarn.lock b/products/ASC.Files/Client/yarn.lock
index 22b2a4bc2b..8cad14d64a 100644
--- a/products/ASC.Files/Client/yarn.lock
+++ b/products/ASC.Files/Client/yarn.lock
@@ -9458,6 +9458,11 @@ react-content-loader@^5.1.1, react-content-loader@^5.1.2:
resolved "https://registry.yarnpkg.com/react-content-loader/-/react-content-loader-5.1.4.tgz#854bafe4415dd9de07174621375bc308edd0ebb5"
integrity sha512-hTq7pZi2GKCK6a9d3u6XStozm0QGCEjw8cSqQReiWnh2up6IwCha5R5TF0o6SY5qUDpByloEZEZtnFxpJyENFw==
+react-content-loader@^5.1.2:
+ version "5.1.4"
+ resolved "https://registry.yarnpkg.com/react-content-loader/-/react-content-loader-5.1.4.tgz#854bafe4415dd9de07174621375bc308edd0ebb5"
+ integrity sha512-hTq7pZi2GKCK6a9d3u6XStozm0QGCEjw8cSqQReiWnh2up6IwCha5R5TF0o6SY5qUDpByloEZEZtnFxpJyENFw==
+
react-custom-scrollbars@^4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/react-custom-scrollbars/-/react-custom-scrollbars-4.2.1.tgz#830fd9502927e97e8a78c2086813899b2a8b66db"
diff --git a/web/ASC.Web.Client/package.json b/web/ASC.Web.Client/package.json
index f506a2e901..f11149ecd4 100644
--- a/web/ASC.Web.Client/package.json
+++ b/web/ASC.Web.Client/package.json
@@ -23,6 +23,7 @@
"react-redux": "7.1.3",
"react-router": "5.1.2",
"react-router-dom": "5.1.2",
+ "react-string-format": "^0.1.0",
"redux": "4.0.5",
"redux-thunk": "2.3.0",
"reselect": "^4.0.0",
diff --git a/web/ASC.Web.Client/public/images/thirdparties/bitly.svg b/web/ASC.Web.Client/public/images/thirdparties/bitly.svg
new file mode 100644
index 0000000000..6ba56303a3
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/bitly.svg
@@ -0,0 +1,3 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/box.svg b/web/ASC.Web.Client/public/images/thirdparties/box.svg
new file mode 100644
index 0000000000..d5cda33a1e
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/box.svg
@@ -0,0 +1,3 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/clickatell.svg b/web/ASC.Web.Client/public/images/thirdparties/clickatell.svg
new file mode 100644
index 0000000000..d4eccc5889
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/clickatell.svg
@@ -0,0 +1,14 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/docusign.svg b/web/ASC.Web.Client/public/images/thirdparties/docusign.svg
new file mode 100644
index 0000000000..37f1376ee5
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/docusign.svg
@@ -0,0 +1,15 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/dropbox.svg b/web/ASC.Web.Client/public/images/thirdparties/dropbox.svg
new file mode 100644
index 0000000000..6e627f3372
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/dropbox.svg
@@ -0,0 +1,6 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/easybib.svg b/web/ASC.Web.Client/public/images/thirdparties/easybib.svg
new file mode 100644
index 0000000000..625f4f8506
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/easybib.svg
@@ -0,0 +1,5 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/facebook.svg b/web/ASC.Web.Client/public/images/thirdparties/facebook.svg
new file mode 100644
index 0000000000..873bbf1011
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/facebook.svg
@@ -0,0 +1,10 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/firebase.svg b/web/ASC.Web.Client/public/images/thirdparties/firebase.svg
new file mode 100644
index 0000000000..f9c7047b79
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/firebase.svg
@@ -0,0 +1,27 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/google.svg b/web/ASC.Web.Client/public/images/thirdparties/google.svg
new file mode 100644
index 0000000000..82cfec0e7e
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/google.svg
@@ -0,0 +1,8 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/googlecloud.svg b/web/ASC.Web.Client/public/images/thirdparties/googlecloud.svg
new file mode 100644
index 0000000000..123aa4f854
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/googlecloud.svg
@@ -0,0 +1,12 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/linkedin.svg b/web/ASC.Web.Client/public/images/thirdparties/linkedin.svg
new file mode 100644
index 0000000000..93c1bc4862
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/linkedin.svg
@@ -0,0 +1,11 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/mailru.svg b/web/ASC.Web.Client/public/images/thirdparties/mailru.svg
new file mode 100644
index 0000000000..fbe55b1f17
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/mailru.svg
@@ -0,0 +1,5 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/rackspace.svg b/web/ASC.Web.Client/public/images/thirdparties/rackspace.svg
new file mode 100644
index 0000000000..a02515db5e
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/rackspace.svg
@@ -0,0 +1,13 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/s3.svg b/web/ASC.Web.Client/public/images/thirdparties/s3.svg
new file mode 100644
index 0000000000..ec6ff2666b
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/s3.svg
@@ -0,0 +1,5 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/selectel.svg b/web/ASC.Web.Client/public/images/thirdparties/selectel.svg
new file mode 100644
index 0000000000..de7f47c180
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/selectel.svg
@@ -0,0 +1,8 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/skydrive.svg b/web/ASC.Web.Client/public/images/thirdparties/skydrive.svg
new file mode 100644
index 0000000000..26bb99cf79
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/skydrive.svg
@@ -0,0 +1,12 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/smsc.svg b/web/ASC.Web.Client/public/images/thirdparties/smsc.svg
new file mode 100644
index 0000000000..06699de0a8
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/smsc.svg
@@ -0,0 +1,10 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/telegram.svg b/web/ASC.Web.Client/public/images/thirdparties/telegram.svg
new file mode 100644
index 0000000000..26821adc53
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/telegram.svg
@@ -0,0 +1,24 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/twilio.svg b/web/ASC.Web.Client/public/images/thirdparties/twilio.svg
new file mode 100644
index 0000000000..44f5f002e4
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/twilio.svg
@@ -0,0 +1,7 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/twitter.svg b/web/ASC.Web.Client/public/images/thirdparties/twitter.svg
new file mode 100644
index 0000000000..e50f5c48d6
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/twitter.svg
@@ -0,0 +1,10 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/vk.svg b/web/ASC.Web.Client/public/images/thirdparties/vk.svg
new file mode 100644
index 0000000000..20a9f118df
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/vk.svg
@@ -0,0 +1,12 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/wordpress.svg b/web/ASC.Web.Client/public/images/thirdparties/wordpress.svg
new file mode 100644
index 0000000000..2936cc1408
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/wordpress.svg
@@ -0,0 +1,11 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/yahoo.svg b/web/ASC.Web.Client/public/images/thirdparties/yahoo.svg
new file mode 100644
index 0000000000..7453541e0a
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/yahoo.svg
@@ -0,0 +1,188 @@
+
diff --git a/web/ASC.Web.Client/public/images/thirdparties/yandex.svg b/web/ASC.Web.Client/public/images/thirdparties/yandex.svg
new file mode 100644
index 0000000000..f79e82686e
--- /dev/null
+++ b/web/ASC.Web.Client/public/images/thirdparties/yandex.svg
@@ -0,0 +1,8 @@
+
diff --git a/web/ASC.Web.Client/src/components/pages/PaymentsEnterprise/sub-components/headerContainer.js b/web/ASC.Web.Client/src/components/pages/PaymentsEnterprise/sub-components/headerContainer.js
index c9389a37fa..6f982ceae3 100644
--- a/web/ASC.Web.Client/src/components/pages/PaymentsEnterprise/sub-components/headerContainer.js
+++ b/web/ASC.Web.Client/src/components/pages/PaymentsEnterprise/sub-components/headerContainer.js
@@ -21,7 +21,6 @@ const StyledHeader = styled.div`
grid-template-columns: 1fr;
grid-template-rows: min-content min-content;
grid-row-gap: 8px;
-
.payments-header {
font-style: normal;
line-height: 32px;
@@ -30,7 +29,6 @@ const StyledHeader = styled.div`
margin-bottom: 40px;
line-height: 20px;
}
-
@media (max-width: 632px) {
.payments-header-additional_support {
margin-bottom: 16px;
diff --git a/web/ASC.Web.Client/src/components/pages/Settings/categories/integration/index.js b/web/ASC.Web.Client/src/components/pages/Settings/categories/integration/index.js
new file mode 100644
index 0000000000..8fa7531c6b
--- /dev/null
+++ b/web/ASC.Web.Client/src/components/pages/Settings/categories/integration/index.js
@@ -0,0 +1,30 @@
+import React, { lazy, Suspense } from "react";
+import { Route, Switch } from "react-router-dom";
+import { withRouter } from "react-router";
+import { Loader } from "asc-web-components";
+
+const ThirdPartyServices = lazy(() => import("./thirdPartyServicesSettings"));
+
+const Integration = ({ match }) => {
+ const basePath = "/settings/integration";
+
+ return (
+ }
+ >
+
+
+
+
+ );
+};
+
+export default withRouter(Integration);
diff --git a/web/ASC.Web.Client/src/components/pages/Settings/categories/integration/sub-components/consumerItem.js b/web/ASC.Web.Client/src/components/pages/Settings/categories/integration/sub-components/consumerItem.js
new file mode 100644
index 0000000000..64cbe445f6
--- /dev/null
+++ b/web/ASC.Web.Client/src/components/pages/Settings/categories/integration/sub-components/consumerItem.js
@@ -0,0 +1,63 @@
+import React from "react";
+import PropTypes from "prop-types";
+import { Box, Text } from "asc-web-components";
+import ConsumerToggle from "./consumerToggle";
+
+class ConsumerItem extends React.Component {
+ render() {
+ const {
+ consumer,
+ onModalOpen,
+ setConsumer,
+ updateConsumerProps,
+ t,
+ } = this.props;
+
+ const logo = `/images/thirdparties/${consumer.name.toLowerCase()}.svg`;
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+ {consumer.description}
+
+
+ >
+ );
+ }
+}
+
+export default ConsumerItem;
+
+ConsumerItem.propTypes = {
+ consumer: PropTypes.shape({
+ name: PropTypes.string,
+ title: PropTypes.string,
+ description: PropTypes.string,
+ instruction: PropTypes.string,
+ canSet: PropTypes.bool,
+ props: PropTypes.arrayOf(PropTypes.object),
+ }).isRequired,
+ onModalOpen: PropTypes.func.isRequired,
+ setConsumer: PropTypes.func.isRequired,
+ updateConsumerProps: PropTypes.func.isRequired,
+};
diff --git a/web/ASC.Web.Client/src/components/pages/Settings/categories/integration/sub-components/consumerModalDialog.js b/web/ASC.Web.Client/src/components/pages/Settings/categories/integration/sub-components/consumerModalDialog.js
new file mode 100644
index 0000000000..bd7bb9a8f2
--- /dev/null
+++ b/web/ASC.Web.Client/src/components/pages/Settings/categories/integration/sub-components/consumerModalDialog.js
@@ -0,0 +1,227 @@
+import React from "react";
+import PropTypes from "prop-types";
+import {
+ ModalDialog,
+ Text,
+ Button,
+ TextInput,
+ Box,
+ Link,
+ toastr,
+} from "asc-web-components";
+import ModalDialogContainer from "./modalDialogContainer";
+import { Trans } from "react-i18next";
+import { connect } from "react-redux";
+import {
+ getSelectedConsumer,
+ getConsumerInstruction,
+} from "../../../../../../store/settings/selectors";
+import { store as commonStore } from "asc-web-common";
+
+const { getUrlSupport, getUrlAuthKeys } = commonStore.auth.selectors;
+
+class ConsumerModalDialog extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {};
+ }
+
+ mapTokenNameToState = () => {
+ const { selectedConsumer } = this.props;
+ selectedConsumer.props.map((prop) =>
+ this.setState({
+ [`${prop.name}`]: prop.value,
+ })
+ );
+ };
+
+ onChangeHandler = (e) => {
+ this.setState({
+ [e.target.name]: e.target.value,
+ });
+ };
+
+ updateConsumerValues = () => {
+ const {
+ onChangeLoading,
+ selectedConsumer,
+ updateConsumerProps,
+ onModalClose,
+ t,
+ } = this.props;
+ const { state } = this;
+
+ onChangeLoading(true);
+
+ const prop = [];
+
+ let i = 0;
+ let stateLength = Object.keys(state).length;
+ for (i = 0; i < stateLength; i++) {
+ prop.push({
+ name: Object.keys(state)[i],
+ value: Object.values(state)[i],
+ });
+ }
+ const data = {
+ name: selectedConsumer.name,
+ props: prop,
+ };
+ updateConsumerProps(data)
+ .then(() => {
+ onChangeLoading(false);
+ toastr.success(t("ThirdPartyPropsActivated"));
+ })
+ .catch((error) => {
+ onChangeLoading(false);
+ toastr.error(error);
+ })
+ .finally(onModalClose());
+ };
+
+ // shouldComponentUpdate(nextProps, nextState) {
+ // console.log("this.state: ", this.state, "nextState: ", nextState);
+ // return nextState !== this.state;
+ // }
+
+ componentDidMount() {
+ this.mapTokenNameToState();
+ }
+
+ bodyDescription = (
+
+
+
+ {this.props.t("ThirdPartyHowItWorks")}
+
+
+
+
+ For more detailed instructions about connecting this service, please
+ refer to our{" "}
+
+ Help Center
+ {" "}
+ that provides all the necessary information.
+
+
+
+ );
+
+ bottomDescription = (
+
+ If you still have some questions on how to connect this service or need
+ technical assistance, please feel free to contact our{" "}
+
+ Support Team
+
+
+ );
+
+ render() {
+ const {
+ selectedConsumer,
+ consumerInstruction,
+ onModalClose,
+ dialogVisible,
+ isLoading,
+ t,
+ } = this.props;
+ const {
+ state,
+ onChangeHandler,
+ updateConsumerValues,
+ bodyDescription,
+ bottomDescription,
+ } = this;
+
+ return (
+
+
+ {selectedConsumer.title}
+
+ {consumerInstruction}
+ {bodyDescription}
+
+ {selectedConsumer.props.map((prop, i) => (
+
+
+
+ {prop.title}:
+
+
+
+
+
+
+ ))}
+
+ {bottomDescription}
+
+
+
+
+
+
+ );
+ }
+}
+
+ConsumerModalDialog.propTypes = {
+ t: PropTypes.func.isRequired,
+ i18n: PropTypes.object.isRequired,
+ selectedConsumer: PropTypes.object,
+ onModalClose: PropTypes.func.isRequired,
+ dialogVisible: PropTypes.bool.isRequired,
+ isLoading: PropTypes.bool.isRequired,
+ onChangeLoading: PropTypes.func.isRequired,
+ updateConsumerProps: PropTypes.func.isRequired,
+ urlSupport: PropTypes.string,
+};
+
+const mapStateToProps = (state) => {
+ return {
+ selectedConsumer: getSelectedConsumer(state),
+ consumerInstruction: getConsumerInstruction(state),
+ urlSupport: getUrlSupport(state),
+ urlAuthKeys: getUrlAuthKeys(state),
+ };
+};
+
+export default connect(mapStateToProps, null)(ConsumerModalDialog);
diff --git a/web/ASC.Web.Client/src/components/pages/Settings/categories/integration/sub-components/consumerToggle.js b/web/ASC.Web.Client/src/components/pages/Settings/categories/integration/sub-components/consumerToggle.js
new file mode 100644
index 0000000000..eea5882c71
--- /dev/null
+++ b/web/ASC.Web.Client/src/components/pages/Settings/categories/integration/sub-components/consumerToggle.js
@@ -0,0 +1,88 @@
+import React from "react";
+import PropTypes from "prop-types";
+import { ToggleButton, toastr } from "asc-web-components";
+import styled from "styled-components";
+
+const StyledToggle = styled(ToggleButton)`
+ position: relative;
+`;
+
+class ConsumerToggle extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ toggleActive: false,
+ };
+ }
+
+ onToggleClick = (e) => {
+ const { consumer, onModalOpen, updateConsumerProps, t } = this.props;
+
+ if (e.currentTarget.checked) {
+ onModalOpen();
+ } else {
+ this.setState({
+ toggleActive: false,
+ });
+
+ const prop = [];
+ let i = 0;
+ let propsLength = Object.keys(consumer.props).length;
+
+ for (i = 0; i < propsLength; i++) {
+ prop.push({
+ name: consumer.props[i].name,
+ value: "",
+ });
+ }
+
+ const data = {
+ name: consumer.name,
+ props: prop,
+ };
+
+ updateConsumerProps(data)
+ .then(() => {
+ toastr.success(t("ThirdPartyPropsDeactivated"));
+ })
+ .catch((error) => {
+ toastr.error(error);
+ });
+ }
+ };
+
+ render() {
+ const { consumer } = this.props;
+ const { toggleActive } = this.state;
+ const { onToggleClick } = this;
+
+ return (
+ <>
+ p.value)
+ ? true
+ : toggleActive
+ }
+ />
+ >
+ );
+ }
+}
+
+export default ConsumerToggle;
+
+ConsumerToggle.propTypes = {
+ consumer: PropTypes.shape({
+ name: PropTypes.string,
+ title: PropTypes.string,
+ description: PropTypes.string,
+ instruction: PropTypes.string,
+ canSet: PropTypes.bool,
+ props: PropTypes.arrayOf(PropTypes.object),
+ }).isRequired,
+ onModalOpen: PropTypes.func.isRequired,
+ updateConsumerProps: PropTypes.func.isRequired,
+};
diff --git a/web/ASC.Web.Client/src/components/pages/Settings/categories/integration/sub-components/modalDialogContainer.js b/web/ASC.Web.Client/src/components/pages/Settings/categories/integration/sub-components/modalDialogContainer.js
new file mode 100644
index 0000000000..ca7c9206d7
--- /dev/null
+++ b/web/ASC.Web.Client/src/components/pages/Settings/categories/integration/sub-components/modalDialogContainer.js
@@ -0,0 +1,22 @@
+import styled from "styled-components";
+import { utils } from "asc-web-components";
+
+const tablet = utils.device.tablet;
+
+const ModalDialogContainer = styled.div`
+ .modal-dialog-aside-footer {
+ @media ${tablet} {
+ width: 90%;
+ }
+ }
+ .modal-dialog-button {
+ @media ${tablet} {
+ width: 100%;
+ }
+ }
+ .field-body {
+ margin-top: 16px;
+ }
+`;
+
+export default ModalDialogContainer;
diff --git a/web/ASC.Web.Client/src/components/pages/Settings/categories/integration/thirdPartyServicesSettings.js b/web/ASC.Web.Client/src/components/pages/Settings/categories/integration/thirdPartyServicesSettings.js
new file mode 100644
index 0000000000..00cbe092ff
--- /dev/null
+++ b/web/ASC.Web.Client/src/components/pages/Settings/categories/integration/thirdPartyServicesSettings.js
@@ -0,0 +1,223 @@
+import React from "react";
+import PropTypes from "prop-types";
+import { connect } from "react-redux";
+import {
+ getConsumers,
+ setSelectedConsumer,
+ updateConsumerProps,
+} from "../../../../../store/settings/actions";
+import { getConsumersList } from "../../../../../store/settings/selectors";
+import { withTranslation } from "react-i18next";
+import styled from "styled-components";
+
+import { Box, Text, Link, toastr } from "asc-web-components";
+import { utils } from "asc-web-components";
+import { store as commonStore } from "asc-web-common";
+import ConsumerItem from "./sub-components/consumerItem";
+import ConsumerModalDialog from "./sub-components/consumerModalDialog";
+
+const { getUrlAuthKeys } = commonStore.auth.selectors;
+
+const tablet = utils.device.tablet;
+const mobile = utils.device.mobile;
+
+const RootContainer = styled(Box)`
+ @media ${tablet} {
+ margin: 0;
+
+ .consumers-list-container {
+ margin: 32px 0 40px 0;
+ }
+ }
+
+ @media ${tablet} {
+ .consumer-item-wrapper {
+ margin: 0 0 24px 0;
+ }
+ }
+`;
+const StyledConsumer = styled(Box)`
+ width: 400px;
+
+ @media ${tablet} {
+ width: 496px;
+ }
+
+ @media ${mobile} {
+ width: 343px;
+ }
+`;
+const Separator = styled.div`
+ border: 1px solid #eceef1;
+`;
+
+class ThirdPartyServices extends React.Component {
+ constructor(props) {
+ super(props);
+ const { t } = props;
+ document.title = `${t("ThirdPartyAuthorization")} – ${t(
+ "OrganizationName"
+ )}`;
+
+ this.state = {
+ dialogVisible: false,
+ isLoading: false,
+ };
+ }
+
+ componentDidMount() {
+ const { getConsumers } = this.props;
+ getConsumers();
+ }
+
+ onChangeLoading = (status) => {
+ this.setState({
+ isLoading: status,
+ });
+ };
+
+ onModalOpen = () => {
+ this.setState({
+ dialogVisible: true,
+ });
+ };
+
+ onModalClose = () => {
+ this.setState({
+ dialogVisible: false,
+ });
+ this.props.setSelectedConsumer();
+ };
+
+ setConsumer = (e) => {
+ this.props.setSelectedConsumer(e.currentTarget.dataset.consumer);
+ };
+
+ updateConsumerValues = (obj, isFill) => {
+ isFill && this.onChangeLoading(true);
+
+ const prop = [];
+ let i = 0;
+ let objLength = Object.keys(isFill ? obj : obj.props).length;
+
+ for (i = 0; i < objLength; i++) {
+ prop.push({
+ name: isFill ? Object.keys(obj)[i] : obj.props[i].name,
+ value: isFill ? Object.values(obj)[i] : "",
+ });
+ }
+
+ const data = {
+ name: isFill ? this.state.selectedConsumer : obj.name,
+ props: prop,
+ };
+
+ this.props
+ .updateConsumerProps(data)
+ .then(() => {
+ isFill && this.onChangeLoading(false);
+ isFill
+ ? toastr.success(this.props.t("ThirdPartyPropsActivated"))
+ : toastr.success(this.props.t("ThirdPartyPropsDeactivated"));
+ })
+ .catch((error) => {
+ isFill && this.onChangeLoading(false);
+ toastr.error(error);
+ })
+ .finally(isFill && this.onModalClose());
+ };
+
+ render() {
+ const { t, i18n, consumers, updateConsumerProps, urlAuthKeys } = this.props;
+ const { dialogVisible, isLoading } = this.state;
+ const { onModalClose, onModalOpen, setConsumer, onChangeLoading } = this;
+
+ return (
+ <>
+
+
+ {t("ThirdPartyTitleDescription")}
+
+
+ {t("LearnMore")}
+
+
+
+
+ {consumers.map((consumer) => (
+
+
+
+
+
+
+ ))}
+
+
+ {dialogVisible && (
+
+ )}
+ >
+ );
+ }
+}
+
+ThirdPartyServices.propTypes = {
+ t: PropTypes.func.isRequired,
+ i18n: PropTypes.object.isRequired,
+ consumers: PropTypes.arrayOf(PropTypes.object).isRequired,
+ urlAuthKeys: PropTypes.string,
+ getConsumers: PropTypes.func.isRequired,
+ updateConsumerProps: PropTypes.func.isRequired,
+ setSelectedConsumer: PropTypes.func.isRequired,
+};
+
+const mapStateToProps = (state) => {
+ return {
+ consumers: getConsumersList(state),
+ urlAuthKeys: getUrlAuthKeys(state),
+ };
+};
+
+export default connect(mapStateToProps, {
+ getConsumers,
+ updateConsumerProps,
+ setSelectedConsumer,
+})(withTranslation()(ThirdPartyServices));
diff --git a/web/ASC.Web.Client/src/components/pages/Settings/index.js b/web/ASC.Web.Client/src/components/pages/Settings/index.js
index e7df7cdcb5..1ce259be60 100644
--- a/web/ASC.Web.Client/src/components/pages/Settings/index.js
+++ b/web/ASC.Web.Client/src/components/pages/Settings/index.js
@@ -11,6 +11,9 @@ const LanguageAndTimeZoneSettings = lazy(() =>
import("./categories/common/language-and-time-zone")
);
const CustomTitles = lazy(() => import("./categories/common/custom-titles"));
+const ThirdPartyServices = lazy(() =>
+ import("./categories/integration/thirdPartyServicesSettings")
+);
//const WhiteLabel = lazy(() => import("./categories/common/whitelabel"));
@@ -46,6 +49,11 @@ const Settings = () => {
component={WhiteLabel}
/> */}
+ Help Center2> that provides all the necessary information.",
+ "ThirdPartyHowItWorks": "How It Works?",
+ "ThirdPartyBottomDescription": "If you still have some questions on how to connect this service or need technical assistance, please feel free to contact our <2>Support Team.2>",
+ "ThirdPartyPropsActivated": "Consumer properties successfully update",
+ "ThirdPartyPropsDeactivated": "Consumer successfully deactivated",
+ "ThirdPartyEnableButton": "Enable",
+ "ThirdPartyProcessSending": "Sending...",
+
"ProjectsUserCapabilityView": "View projects and take part in discussions",
"ProjectsUserCapabilityCreate": "Create and edit milestones, tasks, discussions, documents",
"ProjectsUserCapabilityTrack": "Track time for tasks, generate reports",
diff --git a/web/ASC.Web.Client/src/components/pages/Settings/locales/ru/translation.json b/web/ASC.Web.Client/src/components/pages/Settings/locales/ru/translation.json
index e06ca312fb..0f38c7e03c 100644
--- a/web/ASC.Web.Client/src/components/pages/Settings/locales/ru/translation.json
+++ b/web/ASC.Web.Client/src/components/pages/Settings/locales/ru/translation.json
@@ -70,6 +70,15 @@
"LearnMore": "Подробнее...",
"AccessRightsChangeOwnerButtonText": "Сменить владельца портала",
+ "ThirdPartyTitleDescription": "Ключи авторизации позволяют подключить портал ONLYOFFICE к сторонним сервисам, таким как Twitter, Facebook, Dropbox и т.д. Подключите портал к Facebook, Twitter или Linkedin, если Вы не хотите каждый раз при входе вводить свои учетные данные на портале. Привяжите портал к таким сервисам, как Dropbox, OneDrive и т.д. чтобы перенести документы из всех этих хранилищ в модуль Документы ONLYOFFICE.",
+ "ThirdPartyBodyDescription": "Для получения подробных инструкций по подключению этого сервиса, пожалуйста, перейдите в наш <2>Справочный центр2>, где приводится вся необходимая информация.",
+ "ThirdPartyHowItWorks": "Как это работает?",
+ "ThirdPartyBottomDescription": "Если у вас остались вопросы по подключению этого сервиса или вам требуется помощь, вы всегда можете обратиться в нашу <2>Службу поддержки2>.",
+ "ThirdPartyPropsActivated": "Настройки сервиса успешно обновлены",
+ "ThirdPartyPropsDeactivated": "Сервис был успешно отключен",
+ "ThirdPartyEnableButton": "Включить",
+ "ThirdPartyProcessSending": "Отправка...",
+
"ProductUserOpportunities": "Просматривать профили и группы",
"AccessRightsAccessToProduct": "Доступ к модулю {{product}} предоставлен для",
"ProjectsUserCapabilityView": "Просматривать проекты и участвовать в обсуждениях",
diff --git a/web/ASC.Web.Client/src/components/pages/Settings/utils/settingsTree.js b/web/ASC.Web.Client/src/components/pages/Settings/utils/settingsTree.js
index 8f0baf77a2..b5ab275ab5 100644
--- a/web/ASC.Web.Client/src/components/pages/Settings/utils/settingsTree.js
+++ b/web/ASC.Web.Client/src/components/pages/Settings/utils/settingsTree.js
@@ -54,7 +54,22 @@ export const settingsTree = [
},
],
},
-];
+ {
+ key: "3",
+ icon: "IntegrationIcon",
+ link: "integration",
+ tKey: "ManagementCategoryIntegration",
+ isHeader: true,
+ children: [
+ {
+ key: "3-0",
+ icon: "",
+ link: "third-party-services",
+ tKey: "ThirdPartyAuthorization",
+ isCategory: true,
+ },
+ ],
+ },];
/**
* Array for generation full settings tree, old structure.
diff --git a/web/ASC.Web.Client/src/store/settings/actions.js b/web/ASC.Web.Client/src/store/settings/actions.js
index 8a83f422c7..7bf024c45c 100644
--- a/web/ASC.Web.Client/src/store/settings/actions.js
+++ b/web/ASC.Web.Client/src/store/settings/actions.js
@@ -15,6 +15,8 @@ export const SET_FILTER = "SET_FILTER";
export const SET_LOGO_TEXT = "SET_LOGO_TEXT";
export const SET_LOGO_SIZES = "SET_LOGO_SIZES";
export const SET_LOGO_URLS = "SET_LOGO_URLS";
+export const SET_CONSUMERS = "SET_CONSUMERS";
+export const SET_SELECTED_CONSUMER = "SET_SELECTED_CONSUMER";
export function setOptions(options) {
return {
@@ -72,6 +74,20 @@ export function setLogoUrls(urls) {
};
}
+export function setConsumers(consumers) {
+ return {
+ type: SET_CONSUMERS,
+ consumers,
+ };
+}
+
+export function setSelectedConsumer(selectedConsumer) {
+ return {
+ type: SET_SELECTED_CONSUMER,
+ selectedConsumer,
+ };
+}
+
export function changeAdmins(userIds, productId, isAdmin, filter) {
let filterData = filter && filter.clone();
if (!filterData) {
@@ -186,3 +202,19 @@ export function restoreGreetingTitle() {
});
};
}
+
+export function getConsumers() {
+ return (dispatch) => {
+ return api.settings
+ .getConsumersList()
+ .then((res) => dispatch(setConsumers(res)));
+ };
+}
+
+export function updateConsumerProps(newProps) {
+ return (dispatch) => {
+ return api.settings
+ .updateConsumerProps(newProps)
+ .then(() => dispatch(getConsumers()));
+ };
+}
diff --git a/web/ASC.Web.Client/src/store/settings/reducer.js b/web/ASC.Web.Client/src/store/settings/reducer.js
index 2e886f61d6..70f0bfed45 100644
--- a/web/ASC.Web.Client/src/store/settings/reducer.js
+++ b/web/ASC.Web.Client/src/store/settings/reducer.js
@@ -7,6 +7,8 @@ import {
SET_LOGO_TEXT,
SET_LOGO_SIZES,
SET_LOGO_URLS,
+ SET_CONSUMERS,
+ SET_SELECTED_CONSUMER,
} from "./actions";
import { api } from "asc-web-common";
const { Filter } = api;
@@ -28,6 +30,10 @@ const initialState = {
filter: Filter.getDefault(),
},
},
+ integration: {
+ consumers: [],
+ selectedConsumer: {},
+ },
};
const peopleReducer = (state = initialState, action) => {
@@ -97,6 +103,27 @@ const peopleReducer = (state = initialState, action) => {
},
});
+ case SET_CONSUMERS:
+ return {
+ ...state,
+ integration: {
+ ...state.integration,
+ consumers: action.consumers,
+ },
+ };
+
+ case SET_SELECTED_CONSUMER:
+ return {
+ ...state,
+ integration: {
+ ...state.integration,
+ selectedConsumer:
+ state.integration.consumers.find(
+ (c) => c.name === action.selectedConsumer
+ ) || {},
+ },
+ };
+
default:
return state;
}
diff --git a/web/ASC.Web.Client/src/store/settings/selectors.js b/web/ASC.Web.Client/src/store/settings/selectors.js
index 567abe9407..d0b6803887 100644
--- a/web/ASC.Web.Client/src/store/settings/selectors.js
+++ b/web/ASC.Web.Client/src/store/settings/selectors.js
@@ -1,3 +1,8 @@
+import React from "react";
+import { Box } from "asc-web-components";
+import { format } from "react-string-format";
+import { createSelector } from "reselect";
+
export const getUserRole = (user) => {
if (user.isOwner) return "owner";
else if (user.isAdmin) return "admin";
@@ -9,3 +14,18 @@ export const getUserRole = (user) => {
else if (user.isVisitor) return "guest";
else return "user";
};
+
+export const getConsumersList = (state) => state.settings.integration.consumers;
+
+export const getSelectedConsumer = (state) =>
+ state.settings.integration.selectedConsumer;
+
+export const getConsumerInstruction = createSelector(
+ getSelectedConsumer,
+ (consumer) => {
+ return (
+ consumer.instruction &&
+ format(consumer.instruction, )
+ );
+ }
+);
diff --git a/web/ASC.Web.Client/yarn.lock b/web/ASC.Web.Client/yarn.lock
index d40d502370..fd087061ed 100644
--- a/web/ASC.Web.Client/yarn.lock
+++ b/web/ASC.Web.Client/yarn.lock
@@ -9657,6 +9657,11 @@ react-scripts@3.4.3:
optionalDependencies:
fsevents "2.1.2"
+react-string-format@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/react-string-format/-/react-string-format-0.1.0.tgz#a815c2400eff74559ba72d76af50024d157d9e29"
+ integrity sha512-xkIhnh2t1YmS4r8Zz92qs0Ia8EMbBoRlMEvvMtC0sQBSxxBmBujfssSA4PYYi0w2WvJYSEktgilB+320/mlsOQ==
+
react-svg@^11.0.9:
version "11.1.1"
resolved "https://registry.yarnpkg.com/react-svg/-/react-svg-11.1.1.tgz#0e9b11fbf0efc7df347d8f268e8d77fd9d022a3a"
diff --git a/web/ASC.Web.Common/src/api/settings/index.js b/web/ASC.Web.Common/src/api/settings/index.js
index e408f23a8d..8bb4e6f653 100644
--- a/web/ASC.Web.Common/src/api/settings/index.js
+++ b/web/ASC.Web.Common/src/api/settings/index.js
@@ -174,3 +174,19 @@ export function acceptLicense() {
url: `/settings/license/accept.json`,
});
}
+export function getConsumersList() {
+ return request({
+ method: "get",
+ url: `/settings/authservice`,
+ });
+}
+
+export function updateConsumerProps(newProps) {
+ const options = {
+ method: "post",
+ url: `/settings/authservice`,
+ data: newProps,
+ };
+
+ return request(options);
+}
diff --git a/web/ASC.Web.Common/src/store/auth/selectors.js b/web/ASC.Web.Common/src/store/auth/selectors.js
index acf594e947..1c85841c21 100644
--- a/web/ASC.Web.Common/src/store/auth/selectors.js
+++ b/web/ASC.Web.Common/src/store/auth/selectors.js
@@ -190,3 +190,7 @@ export const getOrganizationName = createSelector([getSettings], (settings) => {
const { organizationName } = settings;
return organizationName;
});
+
+export const getUrlSupport = (state) => state.auth.settings.urlSupport;
+
+export const getUrlAuthKeys = (state) => state.auth.settings.urlAuthKeys;
diff --git a/web/ASC.Web.Components/src/components/icons/svg/index.js b/web/ASC.Web.Components/src/components/icons/svg/index.js
index c476bc7c31..fd7d7a15ab 100644
--- a/web/ASC.Web.Components/src/components/icons/svg/index.js
+++ b/web/ASC.Web.Components/src/components/icons/svg/index.js
@@ -197,6 +197,8 @@ import OrigRecentIcon from "./catalog.recent.react.svg";
import OrigCatalogPrivateRoomIcon from "./catalog.private.react.svg";
+import OrigIntegrationIcon from "./integration.react.svg";
+
export const AZSortingIcon = createStyledIcon(
OrigAZSortingIcon,
"AZSortingIcon"
@@ -752,18 +754,12 @@ export const RotateRightIcon = createStyledIcon(
OrigRotateRight,
"RotateRightIcon"
);
-export const FavoritesIcon = createStyledIcon(
- OrigFavorites,
- "FavoritesIcon"
-);
+export const FavoritesIcon = createStyledIcon(OrigFavorites, "FavoritesIcon");
export const CatalogFavoritesIcon = createStyledIcon(
OrigCatalogFavoritesIcon,
"CatalogFavoritesIcon"
);
-export const FavoriteIcon = createStyledIcon(
- OrigFavoriteIcon,
- "FavoriteIcon"
-);
+export const FavoriteIcon = createStyledIcon(OrigFavoriteIcon, "FavoriteIcon");
export const CatalogRecentIcon = createStyledIcon(
OrigRecentIcon,
"CatalogRecentIcon"
@@ -772,3 +768,7 @@ export const CatalogPrivateRoomIcon = createStyledIcon(
OrigCatalogPrivateRoomIcon,
"CatalogPrivateRoomIcon"
);
+export const IntegrationIcon = createStyledIcon(
+ OrigIntegrationIcon,
+ "IntegrationIcon"
+);
diff --git a/web/ASC.Web.Components/src/components/icons/svg/integration.react.svg b/web/ASC.Web.Components/src/components/icons/svg/integration.react.svg
new file mode 100644
index 0000000000..f72d575c66
--- /dev/null
+++ b/web/ASC.Web.Components/src/components/icons/svg/integration.react.svg
@@ -0,0 +1,12 @@
+
diff --git a/web/ASC.Web.Core/PublicResources/Resource.de.resx b/web/ASC.Web.Core/PublicResources/Resource.de.resx
index 9cbf6fd3de..6feeb8344c 100644
--- a/web/ASC.Web.Core/PublicResources/Resource.de.resx
+++ b/web/ASC.Web.Core/PublicResources/Resource.de.resx
@@ -103,6 +103,9 @@
Wenn Sie den Bitly-Dienst hinzufügen, erhalten Sie verkürzte Links, um neue Nutzer zum ONLYOFFICE ™ -Portal einzuladen und verkürzte Links zu dem Modul "Dokumente", der mit externen Benutzern geteilt wurde.
+
+ Verbinden Sie Bitly Service, um Einladungslinks und freigegebene Links zu dem Modul "Dokumente" zu verkürzen. {0}Fügen Sie Ihr Bitly-Login und API-Schlüssel unten ein:
+
Box Schlüssel
@@ -118,6 +121,9 @@
Wenn man die Anwendung des Box-Dienstes hinzufügt, kann man sein Box-Konto mit dem Modul "Dokumente" verknüpfen. Dies ermöglicht das Hochladen und Erstellen neuer Dateien in Box, Bearbeiten der bestehenden Dateien, Kopieren und Löschen, Freigabe von Dateien oder Ordnern mit ONLYOFFICE ™ Portalbenutzer.
+
+ Erlauben Sie dieser App, die Verbindung von Box mit dem Modul Dokumente zu ermöglichen. Dadurch können Sie Dateien aus Ihrem Box-Konto verwalten, bearbeiten und für ONLYOFFICE-Benutzer freigeben. {0}Melden Sie bei Ihrem Konto auf der Box-Seite für Entwickler an, erstellen Sie eine neue App für die Integration mit ONLYOFFICE. Fügen Sie die erhaltenen Daten unten ein:
+
Clickatell
@@ -130,6 +136,9 @@
Durch Hinzufügen der Clickatell-Dienstanwendung können Sie die Zwei-Faktor-Authentifizierung aktivieren und eine SMS mit einem Code empfangen, der es dem Benutzer ermöglicht, das ONLYOFFICE-Portal zu betreten.
+
+ Benutzen Sie diese App, um die Zwei-Faktor-Authentifizierung über Clickatell zu ermöglichen. {0}Melden Sie bei Ihrer SMS-Plattform an und erstellen Sie eine neue Integration mit ONLYOFFICE. Kopieren Sie den API-Schlüssel und fügen Sie diesen unten ein:
+
DocuSign
@@ -149,6 +158,9 @@
Wenn man die Anwendung des DocuSign-Dienstes hinzufügt, kann man Dateien aus dem Modul "Dokumente" signieren. Dies ermöglicht Ihnen, Dateien über DocuSugn für eine elektronische Signatur an die Mitarbeiter des ONLYOFFICE ™ Portals zu schicken. Die signierte Datei wird im ONLYOFFICE Modul gespeichert.
+
+ Erlauben Sie dieser App, Dokumente mit DocuSign digital zu unterschreiben. {0}Öffnen Sie Ihre DocuSign Admin-Konsole und ermöglichen Sie die Integration mit ONLYOFFICE. Fügen Sie die erhaltenen Daten unten ein:
+
Dropbox
@@ -158,6 +170,9 @@
Wenn man die Anwendung des Dropbox-Dienstes hinzufügt, kann man sein Dropbox -Konto mit dem Modul "Dokumente" verknüpfen. Dies ermöglicht das Hochladen und Erstellen neuer Dateien in Dropbox, Bearbeiten der bestehenden Dateien, Kopieren und Löschen, Freigabe von Dateien oder Ordnern mit ONLYOFFICE ™ Portalbenutzer.
+
+ Erlauben Sie dieser App, die Verbindung von Dropbox mit dem Modul Dokumente zu ermöglichen. Dadurch können Sie Dateien aus Ihrem Dropbox-Konto verwalten, bearbeiten und für ONLYOFFICE-Benutzer freigeben. {0}Melden Sie bei Ihrem Konto auf der Dropbox-Seite für Entwickler an, erstellen Sie eine neue App für die Integration mit ONLYOFFICE. Fügen Sie die erhaltenen Daten unten ein:
+
Dropbox ID
@@ -196,6 +211,9 @@
+
+ Erlauben Sie dieser App, Einloggen bei ONLYOFFICE über Facebook und Import von Facebook-Kontakten ins CRM-Modul zu ermöglichen. {0}Öffnen Sie das Facebook-Portal für Entwickler und erstellen Sie eine neue App für die Integration mit ONLYOFFICE. Fügen Sie die erhaltenen Daten unten ein:
+
Firebase
@@ -251,6 +269,9 @@
Wenn Sie ein Projekt des Google-Dienstes hinzufügen, können Sie Ihr Google-Konto mit Ihrer Profilseite verbinden, sodass Sie sich im ONLYOFFICE ™ -Portal anmelden und Ihr Google Drive-Konto im Modul Dokumente verbinden können. Dies ermöglicht Ihnen, neue Dateien in Google Drive hochzuladen und zu erstellen, bestehende zu bearbeiten, sie zu kopieren und zu löschen, Dateien und Ordner den ONLYOFFICE ™ Portalbenutzern freizugeben.
+
+ Erlauben Sie dieser App, die Verbindung von Google Drive mit dem Modul Dokumente zu ermöglichen. Dadurch können Sie Dateien aus Ihrem Google Drive-Konto verwalten, bearbeiten und für ONLYOFFICE-Benutzer freigeben. {0}Öffnen Sie Google APIs Console und erstellen Sie ein neues Projekt für die Integration mit ONLYOFFICE. Fügen Sie die erhaltenen Daten unten ein:
+
Linkedin-Schlüssel
@@ -260,6 +281,9 @@
Wenn man die Anwendung des LinkedIn-Dienstes hinzufügt, kann man sein LinkedIn-Konto mit der Profilseite verknüpfen. So meldet man sich ins ONLYOFFICE™ Portal mit eigenen LinkedIn-Login-Daten an.
+
+ Erlauben Sie dieser App, Einloggen bei ONLYOFFICE über LinkedIn-Konten zu ermöglichen. {0}Öffnen Sie die LinkedIn-Seite für Entwickler (LinkedIn Developers) und erstellen Sie eine neue App für die Integration mit ONLYOFFICE. Fügen Sie die erhaltenen Daten unten ein:
+
Linkedin ID
@@ -374,6 +398,9 @@
Wenn man die Anwendung des OneDrive-Dienstes hinzufügt, kann man sein OneDrive-Konto mit dem Modul "Dokumente" verknüpfen. Dies ermöglicht das Hochladen und Erstellen neuer Dateien in OneDrive, Bearbeiten der bestehenden Dateien, Kopieren und Löschen, Freigabe von Dateien oder Ordnern mit ONLYOFFICE ™ Portalbenutzer.
+
+ Erlauben Sie dieser App, die Verbindung von OneDrive mit dem Modul Dokumente zu ermöglichen. Dadurch können Sie Dateien aus Ihrem OneDrive-Konto verwalten, bearbeiten und für ONLYOFFICE-Benutzer freigeben. {0}Melden Sie bei Ihrem Microsoft Azure-Konto an und erstellen Sie eine neue App für die Integration mit ONLYOFFICE. Fügen Sie die erhaltenen Daten unten ein:
+
SMS-Center
@@ -383,6 +410,9 @@
Durch Hinzufügen der SMS-Center-Dienstanwendung können Sie die Zwei-Faktor-Authentifizierung aktivieren und eine SMS mit einem Code empfangen, der es dem Benutzer ermöglicht, das ONLYOFFICE-Portal zu betreten. SMS-Center-Anwendung ist als Anbieter für die GUS-Staaten nützlich.
+
+ Benutzen Sie diese App, um die Zwei-Faktor-Authentifizierung über SMS Center zu ermöglichen. {0}Geben Sie Ihre SMSC Anmeldedaten (Login und Passwort bzw. MD5-Passwort) unten ein:
+
Login
@@ -404,6 +434,9 @@
Nachdem Sie Twilio hinzugefügt haben, können Sie jeden CRM-Kontakt direkt aus dem Browser anrufen.
+
+ Erlauben Sie dieser App, Anrufe aus dem CRM-Modul mit Twilio zu ermöglichen. {0}Öffnen Sie die Twilio-Konsole und fügen Sie die folgenden Daten unten ein:
+
Telefonnummer von Twilio (erforderlich für die SMS-Autorisierung)
@@ -422,6 +455,9 @@
Wenn man die Anwendung des Twitter-Dienstes hinzufügt, kann man sein Twitter-Konto mit der Profilseite verknüpfen. So meldet man sich ins ONLYOFFICE™ Portal mit eigenen Twitter-Login-Daten an. Sie können auch ein Facebook-Konto der Person im CRM-Modul finden und mit "Person / Firma bearbeiten" verknüpfen und Twitter-Newsfeedaktualisierungen durchschauen.
+
+ Erlauben Sie dieser App, Einloggen bei ONLYOFFICE über Twitter und Import von Twitter-Kontakten ins CRM-Modul zu ermöglichen. {0}Öffnen Sie das Twitter-Portal für Entwickler (Twitter Developer) und erstellen Sie eine neue App für die Integration mit ONLYOFFICE. Fügen Sie die erhaltenen Daten unten ein:
+
Twitter ID
@@ -476,6 +512,9 @@
Durch Hinzufügen der Yahoo-Dienstanwendung können Sie neue Benutzer des ONLYOFFICE-Portals aus der Kontaktliste hinzufügen.
+
+ Erlauben Sie dieser App, neue Portal-Benutzer aus Ihren Yahoo-Kontaktlisten hinzuzufügen. {0}Öffnen Sie die Seite Create Application (App erstellen) in Yahoo Developer Network und erstellen Sie eine neue App für die Integration mit ONLYOFFICE. Fügen Sie die erhaltenen Daten unten ein:
+
Yandex
diff --git a/web/ASC.Web.Core/PublicResources/Resource.fr.resx b/web/ASC.Web.Core/PublicResources/Resource.fr.resx
index b5fc8f9d6c..282c3541ad 100644
--- a/web/ASC.Web.Core/PublicResources/Resource.fr.resx
+++ b/web/ASC.Web.Core/PublicResources/Resource.fr.resx
@@ -103,6 +103,9 @@
Si vous ajoutez le service Bitly, vous pouvez inviter de nouveaux utilisateurs au portail ONLYOFFICE™ en utilisant les liens raccourcis. En plus, ces liens peuvent être utilisés pour les documents disponibles dans le module Documents et qui ont été partagés avec des utilisateurs externes.
+
+ Activez cette application pour raccourcir des liens d'invitations et de documents. {0}Insérez votre identifiant Bitly et votre clé API ci-dessous :
+
clé de Box
@@ -118,6 +121,9 @@
Si vous ajoutez une application du service Box, vous pouvez connecter votre compte Box au module Documents. Cela vous permet de télécharger et créer de nouveaux fichiers dans Box, modifier ceux qui existent déjà, copier et supprimer, partager des fichiers et des dossiers avec les utilisateurs du portail ONLYOFFICE™.
+
+ Activez cette application pour connecter votre compte Box au module Documents. Vous serez en mesure de gérer, éditer et partager les fichiers stockés sur Box avec les utilisateurs d'ONLYOFFICE. {0}Connectez-vous à votre compte Box, passez à la page pour les développeurs et créez une nouvelle appliction d'intégration pour ONLYOFFICE. Collez ci-dessous les données que vous venez de recevoir :
+
Clickatell
@@ -130,6 +136,9 @@
En ajoutant l'application du service Clickatell, vous serez en mesure d'activer l'authentification à deux facteurs et de recevoir un SMS avec un code permettant à l'utilisateur d'entrer dans le portail ONLYOFFICE.
+
+ Utilisez cette application pour activer l'authentification à deux facteurs en utilisant le service Clickatell. {0}Connectez-vous à votre compte de SMS Platform et créez une nouvelle intégration pour ONLYOFFICE. Copiez la clé apiKey et insérez-la ci-dessous :
+
DocuSign
@@ -148,6 +157,9 @@
Si vous ajoutez une application du service DocuSign vous pouvez signer des fichiers à partir du module Documents. Cela permet d’envoyer un fichier pour la signature électronique aux employés du portail ONLYOFFICE™ via le service DocuSugn. Le fichier signé sera sauvegardé dans le module Documents de ONLYOFFICE™.
+
+ Activez cette application pour signer les documents électroniquement via DocuSign. {0}Passez à votre console administrateur DocuSign et ajoutez l'intégration avec ONLYOFFICE. Collez ci-dessous les données que vous venez de recevoir :
+
Dropbox
@@ -157,6 +169,9 @@
Si vous ajoutez une application du service Dropbox, vous pouvez connecter votre compte Dropbox au module Documents. Cela permet de télécharger et créer de nouveaux fichiers dans Dropbox, modifier ceux qui existent déjà, copier et supprimer, partager des fichiers et des dossiers avec les utilisateurs du portail ONLYOFFICE™.
+
+ Activez cette application pour connecter votre compte Dropbox au module Documents. Vous serez en mesure de gérer, éditer et partager les fichiers stockés sur Dropbox avec les utilisateurs d'ONLYOFFICE. {0}Connectez-vous à votre compte Dropbox, passez à la page pour les développeurs et créez une nouvelle appliction d'intégration pour ONLYOFFICE. Collez ci-dessous les données que vous venez de recevoir :
+
ID de Dropbox
@@ -193,6 +208,9 @@
Si vous ajoutez une application du service Facebook, vous pouvez connecter votre compte Facebook sur votre page de profil en vue de l'utiliser pour accéder au portail ONLYOFFICE™. Cela vous permet également trouver un compte Facebook d’un contact dans le module CRM et le lier sur la page « Modifier personne/entreprise ».
+
+ Activez cette application pour permettre aux utilisateurs de se connecter à ONLYOFFICE via Facebook et relier les comptes Facebook des clients au module CRM. {0}Passez au portail des développeurs Facebook et créez une nouvelle application d'intégration ONLYOFFICE. Collez ci-dessous les données que vous venez de recevoir :
+
Firebase
@@ -247,6 +265,9 @@
En ajoutant un projet du service Google, vous pourrez connecter votre compte Google sur la page de votre profil en vue de l'utiliser pour l'accès au portail ONLYOFFICE™ et connecter votre compte Google Drive au module Documents. Cela vous permettra de télécharger et de créer de nouveaux fichiers dans Google Drive, modifier ceux qui existent déjà, copier et supprimer, partager des fichiers et des dossiers avec les utilisateurs du portail ONLYOFFICE™.
+
+ Activez cette application pour connecter votre compte Google Drive au module Documents. Vous serez en mesure de gérer, éditer et partager les fichiers stockés sur Google Drive avec les utilisateurs d'ONLYOFFICE. {0}Passez à la console Google APIs et créez un nouveau projet d'intégration avec ONLYOFFICE. Collez ci-dessous les données que vous venez de recevoir :
+
Clé de LinkedIn
@@ -256,6 +277,9 @@
Si vous ajoutez une application du service LinkedIn, vous pouvez connecter votre compte LinkedIn sur votre page de profil en vue de l'utiliser pour la connexion au portail ONLYOFFICE™.
+
+ Activez cette application pour permettre aux utilisateurs de se connecter à ONLYOFFICE via leurs comptes LinkedIn. {0}Passez au site web des développeurs LinkedIn et créez une nouvelle application d'intégration ONLYOFFICE. Collez ci-dessous les données que vous venez de recevoir :
+
ID de LinkedIn
@@ -370,6 +394,9 @@
Si vous ajoutez une application du service OneDrive, vous pouvez connecter votre compte de OneDrive au module Documents. Cela permet de télécharger et créer de nouveaux fichiers dans OneDrive, modifier ceux qui existent déjà, copier et supprimer, partager des fichiers et des dossiers avec les utilisateurs du portail ONLYOFFICE™.
+
+ Activez cette application pour connecter votre compte OneDrive au module Documents. Vous serez en mesure de gérer, éditer et partager vos fichiers stockés à OneDrive avec les utilisateurs ONLYOFFICE. {0}Connectez-vous à votre compte Microsoft Azure et créez une nouvelle application d'intégration pour ONLYOFFICE. Collez ci-dessous les données que vous venez de recevoir :
+
Centre SMS
@@ -379,6 +406,9 @@
En ajoutant l'application de service SMS Center, vous pourrez activer l'authentification à deux facteurs et recevoir un SMS avec un code permettant à l'utilisateur d'accéder au portail ONLYOFFICE. L'application SMS Center est utile en tant que fournisseur pour les pays de la CEI.
+
+ Utilisez cette application pour activer l'authentification à deux facteurs via le service SMS Center. {0}Insérez l'identifiant de votre compte smsc et votre mot de passe (ou le mot de passe MD5 hash) en caractères minuscules :
+
Login
@@ -400,6 +430,9 @@
Après avoir ajouté Twilio, vous pouvez appeler tout contaсt CRM depuis le navigateur.
+
+ Activez l'application pour permettre aux utilisateur de faire des appels directement depuis le module CRM en utilisant Twilio. {0}Passez à Twilio Console et collez ci-dessous les données suivantes :
+
Numéro de téléphone de Twilio (requis pour l'autorisation SMS)
@@ -418,6 +451,9 @@
Si vous ajoutez une application du service Twitter, vous pouvez connecter votre compte Twitter sur la page de votre profil en vue de l'utiliser pour la connexion au portail ONLYOFFICE™. Cela vous permet également de trouver un compte Twitter d’une personne dans le module CRM et le lier sur la page « Modifier personne/entreprise », et ensuite afficher le fil d'actualités sur Twitter.
+
+ Activez cette application pour permettre aux utilisateurs de se connecter à ONLYOFFICE via leur Twitter et reliez les comptes Twitter de vos clients à votre module CRM. {0}Passez au portail des développeurs Twitter et créez une nouvelle application d'intégration ONLYOFFICE. Collez ci-dessous les données que vous venez de recevoir :
+
ID de Twitter
@@ -472,6 +508,9 @@
En ajoutant l'application de service Yahoo, vous pourrez ajouter les nouveaux utilisateurs du portail ONLYOFFICE à partir de la liste de contacts.
+
+ Activez l'application pour ajouter les nouveaux utilisateurs au portail depuis votre liste de contacts Yahoo. {0}Sur la page Créer l'application passez à la section réservée aux développeurs Yahoo, créez une nouvelle application d'intégration pour ONLYOFFICE. Collez ci-dessous les données que vous venez de recevoir :
+
Yandex