Merge branch 'develop' into feature/thumbnails

# Conflicts:
#	products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesContent.js
#	products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesRow/SimpleFilesRow.js
#	products/ASC.Files/Client/src/components/pages/Home/Section/Body/FilesTileContent.js
#	products/ASC.Files/Client/src/store/index.js
This commit is contained in:
Artem Tarasov 2021-04-09 11:51:39 +03:00
commit f8b36757ae
122 changed files with 3693 additions and 1412 deletions

View File

@ -0,0 +1,46 @@
#!/bin/bash
SRC_PATH="/AppServer"
while [ "$1" != "" ]; do
case $1 in
-sp | --srcpath )
if [ "$2" != "" ]; then
SRC_PATH=$2
shift
fi
;;
-? | -h | --help )
echo " Usage: bash build-backend.sh [PARAMETER] [[PARAMETER], ...]"
echo " Parameters:"
echo " -sp, --srcpath path to AppServer root directory"
echo " -?, -h, --help this help"
echo " Examples"
echo " bash build-backend.sh -sp /app/AppServer"
exit 0
;;
* )
echo "Unknown parameter $1" 1>&2
exit 1
;;
esac
shift
done
echo "== BACK-END-BUILD =="
cd ${SRC_PATH}
dotnet restore ASC.Web.sln --configfile .nuget/NuGet.Config
dotnet build -r linux-x64 ASC.Web.sln
echo "== Build ASC.Thumbnails =="
yarn install --cwd common/ASC.Thumbnails --frozen-lockfile
echo "== Build ASC.UrlShortener =="
yarn install --cwd common/ASC.UrlShortener --frozen-lockfile
echo "== Build ASC.Socket.IO =="
yarn install --cwd common/ASC.Socket.IO --frozen-lockfile

View File

@ -0,0 +1,36 @@
#!/bin/bash
SRC_PATH="/AppServer"
while [ "$1" != "" ]; do
case $1 in
-sp | --srcpath )
if [ "$2" != "" ]; then
SRC_PATH=$2
shift
fi
;;
-? | -h | --help )
echo " Usage: bash build-backend.sh [PARAMETER] [[PARAMETER], ...]"
echo " Parameters:"
echo " -sp, --srcpath path to AppServer root directory"
echo " -?, -h, --help this help"
echo " Examples"
echo " bash build-backend.sh -sp /app/AppServer"
exit 0
;;
* )
echo "Unknown parameter $1" 1>&2
exit 1
;;
esac
shift
done
echo "== FRONT-END-BUILD =="
cd ${SRC_PATH}
yarn install

View File

@ -0,0 +1,114 @@
#!/bin/bash
SRC_PATH="/AppServer"
BUILD_PATH="/publish"
RID_ID="linux-x64"
SELF_CONTAINED="false"
ARGS=""
while [ "$1" != "" ]; do
case $1 in
-sp | --srcpath )
if [ "$2" != "" ]; then
SRC_PATH=$2
BUILD_PATH=${SRC_PATH}/publish
shift
fi
;;
-bp | --buildpath )
if [ "$2" != "" ]; then
BUILD_PATH=$2
shift
fi
;;
-ri | --runtime )
if [ "$2" != "" ]; then
RID_ID=$2
shift
fi
;;
-sc | --self-contained )
if [ "$2" != "" ]; then
SELF_CONTAINED=$2
shift
fi
;;
-ar | --arguments )
if [ "$2" != "" ]; then
ARGS=$2
shift
fi
;;
-? | -h | --help )
echo " Usage: bash publish-backend.sh [PARAMETER] [[PARAMETER], ...]"
echo " Parameters:"
echo " -sp, --srcpath path to AppServer root directory (by default=/AppServer)"
echo " -bp, --buildpath path where generated output is placed (by default=/publish)"
echo " -ri, --runtime RID ids for .NET runtime publish (by default=linux-x64)"
echo " -sc, --self-contained publish the .NET runtime with your application (by default=false)"
echo " -ar, --arguments additional arguments publish the .NET runtime with your application"
echo " -?, -h, --help this help"
echo " Examples"
echo " bash publish-backend.sh -sp /app/AppServer"
exit 0
;;
* )
echo "Unknown parameter $1" 1>&2
exit 1
;;
esac
shift
done
# Array of names server in directory products
servers_products_name_backend=(ASC.CRM)
servers_products_name_backend+=(ASC.Files)
servers_products_name_backend+=(ASC.People)
servers_products_name_backend+=(ASC.Projects)
# Publish server backend products
for i in ${!servers_products_name_backend[@]}; do
echo "== Publish ${servers_products_name_backend[$i]}.csproj project =="
SERVICE_DIR="$(dirname "$(find ${SRC_PATH} -type f -name "${servers_products_name_backend[$i]}".csproj)")"
cd ${SERVICE_DIR}
dotnet publish -c Release -r ${RID_ID} --self-contained ${SELF_CONTAINED} ${ARGS} -o ${BUILD_PATH}/products/${servers_products_name_backend[$i]}/server/
done
# Array of names backend services
services_name_backend=(ASC.ApiSystem)
services_name_backend+=(ASC.Data.Backup)
services_name_backend+=(ASC.Data.Storage.Encryption)
services_name_backend+=(ASC.Files.Service)
services_name_backend+=(ASC.Data.Storage.Migration)
services_name_backend+=(ASC.Notify)
services_name_backend+=(ASC.Socket.IO.Svc)
services_name_backend+=(ASC.Studio.Notify)
services_name_backend+=(ASC.TelegramService)
services_name_backend+=(ASC.Thumbnails.Svc)
services_name_backend+=(ASC.UrlShortener.Svc)
services_name_backend+=(ASC.Web.Api)
services_name_backend+=(ASC.Web.Studio)
# Publish backend services
for i in ${!services_name_backend[@]}; do
echo "== Publish ${services_name_backend[$i]}.csproj project =="
SERVICE_DIR="$(dirname "$(find ${SRC_PATH} -type f -name "${services_name_backend[$i]}".csproj)")"
cd ${SERVICE_DIR}
dotnet publish -c Release -r ${RID_ID} --self-contained ${SELF_CONTAINED} ${ARGS} -o ${BUILD_PATH}/services/${services_name_backend[$i]}/service/
done
# Array of names backend services in directory common (Nodejs)
services_name_frontend=(ASC.Thumbnails)
services_name_frontend+=(ASC.UrlShortener)
services_name_frontend+=(ASC.Socket.IO)
# Publish backend services (Nodejs)
for i in ${!services_name_frontend[@]}; do
echo "== Publish ${services_name_frontend[$i]} project =="
SERVICE_DIR="$(find ${SRC_PATH} -type d -name ${services_name_frontend[$i]})"
cd ${SERVICE_DIR}
mkdir -p ${BUILD_PATH}/services/${services_name_frontend[$i]}/service/ && cp -arfv ./* ${BUILD_PATH}/services/${services_name_frontend[$i]}/service/
done

View File

@ -2,11 +2,12 @@
PRODUCT=onlyoffice
REPO=${PRODUCT}
STATUS=""
SRV_VERSION=0.0.0
SRV_VERSION=latest
MYSQL_VERSION=8.0.18
ELK_VERSION=7.8.1
SERVICE_PORT=5050
CONTAINER_PREFIX=${PRODUCT}-
DOCKERFILE=Dockerfile-app
# zookeeper #
ZOO_PORT=2181
@ -34,7 +35,6 @@
DOCUMENT_SERVER_JWT_SECRET=your_jwt_secret
DOCUMENT_SERVER_JWT_HEADER=AuthorizationJwt
DOCUMENT_SERVER_URL_PUBLIC=/ds-vpath/
DOCUMENT_SERVER_URL_CONVERTER=/ds-vpath/ConvertService.ashx
DOCUMENT_SERVER_HOST=${CONTAINER_PREFIX}document-server
DOCUMENT_SERVER_URL_INTERNAL=http://${DOCUMENT_SERVER_HOST}/
@ -45,31 +45,42 @@
MYSQL_HOST=${CONTAINER_PREFIX}mysql-server
# service host #
API_HOST=${CONTAINER_PREFIX}api
API_SYSTEM_HOST=${CONTAINER_PREFIX}api_system
URLSHORTENER_HOST=${CONTAINER_PREFIX}urlshortener
STUDIO_NOTIFY_HOST=${CONTAINER_PREFIX}studio.notify
NOTIFY_HOST=${CONTAINER_PREFIX}notify
PEOPLE_SERVER_HOST=${CONTAINER_PREFIX}people.server
FILES_HOST=${CONTAINER_PREFIX}files
FILES_SERVICES_HOST=${CONTAINER_PREFIX}files_services
STUDIO_HOST=${CONTAINER_PREFIX}studio
API_SYSTEM_HOST=${CONTAINER_PREFIX}api-system
BACKUP_HOST=${CONTAINER_PREFIX}backup
THUMBNAILS_HOST=${CONTAINER_PREFIX}thumbnails
CRM_HOST=${CONTAINER_PREFIX}crm
STORAGE_ENCRYPTION_HOST=${CONTAINER_PREFIX}storage-encryption
FILES_HOST=${CONTAINER_PREFIX}files
FILES_SERVICES_HOST=${CONTAINER_PREFIX}files-services
STORAGE_MIGRATION_HOST=${CONTAINER_PREFIX}storage-migration
NOTIFY_HOST=${CONTAINER_PREFIX}notify
PEOPLE_SERVER_HOST=${CONTAINER_PREFIX}people-server
PROJECTS_SERVER_HOST=${CONTAINER_PREFIX}projects-server
SOCKET_HOST=${CONTAINER_PREFIX}socket
STUDIO_NOTIFY_HOST=${CONTAINER_PREFIX}studio-notify
TELEGRAM_SERVICE_HOST=${CONTAINER_PREFIX}telegram-service
THUMBNAILS_HOST=${CONTAINER_PREFIX}thumbnails
URLSHORTENER_HOST=${CONTAINER_PREFIX}urlshortener
API_HOST=${CONTAINER_PREFIX}api
STUDIO_HOST=${CONTAINER_PREFIX}studio
PROXY_HOST=${CONTAINER_PREFIX}proxy
# proxy upstream environment #
SERVICE_API=${API_HOST}:${SERVICE_PORT}
SERVICE_API_SYSTEM=${API_SYSTEM_HOST}:${SERVICE_PORT}
SERVICE_URLSHORTENER=${URLSHORTENER_HOST}:${SERVICE_PORT}
SERVICE_STUDIO_NOTIFY=${STUDIO_NOTIFY_HOST}:${SERVICE_PORT}
SERVICE_PEOPLE_SERVER=${PEOPLE_SERVER_HOST}:${SERVICE_PORT}
SERVICE_BACKUP=${BACKUP_HOST}:${SERVICE_PORT}
SERVICE_CRM=${CRM_HOST}:${SERVICE_PORT}
SERVICE_STORAGE_ENCRYPTION=${STORAGE_ENCRYPTION_HOST}:${SERVICE_PORT}
SERVICE_FILES=${FILES_HOST}:${SERVICE_PORT}
SERVICE_FILES_SERVICES=${FILES_SERVICES_HOST}:${SERVICE_PORT}
SERVICE_STORAGE_MIGRATION=${STORAGE_MIGRATION_HOST}:${SERVICE_PORT}
SERVICE_NOTIFY=${NOTIFY_HOST}:${SERVICE_PORT}
SERVICE_PEOPLE_SERVER=${PEOPLE_SERVER_HOST}:${SERVICE_PORT}
SERVICE_PROJECTS_SERVER=${PROJECTS_SERVER_HOST}:${SERVICE_PORT}
SERVICE_SOCKET=${SOCKET_HOST}:9899
SERVICE_STUDIO_NOTIFY=${STUDIO_NOTIFY_HOST}:${SERVICE_PORT}
SERVICE_TELEGRAM_SERVICE=${TELEGRAM_SERVICE_HOST}:${SERVICE_PORT}
SERVICE_THUMBNAILS=${THUMBNAILS_HOST}:9800
SERVICE_URLSHORTENER=${URLSHORTENER_HOST}:9999
SERVICE_API=${API_HOST}:${SERVICE_PORT}
SERVICE_STUDIO=${STUDIO_HOST}:${SERVICE_PORT}
SERVICE_BACKUP=${BACKUP_HOST}:${SERVICE_PORT}
SERVICE_THUMBNAILS=${THUMBNAILS_HOST}:${SERVICE_PORT}
SERVICE_SH=${URLSHORTENER_HOST}:9999
NETWORK_NAME=${PRODUCT}

View File

@ -1,10 +1,14 @@
### STAGE 1: Develop ######
FROM ubuntu:18.04 AS develop
ARG SRC_PATH="/app/onlyoffice/src"
ARG BUILD_PATH="/var/www"
FROM ubuntu:20.10 AS develop
ARG RELEASE_DATE="2016-06-21"
ARG VERSION="8.9.0.190"
ARG DEBIAN_FRONTEND=noninteractive
ARG GIT_BRANCH="master"
ARG SRC_PATH
ARG BUILD_PATH
LABEL onlyoffice.appserver.release-date="${RELEASE_DATE}" \
onlyoffice.appserver.version="${VERSION}" \
@ -28,135 +32,35 @@ RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
apt-get install -y nodejs && \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list && \
wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb && \
wget https://packages.microsoft.com/config/ubuntu/20.10/packages-microsoft-prod.deb -O packages-microsoft-prod.deb && \
dpkg -i packages-microsoft-prod.deb && \
apt-get -y update && \
apt-get install -y apt-transport-https && \
apt-get install -y apt-utils &&\
apt-get -y update && \
cd ~ && \
echo "#!/bin/sh\nexit 0" > /usr/sbin/policy-rc.d && \
apt-get install -yq git \
yarn \
dotnet-sdk-3.1
dotnet-sdk-5.0
RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
git clone --depth 1 -b ${GIT_BRANCH} https://github.com/ONLYOFFICE/AppServer.git /app/onlyoffice/src/
echo ${GIT_BRANCH} && \
git clone --depth 1 -b ${GIT_BRANCH} https://github.com/ONLYOFFICE/AppServer.git ${SRC_PATH}
RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
cd /app/onlyoffice/src/ && \
yarn install --cwd web/ASC.Web.Components --frozen-lockfile > build/ASC.Web.Components.log && \
yarn pack --cwd web/ASC.Web.Components
RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
cd /app/onlyoffice/src/ && \
component=$(ls web/ASC.Web.Components/asc-web-components-v1.*.tgz) && \
yarn remove asc-web-components --cwd web/ASC.Web.Common --peer && \
yarn add file:../../$component --cwd web/ASC.Web.Common --cache-folder ../../yarn --peer && \
yarn install --cwd web/ASC.Web.Common --frozen-lockfile > build/ASC.Web.Common.log && \
yarn pack --cwd web/ASC.Web.Common
RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
cd /app/onlyoffice/src/ && \
npm run build:storybook --prefix web/ASC.Web.Components && \
mkdir -p /var/www/story/ && \
cp -Rf web/ASC.Web.Components/storybook-static/* /var/www/story/
RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
cd /app/onlyoffice/src/ && \
component=$(ls web/ASC.Web.Components/asc-web-components-v1.*.tgz) && \
common=$(ls web/ASC.Web.Common/asc-web-common-v1.*.tgz) && \
yarn remove asc-web-components asc-web-common --cwd web/ASC.Web.Client && \
yarn add ../../$component --cwd web/ASC.Web.Client --cache-folder ../../yarn && \
yarn add ../../$common --cwd web/ASC.Web.Client --cache-folder ../../yarn && \
yarn install --cwd web/ASC.Web.Client --frozen-lockfile || (cd web/ASC.Web.Client && npm i && cd ../../) && \
npm run build --prefix web/ASC.Web.Client && \
rm -rf /var/www/studio/client/* && \
mkdir -p /var/www/studio/client && \
cp -rf web/ASC.Web.Client/build/* /var/www/studio/client
RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
cd /app/onlyoffice/src/ && \
component=$(ls web/ASC.Web.Components/asc-web-components-v1.*.tgz) && \
common=$(ls web/ASC.Web.Common/asc-web-common-v1.*.tgz) && \
yarn remove asc-web-components asc-web-common --cwd products/ASC.Files/Client && \
yarn add ../../../$component --cwd products/ASC.Files/Client --cache-folder ../../../yarn && \
yarn add ../../../$common --cwd products/ASC.Files/Client --cache-folder ../../../yarn && \
yarn install --cwd products/ASC.Files/Client --frozen-lockfile || (cd products/ASC.Files/Client && npm i && cd ../../../) && \
npm run build --prefix products/ASC.Files/Client && \
mkdir -p /var/www/products/ASC.Files/client && \
cp -Rf products/ASC.Files/Client/build/* /var/www/products/ASC.Files/client && \
mkdir -p /var/www/products/ASC.Files/client/products/files
RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
cd /app/onlyoffice/src/ && \
component=$(ls web/ASC.Web.Components/asc-web-components-v1.*.tgz) && \
common=$(ls web/ASC.Web.Common/asc-web-common-v1.*.tgz) && \
yarn remove asc-web-components asc-web-common --cwd products/ASC.People/Client && \
yarn add ../../../$component --cwd products/ASC.People/Client --cache-folder ../../../yarn && \
yarn add ../../../$common --cwd products/ASC.People/Client --cache-folder ../../../yarn && \
yarn install --cwd products/ASC.People/Client --frozen-lockfile || (cd products/ASC.People/Client && npm i && cd ../../../) && \
npm run build --prefix products/ASC.People/Client && \
mkdir -p /var/www/products/ASC.People/client && \
cp -Rf products/ASC.People/Client/build/* /var/www/products/ASC.People/client && \
mkdir -p /var/www/products/ASC.People/client/products/people
RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
cd /app/onlyoffice/src/ && \
#rm -f /etc/nginx/conf.d/* && \
mkdir -p /etc/nginx/conf.d/ && \
mkdir -p /var/www/public/ && cp -f public/* /var/www/public/ && \
cd ${SRC_PATH} && \
mkdir -p /var/www/public/ && cp -rf public/* /var/www/public/ && \
mkdir -p /app/onlyoffice/config/ && cp -rf config/* /app/onlyoffice/config/ && \
cp -f config/nginx/onlyoffice*.conf /etc/nginx/conf.d/ && \
mkdir -p /etc/nginx/conf.d && cp -f config/nginx/onlyoffice*.conf /etc/nginx/conf.d/ && \
mkdir -p /etc/nginx/includes/ && cp -f config/nginx/includes/onlyoffice*.conf /etc/nginx/includes/ && \
sed -e 's/#//' -i /etc/nginx/conf.d/onlyoffice.conf && \
dotnet restore ASC.Web.sln --configfile .nuget/NuGet.Config && \
dotnet build -r linux-x64 ASC.Web.sln && \
cd products/ASC.People/Server && \
dotnet -d publish --no-build --self-contained -r linux-x64 -o /var/www/products/ASC.People/server && \
cd ../../../ && \
cd products/ASC.Files/Server && \
dotnet -d publish --no-build --self-contained -r linux-x64 -o /var/www/products/ASC.Files/server && \
cp -avrf DocStore /var/www/products/ASC.Files/server/ && \
cd ../../../ && \
cd products/ASC.Files/Service && \
dotnet add ASC.Files.Service.csproj reference ../../ASC.People/Server/ASC.People.csproj ../Server/ASC.Files.csproj && \
dotnet -d publish --no-build --self-contained -r linux-x64 -o /var/www/products/ASC.Files/service && \
cd ../../../ && \
cd web/ASC.Web.Api && \
dotnet -d publish --no-build --self-contained -r linux-x64 -o /var/www/studio/api && \
cd ../../ && \
cd web/ASC.Web.Studio && \
dotnet -d publish --no-build --self-contained -r linux-x64 -o /var/www/studio/server && \
cd ../../ && \
cd common/services/ASC.Data.Backup && \
dotnet -d publish --no-build --self-contained -r linux-x64 -o /var/www/services/backup && \
cd ../../../ && \
cd common/services/ASC.Notify && \
dotnet -d publish --no-build --self-contained -r linux-x64 -o /var/www/services/notify && \
cd ../../../ && \
cd common/services/ASC.ApiSystem && \
dotnet -d publish --no-build --self-contained -r linux-x64 -o /var/www/services/apisystem && \
cd ../../../ && \
cd common/services/ASC.Thumbnails.Svc && \
dotnet -d publish --no-build --self-contained -r linux-x64 -o /services/thumb/service && \
cd ../../../ && \
yarn install --cwd common/ASC.Thumbnails --frozen-lockfile && \
mkdir -p /var/www/services/thumb/client && cp -Rf common/ASC.Thumbnails/* /var/www/services/thumb/client && \
cd common/services/ASC.UrlShortener.Svc && \
dotnet -d publish --no-build --self-contained -r linux-x64 -o /services/urlshortener/service && \
cd ../../../ && \
yarn install --cwd common/ASC.UrlShortener --frozen-lockfile && \
mkdir -p /var/www/services/urlshortener/client && cp -Rf common/ASC.UrlShortener/* /var/www/services/urlshortener/client && \
cd common/services/ASC.Socket.IO.Svc && \
dotnet -d publish --no-build --self-contained -r linux-x64 -o /services/socket/service && \
cd ../../../ && \
yarn install --cwd common/ASC.Socket.IO --frozen-lockfile && \
mkdir -p /var/www/services/socket/client && cp -Rf common/ASC.Socket.IO/* /var/www/services/socket/client && \
cd common/services/ASC.Studio.Notify && \
dotnet add ASC.Studio.Notify.csproj reference ../../../products/ASC.People/Server/ASC.People.csproj ../../../products/ASC.Files/Server/ASC.Files.csproj && \
dotnet -d publish --no-build --self-contained -r linux-x64 -o /var/www/services/studio.notify
cd ${SRC_PATH}/build/install/common/ && \
bash build-frontend.sh -sp ${SRC_PATH} && \
cd ${SRC_PATH} && yarn build && cd ${SRC_PATH}/build/install/common/ && \
bash build-backend.sh -sp ${SRC_PATH} && \
bash publish-backend.sh -sp ${SRC_PATH} -bp ${BUILD_PATH} -ar "--disable-parallel"
COPY config/mysql/conf.d/mysql.cnf /etc/mysql/conf.d/mysql.cnf
COPY config/supervisor/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
@ -165,29 +69,29 @@ RUN sed -i 's/Server=.*;Port=/Server=127.0.0.1;Port=/' /app/onlyoffice/config/ap
RUN rm -rf /var/lib/apt/lists/*
### STAGE 2: Build ###
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 as builder
FROM mcr.microsoft.com/dotnet/aspnet:5.0.4-focal-amd64 as builder
ARG BUILD_PATH
ENV BUILD_PATH=${BUILD_PATH}
COPY --from=develop /app/onlyoffice/config/ /app/onlyoffice/config/
# add defualt user and group for no-root run
RUN mkdir -p /var/log/onlyoffice && \
mkdir -p /app/onlyoffice/data && \
mkdir -p /var/www/services/backup && \
addgroup --system --gid 107 onlyoffice && \
adduser -uid 104 --quiet --home /var/www/onlyoffice --system --gid 107 onlyoffice && \
chown onlyoffice:onlyoffice /app/onlyoffice -R && \
chown onlyoffice:onlyoffice /var/log -R && \
chown onlyoffice:onlyoffice /var/www -R
RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
chown onlyoffice:onlyoffice /var/www -R
RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
apt-get -y update && \
apt-get -y upgrade && \
apt-get install -yq nano &&\
apt-get install -yq jq &&\
apt-get install -yq nodejs &&\
apt-get install -yq nano && \
apt-get install -yq jq && \
apt-get install -yq nodejs && \
apt-get install -yq libgdiplus
#USER onlyoffice
#USER onlyoffice
EXPOSE 5050
ENTRYPOINT ["./docker-entrypoint.sh"]
@ -195,172 +99,201 @@ ENTRYPOINT ["./docker-entrypoint.sh"]
### STAGE 3: Run ###
## NGINX ##
FROM nginx:stable-alpine AS web
FROM nginx AS web
ARG SRC_PATH
ARG BUILD_PATH
# Remove default nginx website
RUN rm -rf /usr/share/nginx/html/*
RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
apt-get -y update && \
apt-get -y upgrade && \
apt-get install -yq vim && \
# Remove default nginx website
rm -rf /usr/share/nginx/html/*
# copy artefacts and config values for nginx
# copy static services files and config values
COPY --from=develop /etc/nginx/conf.d /etc/nginx/conf.d
COPY --from=develop /etc/nginx/includes /etc/nginx/includes
COPY --from=develop /var/www/story /var/www/story
COPY --from=develop /var/www/products/ASC.Files/client /var/www/products/ASC.Files/client
COPY --from=develop /var/www/products/ASC.People/client /var/www/products/ASC.People/client
COPY --from=develop /var/www/public /var/www/public
COPY --from=develop /var/www/studio/client /var/www/studio/client
COPY --from=develop ${SRC_PATH}/products/ASC.CRM/Client/dist ${BUILD_PATH}/products/ASC.CRM/client
COPY --from=develop ${SRC_PATH}/web/ASC.Web.Editor/dist ${BUILD_PATH}/products/ASC.Files/editor
COPY --from=develop ${SRC_PATH}/products/ASC.Files/Client/dist ${BUILD_PATH}/products/ASC.Files/client
COPY --from=develop ${SRC_PATH}/web/ASC.Web.Login/dist ${BUILD_PATH}/studio/login
COPY --from=develop ${SRC_PATH}/products/ASC.People/Client/dist ${BUILD_PATH}/products/ASC.People/client
COPY --from=develop ${SRC_PATH}/products/ASC.Projects/Client/dist ${BUILD_PATH}/products/ASC.Projects/client
COPY --from=develop ${SRC_PATH}/web/ASC.Web.Client/dist ${BUILD_PATH}/studio/client
COPY /config/nginx/templates/upstream.conf.template /etc/nginx/templates/upstream.conf.template
# add defualt user and group for no-root run
RUN chown nginx:nginx /etc/nginx/* -R &&\
chown nginx:nginx /docker-entrypoint.d/* &&\
RUN chown nginx:nginx /etc/nginx/* -R && \
chown nginx:nginx /docker-entrypoint.d/* && \
# changes for upstream configure
sed -i 's/localhost:5000/$service_api/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5010/$service_api_system/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5004/$service_people_server/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5007/$service_files/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5003/$service_studio/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5012/$service_backup/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:9999/$service_sh/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5021/$service_crm/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5007/$service_files/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5004/$service_people_server/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5020/$service_projects_server/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5000/$service_api/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5003/$service_studio/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:9999/$service_urlshortener/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/172.*/$document_server;/' /etc/nginx/conf.d/onlyoffice.conf && \
# configute the image nginx whith less privileged https://hub.docker.com/_/nginx
sed -i 's/pid.*nginx.pid;/pid \/tmp\/nginx.pid;/' /etc/nginx/nginx.conf && \
sed -i 's/http.*{/http {\n client_body_temp_path \/tmp\/client_temp;\n proxy_temp_path \/tmp\/proxy_temp_path;\n fastcgi_temp_path \/tmp\/fastcgi_temp;\n uwsgi_temp_path \/tmp\/uwsgi_temp;\n scgi_temp_path \/tmp\/scgi_temp;/' /etc/nginx/nginx.conf
## backup ##
FROM builder AS backup
WORKDIR /var/www/services/backup/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/services/backup/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ASC.People.dll /var/www/products/ASC.People/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ASC.Files*.dll /var/www/products/ASC.Files/server/
CMD ["ASC.Data.Backup.dll", "backup", "core:products:folder=/var/www/products/", "core:products:subfolder=server"]
## api ##
FROM builder AS api
WORKDIR /var/www/studio/api/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/studio/api .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ASC.People.dll /var/www/products/ASC.People/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ASC.Files*.dll /var/www/products/ASC.Files/server/
CMD ["ASC.Web.Api.dll", "api"]
## api_system ##
## ASC.ApiSystem ##
FROM builder AS api_system
WORKDIR /var/www/services/apisystem/
WORKDIR ${BUILD_PATH}/services/apisystem/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/services/apisystem/ .
COPY --from=develop --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.ApiSystem/service .
CMD ["ASC.ApiSystem.dll", "api_system"]
CMD ["ASC.ApiSystem.dll", "ASC.ApiSystem"]
## urlshortener ##
FROM builder AS urlshortener
WORKDIR /services/urlshortener/service/
## ASC.Data.Backup ##
FROM builder AS backup
WORKDIR ${BUILD_PATH}/services/backup/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /services/urlshortener/service/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/services/urlshortener/client /services/urlshortener/client
CMD ["ASC.UrlShortener.Svc.dll", "urlshortener"]
COPY --from=develop --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.Data.Backup/service .
CMD ["ASC.Data.Backup.dll", "ASC.Data.Backup", "core:products:folder=/var/www/products/", "core:products:subfolder=server"]
## studio.notify ##
FROM builder AS studio.notify
WORKDIR /var/www/services/studio.notify/
## ASC.CRM ##
FROM builder AS crm
WORKDIR ${BUILD_PATH}/products/ASC.CRM/server/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop /var/www/services/studio.notify/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ASC.People.dll /var/www/products/ASC.People/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ASC.Files*.dll /var/www/products/ASC.Files/server/
COPY --from=develop --chown=onlyoffice:onlyoffice ${BUILD_PATH}/products/ASC.CRM/server/ .
CMD ["ASC.Studio.Notify.dll", "studio.notify", "core:products:folder=/var/www/products/", "core:products:subfolder=server"]
CMD ["ASC.CRM.dll", "ASC.CRM"]
## notify ##
FROM builder AS notify
WORKDIR /var/www/services/notify/
## ASC.Data.Storage.Encryption ##
FROM builder AS data_storage_encryption
WORKDIR ${BUILD_PATH}/services/storage.encryption/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop /var/www/services/notify/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ASC.People.dll /var/www/products/ASC.People/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ASC.Files*.dll /var/www/products/ASC.Files/server/
COPY --from=develop --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.Data.Storage.Encryption/service/ .
CMD ["ASC.Notify.dll", "notify", "core:products:folder=/var/www/products/", "core:products:subfolder=server"]
CMD ["ASC.Data.Storage.Encryption.dll", "ASC.Data.Storage.Encryption"]
## people.server ##
FROM builder AS people.server
WORKDIR /var/www/products/ASC.People/server/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ASC.Files*.dll /var/www/products/ASC.Files/server/
CMD ["ASC.People.dll", "people.server"]
## files ##
## ASC.Files ##
FROM builder AS files
WORKDIR /var/www/products/ASC.Files/server/
WORKDIR ${BUILD_PATH}/products/ASC.Files/server/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ASC.People.dll /var/www/products/ASC.People/server/
COPY --from=develop --chown=onlyoffice:onlyoffice ${BUILD_PATH}/products/ASC.Files/server/ .
CMD ["ASC.Files.dll", "files"]
CMD ["ASC.Files.dll", "ASC.Files"]
## files_services ##
## ASC.Files.Service ##
FROM builder AS files_services
WORKDIR /var/www/products/ASC.Files/service/
WORKDIR ${BUILD_PATH}/products/ASC.Files/service/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/service/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ASC.Files*.dll /var/www/products/ASC.Files/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ASC.People*.dll /var/www/products/ASC.People/server/
COPY --from=develop --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.Files.Service/service/ .
CMD ["ASC.Files.Service.dll", "files_services", "core:products:folder=/var/www/products/", "core:products:subfolder=server"]
CMD ["ASC.Files.Service.dll", "ASC.Files.Service", "core:products:folder=/var/www/products/", "core:products:subfolder=server"]
## studio ##
FROM builder AS studio
WORKDIR /var/www/studio/server/
## ASC.Data.Storage.Migration ##
FROM builder AS data_storage_migration
WORKDIR ${BUILD_PATH}/services/storage.migration/service/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/studio/server/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ASC.Files*.dll /var/www/products/ASC.Files/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ASC.People.dll /var/www/products/ASC.People/server/
COPY --from=develop --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.Data.Storage.Migration/service/ .
CMD ["ASC.Web.Studio.dll", "studio"]
CMD ["ASC.Data.Storage.Migration.dll", "ASC.Data.Storage.Migration"]
## thumbnails ##
FROM builder AS thumbnails
WORKDIR /services/thumbnails/service
## ASC.Notify ##
FROM builder AS notify
WORKDIR ${BUILD_PATH}/services/notify/service
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /services/thumb/service/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/services/thumb/client /services/thumbnails/client
COPY --from=develop --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.Notify/service/ .
CMD ["ASC.Thumbnails.Svc.dll", "thumbnails"]
CMD ["ASC.Notify.dll", "ASC.Notify", "core:products:folder=/var/www/products/", "core:products:subfolder=server"]
## socket ##
## ASC.People ##
FROM builder AS people_server
WORKDIR ${BUILD_PATH}/products/ASC.People/server/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice ${BUILD_PATH}/products/ASC.People/server/ .
CMD ["ASC.People.dll", "ASC.People"]
## ASC.Projects ##
FROM builder AS projects_server
WORKDIR ${BUILD_PATH}/products/ASC.Projects/server/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice ${BUILD_PATH}/products/ASC.Projects/server/ .
CMD ["ASC.Projects.dll", "ASC.Projects"]
## ASC.Socket.IO.Svc ##
FROM builder AS socket
WORKDIR /services/socket/service
WORKDIR ${BUILD_PATH}/services/socket/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /services/socket/service/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/services/socket/client /services/ASC.Socket.IO
COPY --from=develop --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.Socket.IO.Svc/service/ .
COPY --from=develop --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.Socket.IO/service/ ${BUILD_PATH}/www/ASC.Socket.IO/
CMD ["ASC.Socket.IO.Svc.dll", "socket"]
CMD ["ASC.Socket.IO.Svc.dll", "ASC.Socket.IO.Svc"]
## ASC.Studio.Notify ##
FROM builder AS studio_notify
WORKDIR ${BUILD_PATH}/services/studio.notify/service/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.Studio.Notify/service/ .
CMD ["ASC.Studio.Notify.dll", "ASC.Studio.Notify", "core:products:folder=/var/www/products/", "core:products:subfolder=server"]
## ASC.TelegramService ##
FROM builder AS telegram_service
WORKDIR ${BUILD_PATH}/services/telegram/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.TelegramService/service/ .
CMD ["ASC.TelegramService.dll", "ASC.TelegramService"]
## ASC.Thumbnails.Svc ##
FROM builder AS thumbnails
WORKDIR ${BUILD_PATH}/services/thumb/service/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.Thumbnails.Svc/service/ .
COPY --from=develop --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.Thumbnails/service/ /var/www/services/thumb/client
CMD ["ASC.Thumbnails.Svc.dll", "ASC.Thumbnails.Svc"]
## ASC.UrlShortener.Svc ##
FROM builder AS urlshortener
WORKDIR ${BUILD_PATH}/services/urlshortener/service/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.UrlShortener.Svc/service/ .
COPY --from=develop --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.UrlShortener/service/ /var/www/services/urlshortener/client
CMD ["ASC.UrlShortener.Svc.dll", "ASC.UrlShortener.Svc"]
## ASC.Web.Api ##
FROM builder AS api
WORKDIR ${BUILD_PATH}/studio/api/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.Web.Api/service/ .
CMD ["ASC.Web.Api.dll", "ASC.Web.Api"]
## ASC.Web.Studio ##
FROM builder AS studio
WORKDIR ${BUILD_PATH}/studio/server/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice ${BUILD_PATH}/services/ASC.Web.Studio/service/ .
CMD ["ASC.Web.Studio.dll", "ASC.Web.Studio"]

View File

@ -0,0 +1,366 @@
### STAGE 1: Develop ######
FROM ubuntu:20.10 AS develop
ARG RELEASE_DATE="2016-06-21"
ARG VERSION="8.9.0.190"
ARG DEBIAN_FRONTEND=noninteractive
ARG GIT_BRANCH="master"
ARG SRC_PATH="/app/onlyoffice/src"
LABEL onlyoffice.appserver.release-date="${RELEASE_DATE}" \
onlyoffice.appserver.version="${VERSION}" \
maintainer="Ascensio System SIA <support@onlyoffice.com>"
ENV LANG=en_US.UTF-8 \
LANGUAGE=en_US:en \
LC_ALL=en_US.UTF-8
RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
apt-get -y update && \
apt-get -y upgrade && \
apt-get -y dist-upgrade && \
apt-get install -yq sudo locales && \
addgroup --system --gid 107 onlyoffice && \
adduser -uid 104 --quiet --home /var/www/onlyoffice --system --gid 107 onlyoffice && \
locale-gen en_US.UTF-8 && \
apt-get -y update && \
apt-get install -yq software-properties-common wget curl && \
curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - && \
apt-get install -y nodejs && \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list && \
wget https://packages.microsoft.com/config/ubuntu/20.10/packages-microsoft-prod.deb -O packages-microsoft-prod.deb && \
dpkg -i packages-microsoft-prod.deb && \
apt-get -y update && \
apt-get install -y apt-transport-https && \
apt-get install -y apt-utils &&\
apt-get -y update && \
cd ~ && \
echo "#!/bin/sh\nexit 0" > /usr/sbin/policy-rc.d && \
apt-get install -yq git \
yarn \
dotnet-sdk-5.0
RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
echo ${GIT_BRANCH} && \
git clone --depth 1 -b ${GIT_BRANCH} https://github.com/ONLYOFFICE/AppServer.git ${SRC_PATH}
RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
cd ${SRC_PATH} && \
mkdir -p /var/www/public/ && cp -rf public/* /var/www/public/ && \
mkdir -p /app/onlyoffice/config/ && cp -rf config/* /app/onlyoffice/config/ && \
mkdir -p /etc/nginx/conf.d && cp -f config/nginx/onlyoffice*.conf /etc/nginx/conf.d/ && \
mkdir -p /etc/nginx/includes/ && cp -f config/nginx/includes/onlyoffice*.conf /etc/nginx/includes/ && \
sed -e 's/#//' -i /etc/nginx/conf.d/onlyoffice.conf && \
cd ${SRC_PATH}/build/install/common/ && \
bash build-frontend.sh -sp ${SRC_PATH} && \
cd ${SRC_PATH} && yarn build && cd ${SRC_PATH}/build/install/common/ && \
bash build-backend.sh -sp ${SRC_PATH} && \
bash publish-backend.sh -sp ${SRC_PATH} -bp ${BUILD_PATH} -ar "--disable-parallel"
COPY config/mysql/conf.d/mysql.cnf /etc/mysql/conf.d/mysql.cnf
COPY config/supervisor/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
RUN sed -i 's/Server=.*;Port=/Server=127.0.0.1;Port=/' /app/onlyoffice/config/appsettings.test.json
RUN rm -rf /var/lib/apt/lists/*
### STAGE 2: Build ###
FROM mcr.microsoft.com/dotnet/aspnet:5.0.4-focal-amd64 as builder
COPY --from=develop /app/onlyoffice/config/ /app/onlyoffice/config/
# add defualt user and group for no-root run
RUN mkdir -p /var/log/onlyoffice && \
mkdir -p /app/onlyoffice/data && \
addgroup --system --gid 107 onlyoffice && \
adduser -uid 104 --quiet --home /var/www/onlyoffice --system --gid 107 onlyoffice && \
chown onlyoffice:onlyoffice /app/onlyoffice -R && \
chown onlyoffice:onlyoffice /var/log -R && \
chown onlyoffice:onlyoffice /var/www -R
RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
apt-get -y update && \
apt-get -y upgrade && \
apt-get install -yq nano &&\
apt-get install -yq jq &&\
apt-get install -yq nodejs &&\
apt-get install -yq libgdiplus
#USER onlyoffice
EXPOSE 5050
ENTRYPOINT ["./docker-entrypoint.sh"]
### STAGE 3: Run ###
## NGINX ##
#FROM nginx:stable-alpine AS web
FROM nginx AS web
ARG SRC_PATH="/app/onlyoffice/src"
RUN echo "nameserver 8.8.8.8" | tee /etc/resolv.conf > /dev/null && \
apt-get -y update && \
apt-get -y upgrade && \
apt-get install -yq vim && \
# Remove default nginx website
rm -rf /usr/share/nginx/html/*
# copy static services files and config values
COPY --from=develop /etc/nginx/conf.d /etc/nginx/conf.d
COPY --from=develop /etc/nginx/includes /etc/nginx/includes
COPY --from=develop /var/www/public /var/www/public
COPY --from=develop ${SRC_PATH}/products/ASC.CRM/Client/dist /var/www/products/ASC.CRM/client
COPY --from=develop ${SRC_PATH}/web/ASC.Web.Editor/dist /var/www/products/ASC.Files/editor
COPY --from=develop ${SRC_PATH}/products/ASC.Files/Client/dist /var/www/products/ASC.Files/client
COPY --from=develop ${SRC_PATH}/web/ASC.Web.Login/dist /var/www/studio/login
COPY --from=develop ${SRC_PATH}/products/ASC.People/Client/dist /var/www/products/ASC.People/client
COPY --from=develop ${SRC_PATH}/products/ASC.Projects/Client/dist /var/www/products/ASC.Projects/client
COPY --from=develop ${SRC_PATH}/web/ASC.Web.Client/dist /var/www/studio/client
COPY /config/nginx/templates/upstream.conf.template /etc/nginx/templates/upstream.conf.template
# add defualt user and group for no-root run
RUN chown nginx:nginx /etc/nginx/* -R &&\
chown nginx:nginx /docker-entrypoint.d/* &&\
# changes for upstream configure
sed -i 's/localhost:5010/$service_api_system/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5012/$service_backup/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5021/$service_crm/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5007/$service_files/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5004/$service_people_server/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5020/$service_projects_server/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5000/$service_api/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:5003/$service_studio/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/localhost:9999/$service_urlshortener/' /etc/nginx/conf.d/onlyoffice.conf && \
sed -i 's/172.*/$document_server;/' /etc/nginx/conf.d/onlyoffice.conf && \
# configute the image nginx whith less privileged https://hub.docker.com/_/nginx
sed -i 's/pid.*nginx.pid;/pid \/tmp\/nginx.pid;/' /etc/nginx/nginx.conf && \
sed -i 's/http.*{/http {\n client_body_temp_path \/tmp\/client_temp;\n proxy_temp_path \/tmp\/proxy_temp_path;\n fastcgi_temp_path \/tmp\/fastcgi_temp;\n uwsgi_temp_path \/tmp\/uwsgi_temp;\n scgi_temp_path \/tmp\/scgi_temp;/' /etc/nginx/nginx.conf
## ASC.ApiSystem ##
FROM builder AS api_system
WORKDIR /var/www/services/apisystem/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/services/apisystem/ .
CMD ["ASC.ApiSystem.dll", "ASC.ApiSystem"]
## ASC.Data.Backup ##
FROM builder AS backup
WORKDIR /var/www/services/backup/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/services/backup/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ASC.People.dll /var/www/products/ASC.People/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ASC.Files*.dll /var/www/products/ASC.Files/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.CRM/server/ASC.CRM*.dll /var/www/products/ASC.CRM/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Projects/server/ASC.Projects*.dll /var/www/products/ASC.Projects/server/
CMD ["ASC.Data.Backup.dll", "ASC.Data.Backup", "core:products:folder=/var/www/products/", "core:products:subfolder=server"]
## ASC.CRM ##
FROM builder AS crm
WORKDIR /var/www/products/ASC.CRM/server/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.CRM/server/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ASC.Files*.dll /var/www/products/ASC.Files/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ASC.People.dll /var/www/products/ASC.People/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.CRM/server/ASC.CRM*.dll /var/www/products/ASC.CRM/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Projects/server/ASC.Projects*.dll /var/www/products/ASC.Projects/server/
CMD ["ASC.CRM.dll", "ASC.CRM"]
## ASC.Data.Storage.Encryption ##
FROM builder AS data_storage_encryption
WORKDIR /var/www/services/storage.encryption/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/services/storage.encryption/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ASC.Files*.dll /var/www/products/ASC.Files/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ASC.People.dll /var/www/products/ASC.People/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.CRM/server/ASC.CRM*.dll /var/www/products/ASC.CRM/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Projects/server/ASC.Projects*.dll /var/www/products/ASC.Projects/server/
CMD ["ASC.Data.Storage.Encryption.dll", "ASC.Data.Storage.Encryption"]
## ASC.Files ##
FROM builder AS files
WORKDIR /var/www/products/ASC.Files/server/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ .
COPY --from=develop --chown=onlyoffice:onlyoffice ${SRC_PATH}/ASC.Files/Server/DocStore .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ASC.People.dll /var/www/products/ASC.People/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.CRM/server/ASC.CRM*.dll /var/www/products/ASC.CRM/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Projects/server/ASC.Projects*.dll /var/www/products/ASC.Projects/server/
CMD ["ASC.Files.dll", "ASC.Files"]
## ASC.Files.Service ##
FROM builder AS files_services
WORKDIR /var/www/products/ASC.Files/service/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/service/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ASC.Files*.dll /var/www/products/ASC.Files/Server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ASC.People*.dll /var/www/products/ASC.People/Server/
CMD ["ASC.Files.Service.dll", "ASC.Files.Service", "core:products:folder=/var/www/products/", "core:products:subfolder=server"]
## ASC.Data.Storage.Migration ##
FROM builder AS data_storage_migration
WORKDIR /var/www/services/storage.migration/service/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/services/storage.migration/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ /var/www/products/ASC.Files/Server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ /var/www/products/ASC.People/Server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.CRM/server/ /var/www/products/ASC.CRM/Server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Projects/server/ /var/www/products/ASC.Projects/Server/
CMD ["ASC.Data.Storage.Migration.dll", "ASC.Data.Storage.Migration"]
## ASC.Notify ##
FROM builder AS notify
WORKDIR /var/www/services/notify/service
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop /var/www/services/notify/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ASC.People.dll /var/www/products/ASC.People/Server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ASC.Files*.dll /var/www/products/ASC.Files/Server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.CRM/server/ASC.CRM*.dll /var/www/products/ASC.CRM/Server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Projects/server/ASC.Projects*.dll /var/www/products/ASC.Projects/Server/
CMD ["ASC.Notify.dll", "ASC.Notify", "core:products:folder=/var/www/products/", "core:products:subfolder=server"]
## ASC.People ##
FROM builder AS people_server
WORKDIR /var/www/products/ASC.People/server/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ASC.Files*.dll /var/www/products/ASC.Files/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.CRM/server/ASC.CRM*.dll /var/www/products/ASC.CRM/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Projects/server/ASC.Projects*.dll /var/www/products/ASC.Projects/server/
CMD ["ASC.People.dll", "ASC.People"]
## ASC.Projects ##
FROM builder AS projects_server
WORKDIR /var/www/products/ASC.Projects/server/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Projects/server/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ASC.Files*.dll /var/www/products/ASC.Files/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ASC.People.dll /var/www/products/ASC.People/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.CRM/server/ASC.CRM*.dll /var/www/products/ASC.CRM/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Projects/server/ASC.Projects*.dll /var/www/products/ASC.Projects/server/
CMD ["ASC.Projects.dll", "ASC.Projects"]
## ASC.Socket.IO.Svc ##
FROM builder AS socket
WORKDIR /var/www/services/socket/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/services/socket/service/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/services/socket/client /var/www/ASC.Socket.IO
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ /var/www/products/ASC.Files/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ /var/www/products/ASC.People/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.CRM/server/ /var/www/products/ASC.CRM/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Projects/server/ /var/www/products/ASC.Projects/server/
CMD ["ASC.Socket.IO.Svc.dll", "ASC.Socket.IO.Svc"]
## ASC.Studio.Notify ##
FROM builder AS studio_notify
WORKDIR /var/www/services/studio.notify/service/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop /var/www/services/studio.notify/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ASC.People.dll /var/www/products/ASC.People/Server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ASC.Files*.dll /var/www/products/ASC.Files/Server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.CRM/server/ASC.CRM*.dll /var/www/products/ASC.CRM/Server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Projects/server/ASC.Projects*.dll /var/www/products/ASC.Projects/Server/
CMD ["ASC.Studio.Notify.dll", "ASC.Studio.Notify", "core:products:folder=/var/www/products/", "core:products:subfolder=server"]
## ASC.TelegramService ##
FROM builder AS telegram_service
WORKDIR /var/www/services/telegram/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/services/telegram/service/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ASC.Files*.dll /var/www/products/ASC.Files/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ASC.People.dll /var/www/products/ASC.People/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.CRM/server/ASC.CRM*.dll /var/www/products/ASC.CRM/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Projects/server/ASC.Projects*.dll /var/www/products/ASC.Projects/server/
CMD ["ASC.TelegramService.dll", "ASC.TelegramService"]
## ASC.Thumbnails.Svc ##
FROM builder AS thumbnails
WORKDIR /var/www/services/thumb/service/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/services/thumb/service/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/services/thumb/client /var/www/services/thumb/client
CMD ["ASC.Thumbnails.Svc.dll", "ASC.Thumbnails.Svc"]
## ASC.UrlShortener.Svc ##
FROM builder AS urlshortener
WORKDIR /var/www/services/urlshortener/service/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/services/urlshortener/service/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/services/urlshortener/client /var/www/services/urlshortener/client
CMD ["ASC.UrlShortener.Svc.dll", "ASC.UrlShortener.Svc"]
## ASC.Web.Api ##
FROM builder AS api
WORKDIR /var/www/studio/api/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/studio/api .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ASC.People.dll /var/www/products/ASC.People/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ASC.Files*.dll /var/www/products/ASC.Files/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.CRM/server/ASC.CRM*.dll /var/www/products/ASC.CRM/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Projects/server/ASC.Projects*.dll /var/www/products/ASC.Projects/server/
CMD ["ASC.Web.Api.dll", "ASC.Web.Api"]
## ASC.Web.Studio ##
FROM builder AS studio
WORKDIR /var/www/studio/server/
COPY --chown=onlyoffice:onlyoffice docker-entrypoint.sh .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/studio/server/ .
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Files/server/ASC.Files*.dll /var/www/products/ASC.Files/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.People/server/ASC.People.dll /var/www/products/ASC.People/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.CRM/server/ASC.CRM*.dll /var/www/products/ASC.CRM/server/
COPY --from=develop --chown=onlyoffice:onlyoffice /var/www/products/ASC.Projects/server/ASC.Projects*.dll /var/www/products/ASC.Projects/server/
CMD ["ASC.Web.Studio.dll", "ASC.Web.Studio"]

View File

@ -25,6 +25,10 @@ x-service:
volumes:
#- /app/onlyoffice/CommunityServer/data:/app/onlyoffice/data
- app_data:/app/onlyoffice/data
- files_data:/var/www/products/ASC.Files/server/
- people_data:/var/www/products/ASC.People/server/
- crm_data:/var/www/products/ASC.CRM/server/
- project_data:/var/www/products/ASC.Projects/server/
services:
onlyoffice-elasticsearch:
@ -81,69 +85,100 @@ services:
volumes:
- kafka_data:/var/lib/kafka/data
onlyoffice-api:
onlyoffice-api-system:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-api:${SRV_VERSION}"
container_name: ${API_HOST}
onlyoffice-api_system:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-api_system:${SRV_VERSION}"
image: "${REPO}/${STATUS}appserver-api-system:${SRV_VERSION}"
container_name: ${API_SYSTEM_HOST}
onlyoffice-backup:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-backup:${SRV_VERSION}"
container_name: ${BACKUP_HOST}
onlyoffice-crm:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-crm:${SRV_VERSION}"
container_name: ${CRM_HOST}
onlyoffice-storage-encryption:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-storage-encryption:${SRV_VERSION}"
container_name: ${STORAGE_ENCRYPTION_HOST}
onlyoffice-files:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-files:${SRV_VERSION}"
container_name: ${FILES_HOST}
onlyoffice-files-services:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-files-services:${SRV_VERSION}"
container_name: ${FILES_SERVICES_HOST}
onlyoffice-storage-migration:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-storage-migration:${SRV_VERSION}"
container_name: ${STORAGE_MIGRATION_HOST}
onlyoffice-notify:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-notify:${SRV_VERSION}"
container_name: ${NOTIFY_HOST}
onlyoffice-people-server:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-people-server:${SRV_VERSION}"
container_name: ${PEOPLE_SERVER_HOST}
onlyoffice-projects-server:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-projects-server:${SRV_VERSION}"
container_name: ${PROJECTS_SERVER_HOST}
onlyoffice-socket:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-socket:${SRV_VERSION}"
container_name: ${SOCKET_HOST}
expose:
- ${SERVICE_PORT}
- "9999"
onlyoffice-studio-notify:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-studio-notify:${SRV_VERSION}"
container_name: ${STUDIO_NOTIFY_HOST}
onlyoffice-telegram-service:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-telegram-service:${SRV_VERSION}"
container_name: ${TELEGRAM_SERVICE_HOST}
onlyoffice-thumbnails:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-thumbnails:${SRV_VERSION}"
container_name: ${THUMBNAILS_HOST}
expose:
- ${SERVICE_PORT}
- "9800"
onlyoffice-urlshortener:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-urlshortener:${SRV_VERSION}"
container_name: ${URLSHORTENER_HOST}
expose:
- "9999"
- ${SERVICE_PORT}
- ${SERVICE_PORT}
- "9999"
onlyoffice-studio.notify:
onlyoffice-api:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-studio.notify:${SRV_VERSION}"
container_name: ${STUDIO_NOTIFY_HOST}
onlyoffice-notify:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-notify:${SRV_VERSION}"
container_name: ${NOTIFY_HOST}
image: "${REPO}/${STATUS}appserver-api:${SRV_VERSION}"
container_name: ${API_HOST}
onlyoffice-people.server:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-people.server:${SRV_VERSION}"
container_name: ${PEOPLE_SERVER_HOST}
onlyoffice-files:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-files:${SRV_VERSION}"
container_name: ${FILES_HOST}
onlyoffice-files_services:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-files_services:${SRV_VERSION}"
container_name: ${FILES_SERVICES_HOST}
onlyoffice-studio:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-studio:${SRV_VERSION}"
container_name: ${STUDIO_HOST}
onlyoffice-backup:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-backup:${SRV_VERSION}"
container_name: ${BACKUP_HOST}
onlyoffice-thumbnails:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-thumbnails:${SRV_VERSION}"
container_name: ${THUMBNAILS_HOST}
onlyoffice-socket:
<<: *x-service-base
image: "${REPO}/${STATUS}appserver-socket:${SRV_VERSION}"
container_name: ${SOCKET_HOST}
onlyoffice-proxy:
image: "${REPO}/${STATUS}appserver-proxy:${SRV_VERSION}"
container_name: ${PROXY_HOST}
@ -151,32 +186,45 @@ services:
expose:
- "8081"
- "8099"
- "8092"
ports:
- 8092:8092
depends_on:
- onlyoffice-api
- onlyoffice-api_system
- onlyoffice-urlshortener
- onlyoffice-studio.notify
- onlyoffice-notify
- onlyoffice-people.server
- onlyoffice-files
- onlyoffice-files_services
- onlyoffice-studio
- onlyoffice-api-system
- onlyoffice-backup
- onlyoffice-crm
- onlyoffice-storage-encryption
- onlyoffice-files
- onlyoffice-files-services
- onlyoffice-storage-migration
- onlyoffice-notify
- onlyoffice-people-server
- onlyoffice-projects-server
- onlyoffice-socket
- onlyoffice-studio-notify
- onlyoffice-telegram-service
- onlyoffice-thumbnails
- onlyoffice-urlshortener
- onlyoffice-api
- onlyoffice-studio
environment:
- SERVICE_API=${SERVICE_API}
- SERVICE_API_SYSTEM=${SERVICE_API_SYSTEM}
- SERVICE_URLSHORTENER=${SERVICE_URLSHORTENER}
- SERVICE_STUDIO_NOTIFY=${SERVICE_STUDIO_NOTIFY}
- SERVICE_PEOPLE_SERVER=${SERVICE_PEOPLE_SERVER}
- SERVICE_BACKUP=${SERVICE_BACKUP}
- SERVICE_CRM=${SERVICE_CRM}
- SERVICE_STORAGE_ENCRYPTION=${SERVICE_STORAGE_ENCRYPTION}
- SERVICE_FILES=${SERVICE_FILES}
- SERVICE_FILES_SERVICES=${SERVICE_FILES_SERVICES}
- SERVICE_STUDIO=${SERVICE_STUDIO}
- SERVICE_BACKUP=${SERVICE_BACKUP}
- SERVICE_STORAGE_MIGRATION=${SERVICE_STORAGE_MIGRATION}
- SERVICE_NOTIFY=${SERVICE_NOTIFY}
- SERVICE_PEOPLE_SERVER=${SERVICE_PEOPLE_SERVER}
- SERVICE_PROJECTS_SERVER=${SERVICE_PROJECTS_SERVER}
- SERVICE_SOCKET=${SERVICE_SOCKET}
- SERVICE_STUDIO_NOTIFY=${SERVICE_STUDIO_NOTIFY}
- SERVICE_TELEGRAM_SERVICE=${SERVICE_TELEGRAM_SERVICE}
- SERVICE_THUMBNAILS=${SERVICE_THUMBNAILS}
- SERVICE_SH=${SERVICE_SH}
- SERVICE_URLSHORTENER=${SERVICE_URLSHORTENER}
- SERVICE_API=${SERVICE_API}
- SERVICE_STUDIO=${SERVICE_STUDIO}
- DOCUMENT_SERVER=${DOCUMENT_SERVER_HOST}
- SERVICE_PORT=${SERVICE_PORT}
volumes:
@ -189,8 +237,12 @@ networks:
volumes:
kafka_data:
es_data:
zoo_data:
zoo_log:
proxy_log:
app_data:
es_data:
files_data:
people_data:
crm_data:
project_data:

View File

@ -1,93 +1,128 @@
version: "3.6"
services:
onlyoffice-api:
onlyoffice-api-system:
build:
context: ./
dockerfile: Dockerfile-app
target: api
image: "${REPO}/${STATUS}appserver-api:${SRV_VERSION}"
onlyoffice-api_system:
build:
context: ./
dockerfile: Dockerfile-app
dockerfile: "${DOCKERFILE}"
target: api_system
image: "${REPO}/${STATUS}appserver-api_system:${SRV_VERSION}"
image: "${REPO}/${STATUS}appserver-api-system:${SRV_VERSION}"
onlyoffice-urlshortener:
build:
context: ./
dockerfile: Dockerfile-app
target: urlshortener
image: "${REPO}/${STATUS}appserver-urlshortener:${SRV_VERSION}"
onlyoffice-studio.notify:
build:
context: ./
dockerfile: Dockerfile-app
target: studio.notify
image: "${REPO}/${STATUS}appserver-studio.notify:${SRV_VERSION}"
onlyoffice-notify:
build:
context: ./
dockerfile: Dockerfile-app
target: notify
image: "${REPO}/${STATUS}appserver-notify:${SRV_VERSION}"
onlyoffice-people.server:
build:
context: ./
dockerfile: Dockerfile-app
target: people.server
image: "${REPO}/${STATUS}appserver-people.server:${SRV_VERSION}"
onlyoffice-files:
build:
context: ./
dockerfile: Dockerfile-app
target: files
image: "${REPO}/${STATUS}appserver-files:${SRV_VERSION}"
onlyoffice-files_services:
build:
context: ./
dockerfile: Dockerfile-app
target: files_services
image: "${REPO}/${STATUS}appserver-files_services:${SRV_VERSION}"
onlyoffice-studio:
build:
context: ./
dockerfile: Dockerfile-app
target: studio
image: "${REPO}/${STATUS}appserver-studio:${SRV_VERSION}"
onlyoffice-backup:
build:
context: ./
dockerfile: Dockerfile-app
dockerfile: "${DOCKERFILE}"
target: backup
image: "${REPO}/${STATUS}appserver-backup:${SRV_VERSION}"
onlyoffice-thumbnails:
onlyoffice-crm:
build:
context: ./
dockerfile: Dockerfile-app
target: thumbnails
image: "${REPO}/${STATUS}appserver-thumbnails:${SRV_VERSION}"
onlyoffice-proxy:
dockerfile: "${DOCKERFILE}"
target: crm
image: "${REPO}/${STATUS}appserver-crm:${SRV_VERSION}"
onlyoffice-storage-encryption:
build:
context: ./
dockerfile: Dockerfile-app
target: web
image: "${REPO}/${STATUS}appserver-proxy:${SRV_VERSION}"
context: ./
dockerfile: "${DOCKERFILE}"
target: data_storage_encryption
image: "${REPO}/${STATUS}appserver-storage-encryption:${SRV_VERSION}"
onlyoffice-files:
build:
context: ./
dockerfile: "${DOCKERFILE}"
target: files
image: "${REPO}/${STATUS}appserver-files:${SRV_VERSION}"
onlyoffice-files-services:
build:
context: ./
dockerfile: "${DOCKERFILE}"
target: files_services
image: "${REPO}/${STATUS}appserver-files-services:${SRV_VERSION}"
onlyoffice-storage-migration:
build:
context: ./
dockerfile: "${DOCKERFILE}"
target: data_storage_migration
image: "${REPO}/${STATUS}appserver-storage-migration:${SRV_VERSION}"
onlyoffice-notify:
build:
context: ./
dockerfile: "${DOCKERFILE}"
target: notify
image: "${REPO}/${STATUS}appserver-notify:${SRV_VERSION}"
onlyoffice-people-server:
build:
context: ./
dockerfile: "${DOCKERFILE}"
target: people_server
image: "${REPO}/${STATUS}appserver-people-server:${SRV_VERSION}"
onlyoffice-projects-server:
build:
context: ./
dockerfile: "${DOCKERFILE}"
target: projects_server
image: "${REPO}/${STATUS}appserver-projects-server:${SRV_VERSION}"
onlyoffice-socket:
build:
context: ./
dockerfile: Dockerfile-app
dockerfile: "${DOCKERFILE}"
target: socket
image: "${REPO}/${STATUS}appserver-socket:${SRV_VERSION}"
onlyoffice-studio-notify:
build:
context: ./
dockerfile: "${DOCKERFILE}"
target: studio_notify
image: "${REPO}/${STATUS}appserver-studio-notify:${SRV_VERSION}"
onlyoffice-telegram-service:
build:
context: ./
dockerfile: "${DOCKERFILE}"
target: telegram_service
image: "${REPO}/${STATUS}appserver-telegram-service:${SRV_VERSION}"
onlyoffice-thumbnails:
build:
context: ./
dockerfile: "${DOCKERFILE}"
target: thumbnails
image: "${REPO}/${STATUS}appserver-thumbnails:${SRV_VERSION}"
onlyoffice-urlshortener:
build:
context: ./
dockerfile: "${DOCKERFILE}"
target: urlshortener
image: "${REPO}/${STATUS}appserver-urlshortener:${SRV_VERSION}"
onlyoffice-api:
build:
context: ./
dockerfile: "${DOCKERFILE}"
target: api
image: "${REPO}/${STATUS}appserver-api:${SRV_VERSION}"
onlyoffice-studio:
build:
context: ./
dockerfile: "${DOCKERFILE}"
target: studio
image: "${REPO}/${STATUS}appserver-studio:${SRV_VERSION}"
onlyoffice-proxy:
build:
context: ./
dockerfile: "${DOCKERFILE}"
target: web
image: "${REPO}/${STATUS}appserver-proxy:${SRV_VERSION}"

View File

@ -1,38 +1,23 @@
resolver 127.0.0.11 valid=30s;
map $DOCUMENT_SERVER $document_server {
volatile;
$DOCUMENT_SERVER $DOCUMENT_SERVER;
}
map $SERVICE_API $service_api {
volatile;
$SERVICE_API $SERVICE_API;
}
map $SERVICE_API_SYSTEM $service_api_system {
volatile;
$SERVICE_API_SYSTEM $SERVICE_API_SYSTEM;
}
map $SERVICE_URLSHORTENER $service_urlshortener {
map $SERVICE_BACKUP $service_backup {
volatile;
$SERVICE_URLSHORTENER $SERVICE_URLSHORTENER;
$SERVICE_BACKUP $SERVICE_BACKUP;
}
map $SERVICE_THUMBNAILS $service_thumbnails {
map $SERVICE_CRM $service_crm {
volatile;
$SERVICE_THUMBNAILS $SERVICE_THUMBNAILS;
$SERVICE_CRM $SERVICE_CRM;
}
map $SERVICE_STUDIO_NOTIFY $service_studio_notify {
map $SERVICE_STORAGE_ENCRYPTION $service_storage_encryption {
volatile;
$SERVICE_STUDIO_NOTIFY $SERVICE_STUDIO_NOTIFY;
}
map $SERVICE_PEOPLE_SERVER $service_people_server {
volatile;
$SERVICE_PEOPLE_SERVER $SERVICE_PEOPLE_SERVER;
$SERVICE_STORAGE_ENCRYPTION $SERVICE_STORAGE_ENCRYPTION;
}
map $SERVICE_FILES $service_files {
@ -45,17 +30,62 @@ map $SERVICE_FILES_SERVICES $service_files_services {
$SERVICE_FILES_SERVICES $SERVICE_FILES_SERVICES;
}
map $SERVICE_STORAGE_MIGRATION $service_storage_migration {
volatile;
$SERVICE_STORAGE_MIGRATION $SERVICE_STORAGE_MIGRATION;
}
map $SERVICE_NOTIFY $service_notify {
volatile;
$SERVICE_NOTIFY $SERVICE_NOTIFY;
}
map $SERVICE_PEOPLE_SERVER $service_people_server {
volatile;
$SERVICE_PEOPLE_SERVER $SERVICE_PEOPLE_SERVER;
}
map $SERVICE_PROJECTS_SERVER $service_projects_server {
volatile;
$SERVICE_PROJECTS_SERVER $SERVICE_PROJECTS_SERVER;
}
map $SERVICE_SOCKET $service_socket {
volatile;
$SERVICE_SOCKET $SERVICE_SOCKET;
}
map $SERVICE_STUDIO_NOTIFY $service_studio_notify {
volatile;
$SERVICE_STUDIO_NOTIFY $SERVICE_STUDIO_NOTIFY;
}
map $SERVICE_TELEGRAM_SERVICE $service_telegram_service {
volatile;
$SERVICE_TELEGRAM_SERVICE $SERVICE_TELEGRAM_SERVICE;
}
map $SERVICE_THUMBNAILS $service_thumbnails {
volatile;
$SERVICE_THUMBNAILS $SERVICE_THUMBNAILS;
}
map $SERVICE_URLSHORTENER $service_urlshortener {
volatile;
$SERVICE_URLSHORTENER $SERVICE_URLSHORTENER;
}
map $SERVICE_API $service_api {
volatile;
$SERVICE_API $SERVICE_API;
}
map $SERVICE_STUDIO $service_studio {
volatile;
$SERVICE_STUDIO $SERVICE_STUDIO;
}
map $SERVICE_BACKUP $service_backup {
map $DOCUMENT_SERVER $document_server {
volatile;
$SERVICE_BACKUP $SERVICE_BACKUP;
}
map $SERVICE_SH $service_sh {
volatile;
$SERVICE_SH $SERVICE_SH;
$DOCUMENT_SERVER $DOCUMENT_SERVER;
}

View File

@ -0,0 +1,112 @@
DELIMITER DLM00
DROP PROCEDURE IF EXISTS upgrade110 DLM00
CREATE PROCEDURE upgrade110()
BEGIN
IF (SELECT DATA_TYPE FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'crm_invoice_item' AND COLUMN_NAME = 'quantity') <> 'decimal' THEN
ALTER TABLE `crm_invoice_item` CHANGE COLUMN `quantity` `quantity` DECIMAL(10,2) NOT NULL DEFAULT '0.00' AFTER `price`;
END IF;
IF (SELECT DATA_TYPE FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'crm_invoice_item' AND COLUMN_NAME = 'stock_quantity') <> 'decimal' THEN
ALTER TABLE `crm_invoice_item` CHANGE COLUMN `stock_quantity` `stock_quantity` DECIMAL(10,2) NOT NULL DEFAULT '0.00' AFTER `quantity`;
END IF;
IF (SELECT DATA_TYPE FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'crm_invoice_line' AND COLUMN_NAME = 'quantity') <> 'decimal' THEN
ALTER TABLE `crm_invoice_line` CHANGE COLUMN `quantity` `quantity` DECIMAL(10,2) NOT NULL DEFAULT '0.00' AFTER `description`;
END IF;
IF (SELECT DATA_TYPE FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'crm_invoice_line' AND COLUMN_NAME = 'discount') <> 'decimal' THEN
ALTER TABLE `crm_invoice_line` CHANGE COLUMN `discount` `discount` DECIMAL(10,2) NOT NULL DEFAULT '0.00' AFTER `price`;
END IF;
IF EXISTS(SELECT * FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'crm_invoice_item' AND COLUMN_NAME = 'quantity') THEN
ALTER TABLE `crm_invoice_item` DROP COLUMN `quantity`;
END IF;
IF NOT EXISTS(SELECT * FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'notify_queue' AND COLUMN_NAME = 'auto_submitted') THEN
ALTER TABLE `notify_queue` ADD COLUMN `auto_submitted` VARCHAR(64) NULL DEFAULT NULL AFTER `attachments`;
END IF;
IF NOT EXISTS(SELECT * FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'core_usersecurity' AND COLUMN_NAME = 'LastModified') THEN
ALTER TABLE `core_usersecurity` ADD COLUMN `LastModified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP() AFTER `pwdhashsha512`;
END IF;
UPDATE `tenants_quota` SET `features` = 'domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom' WHERE `tenant` = -1 and `name` NOT LIKE '%saas%';
UPDATE `tenants_quota` SET `features` = 'docs,domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom' WHERE tenant = -1000;
CREATE TABLE IF NOT EXISTS `telegram_users` (
`portal_user_id` VARCHAR(38) NOT NULL,
`tenant_id` INT(11) NOT NULL,
`telegram_user_id` INT(11) NOT NULL,
PRIMARY KEY (`tenant_id`, `portal_user_id`),
INDEX `tgId` (`telegram_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
UPDATE `res_data`
SET `textValue` = REPLACE(`textValue`, 'products/crm/default', 'Products/CRM/Default')
WHERE `fileid` = (SELECT `id` FROM `res_files` WHERE `resName` = 'CRMPatternResource.resx');
UPDATE `res_data`
SET `textValue` = REPLACE(`textValue`, 'products/crm/deals', 'Products/CRM/Deals')
WHERE `fileid` = (SELECT `id` FROM `res_files` WHERE `resName` = 'CRMPatternResource.resx');
UPDATE `res_data`
SET `textValue` = REPLACE(`textValue`, 'products/crm/tasks', 'Products/CRM/Tasks')
WHERE `fileid` = (SELECT `id` FROM `res_files` WHERE `resName` = 'CRMPatternResource.resx');
UPDATE `res_data`
SET `textValue` = REPLACE(`textValue`, 'products/crm', 'Products/CRM')
WHERE `fileid` = (SELECT `id` FROM `res_files` WHERE `resName` = 'CRMPatternResource.resx');
UPDATE `res_data`
SET `textValue` = REPLACE(`textValue`, 'products/projects/messages', 'Products/Projects/Messages')
WHERE `fileid` = (SELECT `id` FROM `res_files` WHERE `resName` = 'PatternResource.resx');
UPDATE `res_data`
SET `textValue` = REPLACE(`textValue`, 'products/projects/tasks', 'Products/Projects/Tasks')
WHERE `fileid` = (SELECT `id` FROM `res_files` WHERE `resName` = 'PatternResource.resx');
UPDATE `res_data`
SET `textValue` = REPLACE(`textValue`, 'products/projects/projects', 'Products/Projects/Projects')
WHERE `fileid` = (SELECT `id` FROM `res_files` WHERE `resName` = 'PatternResource.resx');
UPDATE `res_data`
SET `textValue` = REPLACE(`textValue`, 'products/projects/milestones', 'Products/Projects/Milestones')
WHERE `fileid` = (SELECT `id` FROM `res_files` WHERE `resName` = 'PatternResource.resx');
UPDATE `res_data`
SET `textValue` = REPLACE(`textValue`, 'products/projects', 'Products/Projects')
WHERE `fileid` = (SELECT `id` FROM `res_files` WHERE `resName` = 'PatternResource.resx');
UPDATE `res_data`
SET `textValue` = REPLACE(`textValue`, 'products/files', 'Products/Files')
WHERE `fileid` = (SELECT `id` FROM `res_files` WHERE `resName` = 'FilesPatternResource.resx');
UPDATE `res_data`
SET `textValue` = REPLACE(`textValue`, 'products/files', 'Products/Files')
WHERE `fileid` = (SELECT `id` FROM `res_files` WHERE `resName` = 'WebstudioNotifyPatternResource.resx');
UPDATE `res_data`
SET `textValue` = REPLACE(`textValue`, 'products/projects', 'Products/Projects')
WHERE `fileid` = (SELECT `id` FROM `res_files` WHERE `resName` = 'WebstudioNotifyPatternResource.resx');
UPDATE `res_data`
SET `textValue` = REPLACE(`textValue`, 'products/community', 'Products/Community')
WHERE `fileid` = (SELECT `id` FROM `res_files` WHERE `resName` = 'WebstudioNotifyPatternResource.resx');
UPDATE `res_data`
SET `textValue` = REPLACE(`textValue`, 'products/crm', 'Products/CRM')
WHERE `fileid` = (SELECT `id` FROM `res_files` WHERE `resName` = 'WebstudioNotifyPatternResource.resx');
UPDATE `core_settings`
SET `value`=0xF547048A4865171587D9CEBC8A496C601D96031F2C1C3E9160353942EE765DACD316F4B5F42892436FC4A21B9A6DF8FFD3BC4036B47E3A5A1B4C881B26609869FEBB6848BD88C02EEAC6A4CCB3E8F404290812F0E6E124A552BE81A58C64BB8BD3C9A8C0EDE1F9421281DE0C7AF82733A4BCE515E85694C4DDA78E22652BA2891FCE9578F97285A81E12FEDF5D6558611E3AA3E03EADDCAA98287C64A5510757A881B00C3345E6FC1E22B607CA2D753C63F1ED94C92366DBA0E4C2E6DB16F44A8AB091007AA7505D17E41530643C1FFAE822F8F99FD2E30C0DEF82DF65C43324507F3E5C68E4C5E22BE8A40C24423485
WHERE `tenant`=-1 AND `id`='CompanyWhiteLabelSettings';
END DLM00
CALL upgrade110() DLM00
DELIMITER ;

View File

@ -0,0 +1,19 @@
DELIMITER DLM00
DROP PROCEDURE IF EXISTS upgrade111 DLM00
CREATE PROCEDURE upgrade111()
BEGIN
IF NOT EXISTS(SELECT * FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'files_file' AND COLUMN_NAME = 'thumb') THEN
ALTER TABLE `files_file` ADD COLUMN `thumb` INT(1) NOT NULL DEFAULT '0' AFTER `forcesave`;
END IF;
ALTER TABLE `files_thirdparty_account` CHANGE COLUMN `password` `password` VARCHAR(512) NOT NULL AFTER `user_name`;
END DLM00
CALL upgrade111() DLM00
DELIMITER ;

View File

@ -0,0 +1,39 @@
DELIMITER DLM00
DROP PROCEDURE IF EXISTS upgrade115 DLM00
CREATE PROCEDURE upgrade115()
BEGIN
INSERT IGNORE INTO `files_converts` (`input`, `output`) VALUES ('.fb2', '.docx');
INSERT IGNORE INTO `files_converts` (`input`, `output`) VALUES ('.fb2', '.odt');
INSERT IGNORE INTO `files_converts` (`input`, `output`) VALUES ('.fb2', '.pdf');
INSERT IGNORE INTO `files_converts` (`input`, `output`) VALUES ('.fb2', '.rtf');
INSERT IGNORE INTO `files_converts` (`input`, `output`) VALUES ('.fb2', '.txt');
IF NOT EXISTS(SELECT * FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'calendar_events' AND COLUMN_NAME = 'time_zone') THEN
ALTER TABLE `calendar_events` ADD COLUMN `time_zone` VARCHAR(255) NULL DEFAULT NULL AFTER `status`;
END IF;
IF NOT EXISTS(SELECT * FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'backup_backup' AND COLUMN_NAME = 'hash') THEN
ALTER TABLE `backup_backup` ADD COLUMN `hash` char(64) NOT NULL AFTER `storage_params`;
END IF;
IF EXISTS(SELECT * FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'tenants_tariff' AND COLUMN_NAME = 'tariff_key') THEN
ALTER TABLE `tenants_tariff` DROP COLUMN `tariff_key`;
END IF;
IF NOT EXISTS(SELECT * FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'tenants_tariff' AND COLUMN_NAME = 'quantity') THEN
ALTER TABLE `tenants_tariff` ADD COLUMN `quantity` int(10) NOT NULL DEFAULT 1 AFTER `stamp`;
END IF;
INSERT IGNORE INTO `crm_currency_info` (`resource_key`, `abbreviation`, `symbol`, `culture_name`, `is_convertable`, `is_basic`) values ('Currency_MongolianTugrik', 'MNT', '', 'MN', 0, 0);
UPDATE `tenants_quota` SET `features` = 'docs,domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom,restore,contentsearch' WHERE tenant = -1000;
UPDATE `tenants_quota` SET `features` = 'domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom,restore,contentsearch' WHERE `tenant` = -1 and `name` NOT LIKE '%saas%';
END DLM00
CALL upgrade115() DLM00
DELIMITER ;

View File

@ -26,6 +26,9 @@ services:
- ./config/onlyoffice.sql:/docker-entrypoint-initdb.d/02_onlyoffice.sql
- ./config/onlyoffice.data.sql:/docker-entrypoint-initdb.d/03_onlyoffice.data.sql
- ./config/onlyoffice.resources.sql:/docker-entrypoint-initdb.d/04_onlyoffice.resources.sql
- ./config/onlyoffice.upgradev110.sql:/docker-entrypoint-initdb.d/05_onlyoffice.upgradev110.sql
- ./config/onlyoffice.upgradev111.sql:/docker-entrypoint-initdb.d/06_onlyoffice.upgradev111.sql
- ./config/onlyoffice.upgradev115.sql:/docker-entrypoint-initdb.d/07_onlyoffice.upgradev115.sql
networks:
- ${NETWORK_NAME}
tmpfs: /var/log/mysql/

View File

@ -70,6 +70,7 @@ sed -i "s!\"header\".*!\"header\": \"${DOCUMENT_SERVER_JWT_HEADER}\"!" ${PATH_TO
grep -q "${ELK_VALUE}" ${PATH_TO_CONF}/appsettings.${APP_DOTNET_ENV}.json || sed -i "s!\"files\".*!${ELK_VALUE}\n\"files\": {!" ${PATH_TO_CONF}/appsettings.${APP_DOTNET_ENV}.json
sed -i "s!\"subfolder\".*!\"subfolder\": \"server\",!g" ${PATH_TO_CONF}/appsettings.services.json
sed -i "s!\"BootstrapServers\".*!\"BootstrapServers\": \"${KAFKA_HOST}\"!g" ${PATH_TO_CONF}/kafka.${APP_DOTNET_ENV}.json
dotnet ${DOTNET_RUN} --urls=${URLS} --ENVIRONMENT=${APP_DOTNET_ENV} --'$STORAGE_ROOT'=${APP_STORAGE_ROOT} --pathToConf=${PATH_TO_CONF} --log:dir=${LOG_DIR} --log:name=${DOTNET_LOG_NAME} ${PARAMETERS}

View File

@ -1,18 +0,0 @@
PUSHD %~dp0
call start\stop.bat
PUSHD %~dp0..
echo "Build FRONT-END"
call yarn wipe
call yarn install
echo "ASC.UrlShortener"
call yarn install --cwd common/ASC.UrlShortener > build\ASC.UrlShortener.log
echo "ASC.Web.sln"
call dotnet build ASC.Web.sln /fl1 /flp1:LogFile=build/ASC.Web.log;Verbosity=Normal
start /b call build\start\start.bat
pause

View File

@ -1,6 +0,0 @@
PUSHD %~dp0..
del /f /q yarn.lock
start /b call build\rebuild.frontend.bat

View File

@ -40,11 +40,11 @@
</PackageReference>
<PackageReference Include="JWT" Version="6.1.4" />
<PackageReference Include="log4net" Version="2.0.11" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="5.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="5.0.5" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="5.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="5.0.5" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0" />

View File

@ -57,11 +57,11 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="MailKit" Version="2.5.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.5" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="5.0.2" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="5.0.0-alpha.2" />
<PackageReference Include="System.Text.Json" Version="5.0.1" />
<PackageReference Include="System.Text.Json" Version="5.0.2" />
<PackageReference Include="Telegram.Bot" Version="15.7.1" />
</ItemGroup>
<ItemGroup>

View File

@ -576,12 +576,11 @@ namespace ASC.Core.Data
using var tr = UserDbContext.Database.BeginTransaction();
UserDbContext.AddOrUpdate(r => r.UserGroups, FromUserGroupRefToUserGroup(r));
var user = GetUserQuery(tenant).FirstOrDefault(a => a.Tenant == tenant && a.Id == r.UserId);
if (user != null)
{
user.LastModified = r.LastModified;
UserDbContext.AddOrUpdate(r => r.UserGroups, FromUserGroupRefToUserGroup(r));
}
UserDbContext.SaveChanges();

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,84 @@
map $http_host $this_host {
"" $host;
default $http_host;
}
map $http_x_forwarded_proto $the_scheme {
default $http_x_forwarded_proto;
"" $scheme;
}
map $http_x_forwarded_host $the_host {
default $http_x_forwarded_host;
"" $this_host;
}
server {
listen 80;
listen [::]:80;
server_name localhost;
set $X_REWRITER_URL $the_scheme://$the_host;
set $mobile_rewrite do_not_perform;
set $desktop "";
location / {
## redirect to mobile -> appserver ##
if ($http_user_agent ~* "(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino") {
set $mobile_rewrite perform;
}
if ($http_user_agent ~* "^(1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-)") {
set $mobile_rewrite perform;
}
if ($args ~ 'desktop_view=true') {
set $mobile_rewrite do_not_perform;
set $desktop "desktop_view=true";
}
if ($args ~ 'desktop_view=false') {
set $mobile_rewrite perform;
set $desktop "desktop_view=false";
}
add_header Set-Cookie "$desktop; Path=/" always;
if ($http_cookie ~ "desktop_view=true") {
set $mobile_rewrite do_not_perform;
}
if ($http_cookie ~ "desktop_view=false") {
set $mobile_rewrite perform;
}
if ($mobile_rewrite = perform) {
rewrite ^ /appserver$request_uri? redirect;
}
proxy_pass http://localhost:8081;
root /usr/share/nginx/html;
index index.html index.htm;
}
location ~* ^/appserver {
sub_filter '</head>' '</head><script language="javascript">window.APPSERVER_PROXY_URL=`/appserver`;</script>';
sub_filter_once on;
rewrite /appserver(.*) $1 break;
proxy_pass http://localhost:8092;
proxy_set_header Accept-Encoding "";
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

View File

@ -21,34 +21,51 @@ server {
server_name localhost;
set $X_REWRITER_URL $the_scheme://$the_host;
set $mobile_rewrite do_not_perform;
set $desktop "";
location / {
if ($http_referer ~* /appserver) {
rewrite /(.*) /appserver/$1 last;
## redirect to mobile -> appserver ##
if ($http_user_agent ~* "(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino") {
set $mobile_rewrite perform;
}
# if ($http_referer ~* /products/people/) {
# rewrite /(.*) /appserver/$1 last;
# }
# proxy_set_header Host portals;
if ($http_user_agent ~* "^(1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-)") {
set $mobile_rewrite perform;
}
if ($args ~ 'desktop_view=true') {
set $mobile_rewrite do_not_perform;
set $desktop "desktop_view=true";
}
if ($args ~ 'desktop_view=false') {
set $mobile_rewrite perform;
set $desktop "desktop_view=false";
}
add_header Set-Cookie "$desktop; Path=/" always;
if ($http_cookie ~ "desktop_view=true") {
set $mobile_rewrite do_not_perform;
}
if ($http_cookie ~ "desktop_view=false") {
set $mobile_rewrite perform;
}
if ($mobile_rewrite = perform) {
proxy_pass http://localhost:8092;
break;
}
proxy_pass http://localhost:8081;
root /usr/share/nginx/html;
index index.html index.htm;
}
location ~* ^/appserver/ {
rewrite /appserver(.*) $1 break;
proxy_pass http://localhost:8092;
proxy_set_header Accept-Encoding "";
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
# proxy_redirect ~*(.*)/login/(.*) $1/appserver/login/$2;
# proxy_redirect ~*(.*)/products/people/(.*) $1/appserver/products/people/$2;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {

View File

@ -1,5 +1,5 @@
{
"version": "0.1.0",
"version": "0.1.2",
"npmClient": "yarn",
"packages": [
"packages/asc-web-components",

View File

@ -44,9 +44,9 @@ export function deleteGroup(id) {
});
}
export function getGroupListFull() {
/*export function getGroupListFull() {
return request({
method: "get",
url: "/group/full",
});
}
}*/ //TODO: use after fixing problems on the server

View File

@ -124,6 +124,7 @@ class PageLayout extends React.Component {
isArticleVisible: false,
isArticlePinned: false,
});
isMobile && this.props.setArticleVisibleOnUnpin(false);
};
pinArticle = () => {
@ -134,6 +135,7 @@ class PageLayout extends React.Component {
});
this.props.setArticlePinned(true);
isMobile && this.props.setArticleVisibleOnUnpin(false);
};
unpinArticle = () => {
@ -144,6 +146,7 @@ class PageLayout extends React.Component {
});
this.props.setArticlePinned(false);
isMobile && this.props.setArticleVisibleOnUnpin(true);
};
showArticle = () => {
@ -152,6 +155,7 @@ class PageLayout extends React.Component {
isArticleVisible: true,
isArticlePinned: false,
});
isMobile && this.props.setArticleVisibleOnUnpin(true);
};
render() {
@ -273,7 +277,7 @@ class PageLayout extends React.Component {
</SubArticleMainButton>
)}
{isArticleBodyAvailable && (
<SubArticleBody>
<SubArticleBody pinned={this.state.isArticlePinned}>
{articleBodyContent ? articleBodyContent.props.children : null}
</SubArticleBody>
)}
@ -453,6 +457,7 @@ export default inject(({ auth }) => {
isTabletView,
isArticlePinned,
setArticlePinned,
setArticleVisibleOnUnpin,
} = settingsStore;
return {
isLoaded,
@ -460,5 +465,6 @@ export default inject(({ auth }) => {
isHeaderVisible,
isArticlePinned,
setArticlePinned,
setArticleVisibleOnUnpin,
};
})(observer(PageLayout));

View File

@ -4,6 +4,7 @@ import styled from "styled-components";
import equal from "fast-deep-equal/react";
import Scrollbar from "@appserver/components/scrollbar";
import { tablet, smallTablet } from "@appserver/components/utils/device";
import { isMobile } from "react-device-detect";
const StyledArticleBody = styled.div`
${(props) => props.displayBorder && `outline: 1px dotted;`}
@ -27,6 +28,7 @@ const StyledArticleBody = styled.div`
.people-tree-menu {
margin-right: 0;
${(props) => isMobile && props.pinned && `margin-bottom: 56px`}
}
.custom-scrollbar {
@ -56,10 +58,10 @@ class ArticleBody extends React.Component {
render() {
//console.log("PageLayout ArticleBody render");
const { children } = this.props;
const { children, pinned } = this.props;
return (
<StyledArticleBody>
<StyledArticleBody pinned={pinned}>
<Scrollbar
id="articleScrollBar"
className="custom-scrollbar"

View File

@ -1,8 +1,10 @@
const pks = require("../package.json");
const window = require("global/window");
const { proxy, api } = pks;
module.exports = {
proxyURL: (proxy && proxy.url) || "",
proxyURL:
(proxy && proxy.url) || (window && window.APPSERVER_PROXY_URL) || "",
apiPrefixURL: (api && api.url) || "/api/2.0",
apiTimeout: (api && api.timeout) || 30000,
};

View File

@ -1,6 +1,6 @@
{
"name": "@appserver/common",
"version": "0.0.1",
"version": "0.0.2",
"private": true,
"scripts": {
"build": "echo 'skip it'",
@ -14,5 +14,8 @@
},
"proxy": {
"url": ""
},
"dependencies": {
"global": "^4.4.0"
}
}

View File

@ -59,6 +59,8 @@ class SettingsStore {
isArticlePinned =
localStorage.getItem(ARTICLE_PINNED_KEY) === "true" || false;
isArticleVisibleOnUnpin = false;
hashSettings = null;
title = "";
ownerId = null;
@ -97,9 +99,11 @@ class SettingsStore {
? combineUrl(proxyURL, newSettings[key])
: newSettings[key]
);
if (key === "culture" && !localStorage.getItem(LANGUAGE)) {
localStorage.setItem(LANGUAGE, newSettings[key]);
if (key === "culture") {
const language = localStorage.getItem(LANGUAGE);
if (!language || language == "undefined") {
localStorage.setItem(LANGUAGE, newSettings[key]);
}
}
} else if (key === "passwordHash") {
this.setValue("hashSettings", newSettings[key]);
@ -228,6 +232,10 @@ class SettingsStore {
: localStorage.removeItem(ARTICLE_PINNED_KEY);
this.isArticlePinned = isPinned;
};
setArticleVisibleOnUnpin = (visible) => {
this.isArticleVisibleOnUnpin = visible;
};
}
export default SettingsStore;

View File

@ -21,7 +21,8 @@ class UserStore {
getCurrentUser = async () => {
const user = await api.people.getUser();
localStorage.getItem(LANGUAGE) !== user.cultureName &&
user.cultureName &&
localStorage.getItem(LANGUAGE) !== user.cultureName &&
localStorage.setItem(LANGUAGE, user.cultureName);
this.setUser(user);
};

View File

@ -169,3 +169,44 @@ export function isAdmin(currentUser, currentProductId) {
import combineUrlFunc from "./combineUrl";
export const combineUrl = combineUrlFunc;
export function getCookie(name) {
let matches = document.cookie.match(
new RegExp(
"(?:^|; )" +
name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, "\\$1") +
"=([^;]*)"
)
);
return matches ? decodeURIComponent(matches[1]) : undefined;
}
export function setCookie(name, value, options = {}) {
options = {
path: "/",
...options,
};
if (options.expires instanceof Date) {
options.expires = options.expires.toUTCString();
}
let updatedCookie =
encodeURIComponent(name) + "=" + encodeURIComponent(value);
for (let optionKey in options) {
updatedCookie += "; " + optionKey;
let optionValue = options[optionKey];
if (optionValue !== true) {
updatedCookie += "=" + optionValue;
}
}
document.cookie = updatedCookie;
}
export function deleteCookie(name) {
setCookie(name, "", {
"max-age": -1,
});
}

View File

@ -0,0 +1,61 @@
import { Workbox } from "workbox-window";
export function registerSW(homepage) {
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
const wb = new Workbox(`${homepage}/sw.js`);
//TODO: watch https://developers.google.com/web/tools/workbox/guides/advanced-recipes and https://github.com/webmaxru/prog-web-news/blob/5ff94b45c9d317409c21c0fbb7d76e92f064471b/src/app/app-shell/app-shell.component.ts
const showSkipWaitingPrompt = (event) => {
console.log(
`A new service worker has installed, but it can't activate` +
`until all tabs running the current version have fully unloaded.`
);
// Assuming the user accepted the update, set up a listener
// that will reload the page as soon as the previously waiting
// service worker has taken control.
wb.addEventListener("controlling", () => {
window.location.reload();
});
// This will postMessage() to the waiting service worker.
wb.messageSkipWaiting();
// let snackBarRef = this.snackBar.open(
// "A new version of the website available",
// "Reload page",
// {
// duration: 5000,
// }
// );
// // Displaying prompt
// snackBarRef.onAction().subscribe(() => {
// // Assuming the user accepted the update, set up a listener
// // that will reload the page as soon as the previously waiting
// // service worker has taken control.
// wb.addEventListener("controlling", () => {
// window.location.reload();
// });
// // This will postMessage() to the waiting service worker.
// wb.messageSkipWaiting();
// });
};
// Add an event listener to detect when the registered
// service worker has installed but is waiting to activate.
wb.addEventListener("waiting", showSkipWaitingPrompt);
wb.register()
.then((reg) => {
console.log("Successful service worker registration", reg);
})
.catch((err) => console.error("Service worker registration failed", err));
} else {
console.log("SKIP registerSW because of DEV mode");
}
}

View File

@ -81,20 +81,20 @@ offlineFallback({
// ALL OTHER EVENTS
// Receive push and show a notification
self.addEventListener("push", function (event) {
console.log("[Service Worker]: Received push event", event);
// self.addEventListener("push", function (event) {
// console.log("[Service Worker]: Received push event", event);
var notificationData = {};
// var notificationData = {};
if (event.data.json()) {
notificationData = event.data.json();
} else {
notificationData = {
title: "Something Has Happened",
message: "Something you might want to check out",
icon: "/assets/img/pwa-logo.png",
};
}
// if (event.data.json()) {
// notificationData = event.data.json();
// } else {
// notificationData = {
// title: "Something Has Happened",
// message: "Something you might want to check out",
// icon: "/assets/img/pwa-logo.png",
// };
// }
self.registration.showNotification(notificationData.title, notificationData);
});
// self.registration.showNotification(notificationData.title, notificationData);
// });

View File

@ -399,18 +399,17 @@ class AvatarEditorBody extends React.Component {
isClickable={true}
color="#FFFFFF"
className="editor-button"
style={{padding: 8}}
/>
</Box>
<Box className="zoom-container">
<IconButton
className="zoom-container-svg_zoom-minus"
size="16"
isDisabled={false}
onClick={this.onZoomMinusClick}
iconName={"/static/images/zoom-minus.react.svg"}
isFill={true}
isClickable={false}
style={{paddingTop: 20}}
/>
<Slider
id="scale"
@ -424,12 +423,12 @@ class AvatarEditorBody extends React.Component {
/>
<IconButton
size="16"
className="zoom-container-svg_zoom-plus"
isDisabled={false}
onClick={this.onZoomPlusClick}
iconName={"/static/images/zoom-plus.react.svg"}
isFill={true}
isClickable={false}
style={{paddingTop: 20}}
/>
</Box>
</Box>

View File

@ -216,6 +216,9 @@ const mobileStyles = css`
props.theme.avatarEditorBody.container.button.height};
border-radius: ${(props) =>
props.theme.avatarEditorBody.container.button.borderRadius};
display: flex;
align-items: center;
}
}
@ -224,6 +227,10 @@ const mobileStyles = css`
props.theme.avatarEditorBody.container.zoom.mobileHeight};
margin-top: ${(props) =>
props.theme.avatarEditorBody.container.zoom.marginTop};
.zoom-container-svg_zoom-minus,
.zoom-container-svg_zoom-plus {
margin: auto 0;
}
}
}
}
@ -299,6 +306,9 @@ const StyledAvatarContainer = styled.div`
background: ${(props) =>
props.theme.avatarEditorBody.container.buttons.background};
justify-items: center;
.editor-button {
margin: auto 0;
}
}
.zoom-container {
@ -307,6 +317,10 @@ const StyledAvatarContainer = styled.div`
display: grid;
grid-template-columns: min-content 1fr min-content;
grid-column-gap: 12px;
.zoom-container-svg_zoom-minus,
.zoom-container-svg_zoom-plus {
margin: auto 0;
}
}
}
}

View File

@ -45,6 +45,7 @@ class ContextMenuSub extends Component {
if (item.onClick) {
item.onClick({
originalEvent: e,
action: item.action,
});
}
@ -201,6 +202,7 @@ class ContextMenuSub extends Component {
}
renderItem(item, index) {
if (!item) return null;
if (item.isSeparator) return this.renderSeparator(index);
else return this.renderMenuitem(item, index);
}

View File

@ -101,7 +101,10 @@ const StyledContextMenu = styled.div`
.p-menuitem-icon {
max-height: ${(props) => props.theme.dropDownItem.lineHeight};
& svg {
height: 16px;
width: 16px;
}
path {
fill: ${(props) => props.theme.dropDownItem.icon.color};
}

View File

@ -23,7 +23,7 @@ const DragAndDrop = (props) => {
className={`drag-and-drop ${classNameProp}`}
dragging={dragging}
isDragAccept={isDragActive}
drag={isDragActive && isDropZone}
drag={isDragActive && isDropZone && props.onDrop}
{...getRootProps()}
>
{children}

View File

@ -243,6 +243,15 @@ class PasswordInput extends React.Component {
return !equal(this.props, nextProps) || !equal(this.state, nextState);
}
componentDidUpdate(prevProps, prevState) {
if (
prevProps.clipActionResource !== this.props.clipActionResource &&
this.state.copyLabel !== this.props.clipCopiedResource
) {
this.setState({ copyLabel: this.props.clipActionResource });
}
}
renderTextTooltip = (settings, length, digits, capital, special) => {
return (
<>
@ -415,6 +424,7 @@ class PasswordInput extends React.Component {
hideNewPasswordButton,
isDisabled,
} = this.props;
const { copyLabel, disableCopyAction } = this.state;
return (

View File

@ -1,6 +1,6 @@
{
"name": "@appserver/crm",
"version": "0.1.0",
"version": "0.1.2",
"private": "true",
"homepage": "/products/crm",
"title": "ONLYOFFICE",

View File

@ -2,46 +2,8 @@ import App from "./App";
import React from "react";
import ReactDOM from "react-dom";
import config from "../package.json";
import { Workbox, messageSW } from "workbox-window";
import { registerSW } from "@appserver/common/utils/sw-helper";
ReactDOM.render(<App />, document.getElementById("root"));
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
const wb = new Workbox(`${config.homepage}/sw.js`);
//TODO: watch https://developers.google.com/web/tools/workbox/guides/advanced-recipes and https://github.com/webmaxru/prog-web-news/blob/5ff94b45c9d317409c21c0fbb7d76e92f064471b/src/app/app-shell/app-shell.component.ts
// const showSkipWaitingPrompt = (event) => {
// let snackBarRef = this.snackBar.open(
// "A new version of the website available",
// "Reload page",
// {
// duration: 5000,
// }
// );
// // Displaying prompt
// snackBarRef.onAction().subscribe(() => {
// // Assuming the user accepted the update, set up a listener
// // that will reload the page as soon as the previously waiting
// // service worker has taken control.
// wb.addEventListener("controlling", () => {
// window.location.reload();
// });
// // This will postMessage() to the waiting service worker.
// wb.messageSkipWaiting();
// });
// };
// // Add an event listener to detect when the registered
// // service worker has installed but is waiting to activate.
// wb.addEventListener("waiting", showSkipWaitingPrompt);
wb.register()
.then((reg) => {
console.log("Successful service worker registration", reg);
})
.catch((err) => console.error("Service worker registration failed", err));
}
registerSW(config.homepage);

View File

@ -19,6 +19,7 @@ import { setDocumentTitle } from "../../helpers/utils";
import { inject } from "mobx-react";
import i18n from "../../i18n";
import { I18nextProvider } from "react-i18next";
import { combineUrl, deleteCookie } from "@appserver/common/utils";
const commonStyles = `
.link-box {
@ -90,12 +91,13 @@ const StyledDesktopContainer = styled(EmptyScreenContainer)`
}
`;
const ExternalLink = ({ label, href }) => (
const ExternalLink = ({ label, href, onClick }) => (
<Box className="link-box">
<ExternalLinkIcon color="#333333" size={isMobile ? "small" : "medium"} />
<Link
as="a"
href={href}
onClick={onClick}
target="_blank"
className="view-web-link"
color="#555F65"
@ -122,7 +124,10 @@ const Body = ({ modules, match, isLoaded, setCurrentProductId }) => {
helpUrl,
} = currentModule;
const url = originUrl ? originUrl : link;
const webLink = protocol + "//" + hostname + url;
const webLink = combineUrl(
protocol + "//" + hostname,
`${url}?desktop_view=true`
);
const appLink = isIOS
? id === "2A923037-8B2D-487b-9A22-5AC0918ACF3F"
? "message:"
@ -147,7 +152,13 @@ const Body = ({ modules, match, isLoaded, setCurrentProductId }) => {
borderRadius="2px"
className="coming-soon-badge"
/>
<ExternalLink label={t("ViewWeb")} href={webLink} />
<ExternalLink
label={t("ViewWeb")}
onClick={() => {
deleteCookie("desktop_view");
window.open(webLink, "_self", "", true);
}}
/>
{appLink && (
<ExternalLink
label={t("OpenApp", {

View File

@ -77,7 +77,7 @@ namespace ASC.CRM.Configuration
public override string StartURL { get { return PathProvider.StartURL(); } }
public override string HelpURL { get { return string.Concat(PathProvider.BaseVirtualPath, "Help.aspx"); } }
public override string HelpURL { get { return "https://helpcenter.onlyoffice.com/userguides/crm.aspx"; } }
public override string ProductClassName { get { return "crm"; } }

View File

@ -1,6 +1,6 @@
{
"name": "@appserver/files",
"version": "0.1.0",
"version": "0.1.2",
"private": "true",
"homepage": "/products/files",
"id": "e67be73d-f9ae-4ce1-8fec-1880cb518cb4",

View File

@ -127,5 +127,7 @@
"ThirdPartyInfo": "Change the third party info",
"EmptyFile": "Empty file",
"DeleteSelectedElem": "Selected elements were successfully deleted",
"DeleteFromTrash": "Selected elements were successfully deleted from trash"
"DeleteFromTrash": "Selected elements were successfully deleted from trash",
"New": "New",
"Version": "Ver.{{version}}"
}

View File

@ -127,5 +127,7 @@
"ThirdPartyInfo": "Изменить настройки подключения",
"EmptyFile": "Пустой файл",
"DeleteSelectedElem": "Выбранные элементы успешно удалены",
"DeleteFromTrash": "Выбранные элементы успешно удалены из корзины"
"DeleteFromTrash": "Выбранные элементы успешно удалены из корзины",
"New": "Новое",
"Version": "Вер.{{version}}"
}

View File

@ -2,46 +2,8 @@ import App from "./App";
import React from "react";
import ReactDOM from "react-dom";
import config from "../package.json";
import { Workbox, messageSW } from "workbox-window";
import { registerSW } from "@appserver/common/utils/sw-helper";
ReactDOM.render(<App />, document.getElementById("root"));
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
const wb = new Workbox(`${config.homepage}/sw.js`);
//TODO: watch https://developers.google.com/web/tools/workbox/guides/advanced-recipes and https://github.com/webmaxru/prog-web-news/blob/5ff94b45c9d317409c21c0fbb7d76e92f064471b/src/app/app-shell/app-shell.component.ts
// const showSkipWaitingPrompt = (event) => {
// let snackBarRef = this.snackBar.open(
// "A new version of the website available",
// "Reload page",
// {
// duration: 5000,
// }
// );
// // Displaying prompt
// snackBarRef.onAction().subscribe(() => {
// // Assuming the user accepted the update, set up a listener
// // that will reload the page as soon as the previously waiting
// // service worker has taken control.
// wb.addEventListener("controlling", () => {
// window.location.reload();
// });
// // This will postMessage() to the waiting service worker.
// wb.messageSkipWaiting();
// });
// };
// // Add an event listener to detect when the registered
// // service worker has installed but is waiting to activate.
// wb.addEventListener("waiting", showSkipWaitingPrompt);
wb.register()
.then((reg) => {
console.log("Successful service worker registration", reg);
})
.catch((err) => console.error("Service worker registration failed", err));
}
registerSW(config.homepage);

View File

@ -148,7 +148,7 @@ class TreeFolders extends React.Component {
isAdmin,
myId,
commonId,
rootFolderType,
//rootFolderType,
currentId,
draggableItems,
} = this.props;
@ -158,9 +158,9 @@ class TreeFolders extends React.Component {
if (draggableItems.find((x) => x.id === item.id)) return false;
const isMy = rootFolderType === FolderType.USER;
const isCommon = rootFolderType === FolderType.COMMON;
const isShare = rootFolderType === FolderType.SHARE;
// const isMy = rootFolderType === FolderType.USER;
// const isCommon = rootFolderType === FolderType.COMMON;
// const isShare = rootFolderType === FolderType.SHARE;
if (
item.rootFolderType === FolderType.SHARE &&
@ -170,25 +170,25 @@ class TreeFolders extends React.Component {
}
if (isAdmin) {
if (isMy || isCommon || isShare) {
if (
(item.pathParts &&
(item.pathParts[0] === myId || item.pathParts[0] === commonId)) ||
item.rootFolderType === FolderType.USER ||
item.rootFolderType === FolderType.COMMON
) {
return true;
}
//if (isMy || isCommon || isShare) {
if (
(item.pathParts &&
(item.pathParts[0] === myId || item.pathParts[0] === commonId)) ||
item.rootFolderType === FolderType.USER ||
item.rootFolderType === FolderType.COMMON
) {
return true;
}
//}
} else {
if (isMy || isCommon || isShare) {
if (
(item.pathParts && item.pathParts[0] === myId) ||
item.rootFolderType === FolderType.USER
) {
return true;
}
//if (isMy || isCommon || isShare) {
if (
(item.pathParts && item.pathParts[0] === myId) ||
item.rootFolderType === FolderType.USER
) {
return true;
}
//}
}
return false;
@ -489,13 +489,13 @@ export default inject(
expandedKeys,
setExpandedKeys,
} = treeFoldersStore;
const { id, rootFolderType } = selectedFolderStore;
const { id /* rootFolderType */ } = selectedFolderStore;
return {
isAdmin: auth.isAdmin,
isDesktop: auth.settingsStore.isDesktopClient,
dragging,
rootFolderType,
//rootFolderType,
currentId: id,
myId: myFolderId,
commonId: commonFolderId,

View File

@ -132,7 +132,8 @@ export default inject(
const { fetchFiles, filter, setIsLoading } = filesStore;
const { treeFolders, setSelectedNode, setTreeFolders } = treeFoldersStore;
const selectedTreeNode =
treeFoldersStore.selectedTreeNode.length > 0
treeFoldersStore.selectedTreeNode.length > 0 &&
treeFoldersStore.selectedTreeNode[0] !== "@my"
? treeFoldersStore.selectedTreeNode
: [selectedFolderStore.id + ""];

View File

@ -125,7 +125,7 @@ const ThirdPartyDialog = (props) => {
<Text as="div">
{t("ConnectDescription")}
{isAdmin && (
<Trans i18nKey="ConnectAdminDescription" ns="Settings">
<Trans t={t} i18nKey="ConnectAdminDescription" ns="Settings">
For successful connection enter the necessary data at
<Link isHovered href="/settings/integration/third-party-services">
this page

View File

@ -110,7 +110,7 @@ const RootFolderContainer = (props) => {
</Text>
{!isDesktop && (
<Text fontSize="12px">
<Trans i18nKey="PrivateRoomSupport" ns="Home">
<Trans t={t} i18nKey="PrivateRoomSupport" ns="Home">
Work in Private Room is available via {{ organizationName }} desktop
app.{" "}
<Link isBold isHovered color="#116d9d" href={privacyInstructions}>

View File

@ -87,7 +87,10 @@ class FilesContent extends React.Component {
}
completeAction = (id) => {
this.props.editCompleteAction(id, this.props.item);
const isCancel =
(id.currentTarget && id.currentTarget.dataset.action === "cancel") ||
id.keyCode === 27;
this.props.editCompleteAction(id, this.props.item, isCancel);
};
updateItem = () => {
@ -97,20 +100,23 @@ class FilesContent extends React.Component {
item,
setIsLoading,
fileActionId,
editCompleteAction,
} = this.props;
const { itemTitle } = this.state;
const originalTitle = getTitleWithoutExst(item);
setIsLoading(true);
if (originalTitle === itemTitle || itemTitle.trim() === "") {
const isSameTitle =
originalTitle.trim() === itemTitle.trim() || itemTitle.trim() === "";
if (isSameTitle) {
this.setState({
itemTitle: originalTitle,
});
return this.completeAction(fileActionId);
return editCompleteAction(fileActionId, item, isSameTitle);
}
item.fileExst
item.fileExst || item.contentLength
? updateFile(fileActionId, itemTitle)
.then(() => this.completeAction(fileActionId))
.finally(() => setIsLoading(false))
@ -155,12 +161,12 @@ class FilesContent extends React.Component {
)
: null;
!item.fileExst
!item.fileExst && !item.contentLength
? createFolder(item.parentId, itemTitle)
.then(() => this.completeAction(itemId))
.then(() =>
toastr.success(
<Trans i18nKey="FolderCreated" ns="Home">
<Trans t={t} i18nKey="FolderCreated" ns="Home">
New folder {{ itemTitle }} is created
</Trans>
)
@ -245,11 +251,11 @@ class FilesContent extends React.Component {
addExpandedKeys,
setMediaViewerData,
} = this.props;
const { id, fileExst, viewUrl, providerKey } = item;
const { id, fileExst, viewUrl, providerKey, contentLength } = item;
if (isTrashFolder) return;
if (!fileExst) {
if (!fileExst && !contentLength) {
setIsLoading(true);
if (!expandedKeys.includes(parentFolder + "")) {
@ -322,7 +328,9 @@ class FilesContent extends React.Component {
setIsVerHistoryPanel,
fetchFileVersions,
history,
isTrashFolder,
} = this.props;
if (isTrashFolder) return;
if (!isTabletView) {
fetchFileVersions(item.id + "");

View File

@ -124,14 +124,17 @@ const SectionBodyContent = (props) => {
const onDragOver = (e) => {
e.preventDefault();
if (e.dataTransfer.items.length > 0 && !dragging) {
if (
e.dataTransfer.items.length > 0 &&
e.dataTransfer.dropEffect !== "none"
) {
setDragging(true);
}
};
const onDragLeaveDoc = (e) => {
e.preventDefault();
if (dragging && !e.relatedTarget) {
if (!e.relatedTarget || !e.dataTransfer.items.length) {
setDragging(false);
}
};

View File

@ -145,6 +145,7 @@ const EditingWrapperComponent = (props) => {
onClick={cancelUpdateItem}
icon={CancelIcon}
data-itemid={itemId}
data-action="cancel"
onMouseEnter={setIsHoveredCancelHandler}
onMouseLeave={setIsHoveredCancelHandler}
isHovered={CancelIconIsHovered}

View File

@ -504,7 +504,7 @@ class SectionHeaderContent extends React.Component {
<ContextMenuButton
className="add-button"
directionX="right"
iconName="images/actions.header.touch.react.svg"
iconName="images/plus.svg"
size={17}
color="#A3A9AE"
hoverColor="#657077"
@ -529,7 +529,7 @@ class SectionHeaderContent extends React.Component {
<ContextMenuButton
className="add-button"
directionX="right"
iconName="images/actions.header.touch.react.svg"
iconName="images/plus.svg"
size={17}
color="#A3A9AE"
hoverColor="#657077"

View File

@ -136,30 +136,31 @@ class PureHome extends React.Component {
};
showOperationToast = (type, qty, title) => {
const { t } = this.props;
switch (type) {
case "move":
if (qty > 1) {
return toastr.success(
<Trans i18nKey="MoveItems" ns="Home">
<Trans t={t} i18nKey="MoveItems" ns="Home">
{{ qty }} elements has been moved
</Trans>
);
}
return toastr.success(
<Trans i18nKey="MoveItem" ns="Home">
<Trans t={t} i18nKey="MoveItem" ns="Home">
{{ title }} moved
</Trans>
);
case "duplicate":
if (qty > 1) {
return toastr.success(
<Trans i18nKey="CopyItems" ns="Home">
<Trans t={t} i18nKey="CopyItems" ns="Home">
{{ qty }} elements copied
</Trans>
);
}
return toastr.success(
<Trans i18nKey="CopyItem" ns="Home">
<Trans t={t} i18nKey="CopyItem" ns="Home">
{{ title }} copied
</Trans>
);
@ -170,6 +171,10 @@ class PureHome extends React.Component {
showUploadPanel = () => {
this.props.setUploadPanelVisible(!this.props.uploadPanelVisible);
this.props.primaryProgressDataVisible &&
this.props.uploaded &&
this.props.clearPrimaryProgressData();
};
componentDidUpdate(prevProps) {
const {
@ -209,6 +214,7 @@ class PureHome extends React.Component {
fileActionId,
firstLoad,
isHeaderVisible,
isRecycleBinFolder,
primaryProgressDataVisible,
primaryProgressDataPercent,
@ -235,7 +241,7 @@ class PureHome extends React.Component {
withBodyScroll
withBodyAutoFocus={!isMobile}
uploadFiles
onDrop={this.onDrop}
onDrop={isRecycleBinFolder ? null : this.onDrop}
setSelections={this.props.setSelections}
onMouseMove={this.onMouseMove}
showPrimaryProgressBar={primaryProgressDataVisible}
@ -298,6 +304,7 @@ export default inject(
uploadDataStore,
dialogsStore,
selectedFolderStore,
treeFoldersStore,
}) => {
const {
secondaryProgressDataStore,
@ -319,12 +326,14 @@ export default inject(
} = filesStore;
const { id } = fileActionStore;
const { isRecycleBinFolder } = treeFoldersStore;
const {
visible: primaryProgressDataVisible,
percent: primaryProgressDataPercent,
icon: primaryProgressDataIcon,
alert: primaryProgressDataAlert,
clearPrimaryProgressData,
} = primaryProgressDataStore;
const {
@ -337,7 +346,7 @@ export default inject(
const { convertDialogVisible } = dialogsStore;
const { setUploadPanelVisible, startUpload } = uploadDataStore;
const { setUploadPanelVisible, startUpload, uploaded } = uploadDataStore;
const selectionLength = isProgressFinished ? selection.length : null;
const selectionTitle = isProgressFinished
@ -353,11 +362,14 @@ export default inject(
isLoading,
filter,
viewAs,
uploaded,
isRecycleBinFolder,
primaryProgressDataVisible,
primaryProgressDataPercent,
primaryProgressDataIcon,
primaryProgressDataAlert,
clearPrimaryProgressData,
secondaryProgressDataStoreVisible,
secondaryProgressDataStorePercent,

View File

@ -161,46 +161,42 @@ const SectionBodyContent = ({
);
};
export default inject(
({ auth, filesStore, settingsStore, treeFoldersStore }) => {
const { isLoading } = filesStore;
const { selectedTreeNode } = treeFoldersStore;
const {
isLoadedSettingsTree,
storeOriginalFiles,
confirmDelete,
updateIfExist,
forcesave,
storeForcesave,
enableThirdParty,
setUpdateIfExist,
setStoreOriginal,
setEnableThirdParty,
setConfirmDelete,
setStoreForceSave,
setForceSave,
settingsIsLoaded,
} = settingsStore;
export default inject(({ auth, filesStore, settingsStore }) => {
const { isLoading } = filesStore;
const {
isLoadedSettingsTree,
storeOriginalFiles,
confirmDelete,
updateIfExist,
forcesave,
storeForcesave,
enableThirdParty,
setUpdateIfExist,
setStoreOriginal,
setEnableThirdParty,
setConfirmDelete,
setStoreForceSave,
setForceSave,
settingsIsLoaded,
} = settingsStore;
return {
isAdmin: auth.isAdmin,
isLoading,
selectedTreeNode,
isLoadedSettingsTree,
storeOriginalFiles,
confirmDelete,
updateIfExist,
forceSave: forcesave,
storeForceSave: storeForcesave,
enableThirdParty,
return {
isAdmin: auth.isAdmin,
isLoading,
isLoadedSettingsTree,
storeOriginalFiles,
confirmDelete,
updateIfExist,
forceSave: forcesave,
storeForceSave: storeForcesave,
enableThirdParty,
setUpdateIfExist,
setStoreOriginal,
setEnableThirdParty,
setConfirmDelete,
setStoreForceSave,
setForceSave,
settingsIsLoaded,
};
}
)(observer(SectionBodyContent));
setUpdateIfExist,
setStoreOriginal,
setEnableThirdParty,
setConfirmDelete,
setStoreForceSave,
setForceSave,
settingsIsLoaded,
};
})(observer(SectionBodyContent));

View File

@ -176,8 +176,10 @@ class NewFilesPanelComponent extends React.Component {
dataItem = data.find((x) => x.id === +folderPath[0]);
dataItem.newItems = markAsReadAll ? 0 : dataItem.newItems - 1;
if (item && item.fileExst) {
const fileItem = files.find((x) => x.id === item.id && x.fileExst);
if (item && (item.fileExst || item.contentLength)) {
const fileItem = files.find(
(x) => x.id === item.id && (x.fileExst || item.contentLength)
);
if (fileItem) {
fileItem.new = markAsReadAll ? 0 : fileItem.new - 1;
} else {

View File

@ -68,7 +68,7 @@ const OperationsPanelComponent = (props) => {
const folderIds = [];
for (let item of items) {
if (item.fileExst) {
if (item.fileExst || item.contentLength) {
fileIds.push(item.id);
} else if (item.id === destFolderId) {
toastr.error(t("MoveToFolderMessage"));

View File

@ -77,13 +77,14 @@ class SharingRow extends React.Component {
onShowEmbeddingPanel,
onToggleLink,
externalLinkData,
canShareOwnerChange,
onShowChangeOwnerPanel,
isLoading,
internalLink,
} = this.props;
const { access } = this.state;
const canShareOwnerChange = this.props.canShareOwnerChange(item);
const { isOwner, isLocked } = item;
const { label, displayName, name, shareLink, id } = item.sharedTo;
const userName = name

View File

@ -187,7 +187,11 @@ class SharingPanelComponent extends React.Component {
return replaceFileStream(item.id, encryptedFile, true, true).then(
() =>
toastr.success(
<Trans i18nKey="EncryptedFileSharing" ns="SharingPanel">
<Trans
t={t}
i18nKey="EncryptedFileSharing"
ns="SharingPanel"
>
File {{ title }} successfully shared
</Trans>
)

View File

@ -1,5 +1,5 @@
import React from "react";
import CustomScrollbarsVirtualList from "@appserver/components/scrollbar";
import CustomScrollbarsVirtualList from "@appserver/components/scrollbar/custom-scrollbars-virtual-list";
import AutoSizer from "react-virtualized-auto-sizer";
import { FixedSizeList as List } from "react-window";
import RowWrapper from "./RowWrapper";
@ -17,7 +17,7 @@ const FileList = ({ uploadDataFiles }) => {
width={width}
itemData={uploadDataFiles}
itemCount={uploadDataFiles.length}
itemSize={46}
itemSize={56}
outerElementType={CustomScrollbarsVirtualList}
>
{RowWrapper}

View File

@ -15,6 +15,11 @@ const StyledFileRow = styled(Row)`
box-sizing: border-box;
font-weight: 600;
.row_content > a,
.row_content > p {
margin: auto 0;
}
.upload_panel-icon {
margin-left: auto;
padding-left: 16px;

View File

@ -14,8 +14,6 @@ import {
import FileList from "./FileList";
import { inject, observer } from "mobx-react";
const DownloadBodyStyle = { height: `calc(100vh - 62px)` };
class UploadPanelComponent extends React.Component {
constructor(props) {
super(props);
@ -60,6 +58,7 @@ class UploadPanelComponent extends React.Component {
t,
uploadPanelVisible,
/* sharingPanelVisible, */ uploaded,
uploadDataFiles,
} = this.props;
const visible = uploadPanelVisible;
@ -111,7 +110,11 @@ class UploadPanelComponent extends React.Component {
<StyledBody
stype="mediumBlack"
className="upload-panel_body"
style={DownloadBodyStyle}
style={
uploadDataFiles.length > 15
? { height: `100vh` }
: { height: `calc(100vh - 130px)` }
}
>
<FileList />
</StyledBody>
@ -134,6 +137,7 @@ export default inject(({ dialogsStore, uploadDataStore }) => {
cancelUpload,
uploadPanelVisible,
setUploadPanelVisible,
files,
} = uploadDataStore;
return {
@ -144,5 +148,6 @@ export default inject(({ dialogsStore, uploadDataStore }) => {
setUploadPanelVisible,
clearUploadData,
cancelUpload,
uploadDataFiles: files,
};
})(observer(UploadPanel));

View File

@ -60,7 +60,7 @@ class FilesActionStore {
let i = 0;
while (selection.length !== i) {
if (selection[i].fileExst) {
if (selection[i].fileExst || selection[i].contentLength) {
fileIds.push(selection[i].id);
} else {
folderIds.push(selection[i].id);
@ -225,7 +225,7 @@ class FilesActionStore {
});
};
editCompleteAction = (id, selectedItem) => {
editCompleteAction = async (id, selectedItem, isCancelled = false) => {
const {
filter,
folders,
@ -241,22 +241,21 @@ class FilesActionStore {
const item = items.find((o) => o.id === id && !o.fileExst); //TODO: maybe need files find and folders find, not at one function?
if (type === FileAction.Create || type === FileAction.Rename) {
setIsLoading(true);
fetchFiles(this.selectedFolderStore.id, filter)
.then((data) => {
const newItem = (item && item.id) === -1 ? null : item; //TODO: not add new folders?
if (!selectedItem.fileExst) {
const path = data.selectedFolder.pathParts;
const newTreeFolders = treeFolders;
const folders = data.selectedFolder.folders;
loopTreeFolders(path, newTreeFolders, folders, null, newItem);
setTreeFolders(newTreeFolders);
}
})
.finally(() => {
setAction({ type: null, id: null, extension: null });
setIsLoading(false);
type === FileAction.Rename && this.onSelectItem(selectedItem);
});
if (!isCancelled) {
const data = await fetchFiles(this.selectedFolderStore.id, filter);
const newItem = (item && item.id) === -1 ? null : item; //TODO: not add new folders?
if (!selectedItem.fileExst && !selectedItem.contentLength) {
const path = data.selectedFolder.pathParts;
const newTreeFolders = treeFolders;
const folders = data.selectedFolder.folders;
loopTreeFolders(path, newTreeFolders, folders, null, newItem);
setTreeFolders(newTreeFolders);
}
}
setAction({ type: null, id: null, extension: null });
setIsLoading(false);
type === FileAction.Rename && this.onSelectItem(selectedItem);
}
};

View File

@ -120,7 +120,6 @@ class FilesStore {
initFiles = () => {
if (this.isInit) return;
this.isInit = true;
const { isAuthenticated } = this.authStore;
const {
@ -153,7 +152,7 @@ class FilesStore {
}
}
return Promise.all(requests);
return Promise.all(requests).then(() => (this.isInit = true));
};
setFirstLoad = (firstLoad) => {
@ -292,41 +291,59 @@ class FilesStore {
}
}
return api.files.getFolder(folderId, filter).then((data) => {
const isPrivacyFolder =
data.current.rootFolderType === FolderType.Privacy;
//TODO: fix @my
let requestCounter = 1;
const request = () =>
api.files
.getFolder(folderId, filter)
.then((data) => {
const isPrivacyFolder =
data.current.rootFolderType === FolderType.Privacy;
const newExpandedKeys = createTreeFolders(data.pathParts, expandedKeys);
setExpandedKeys(newExpandedKeys);
filterData.total = data.total;
this.setFilesFilter(filterData); //TODO: FILTER
this.setFolders(
isPrivacyFolder && !this.settingsStore.isEncryptionSupport
? []
: data.folders
);
this.setFiles(
isPrivacyFolder && !this.settingsStore.isEncryptionSupport
? []
: data.files
);
if (clearFilter) {
this.fileActionStore.setAction({ type: null });
this.setSelected("close");
}
const newExpandedKeys = createTreeFolders(
data.pathParts,
expandedKeys
);
setExpandedKeys(newExpandedKeys);
filterData.total = data.total;
this.setFilesFilter(filterData); //TODO: FILTER
this.setFolders(
isPrivacyFolder && !this.settingsStore.isEncryptionSupport
? []
: data.folders
);
this.setFiles(
isPrivacyFolder && !this.settingsStore.isEncryptionSupport
? []
: data.files
);
if (clearFilter) {
this.fileActionStore.setAction({ type: null });
this.setSelected("close");
}
this.selectedFolderStore.setSelectedFolder({
folders: data.folders,
...data.current,
pathParts: data.pathParts,
...{ new: data.new },
});
this.selectedFolderStore.setSelectedFolder({
folders: data.folders,
...data.current,
pathParts: data.pathParts,
...{ new: data.new },
});
const selectedFolder = {
selectedFolder: { ...this.selectedFolderStore },
};
return Promise.resolve(selectedFolder);
});
const selectedFolder = {
selectedFolder: { ...this.selectedFolderStore },
};
return Promise.resolve(selectedFolder);
})
.catch(() => {
if (folderId === "@my" && requestCounter !== 0 && !this.isInit) {
requestCounter--;
setTimeout(() => {
return request();
}, 5000);
}
});
return request();
};
isFileSelected = (selection, fileId, parentId) => {
@ -355,7 +372,7 @@ class FilesStore {
const isVisitor =
(this.userStore.user && this.userStore.user.isVisitor) || false;
const isFile = !!item.fileExst;
const isFile = !!item.fileExst || item.contentLength;
const isFavorite = item.fileStatus === 32;
const isFullAccess = item.access < 2;
const isThirdPartyFolder =
@ -367,11 +384,12 @@ class FilesStore {
isRecycleBinFolder,
isPrivacyFolder,
isRecentFolder,
isShareFolder,
} = this.treeFoldersStore;
if (isRecycleBinFolder) {
options.push("download");
options.push("download-as");
isFile && options.push("download-as");
options.push("restore");
options.push("separator0");
options.push("delete");
@ -406,6 +424,16 @@ class FilesStore {
}
this.canShareOwnerChange(item) && options.push("owner-change");
if (isFile) {
if (canOpenPlayer) {
options.push("view");
} else {
options.push("edit");
options.push("preview");
}
}
options.push("link-for-portal-users");
if (!isVisitor) {
@ -428,39 +456,36 @@ class FilesStore {
options.push("mark-as-favorite");
}
} else {
options.push("separator3");
!isShareFolder && options.push("separator3");
}
if (canOpenPlayer) {
options.push("view");
} else {
options.push("edit");
options.push("preview");
}
options.push("download");
}
options.push("download");
if (!isVisitor) {
!isThirdPartyFolder && this.userAccess && options.push("move");
options.push("copy");
if (isFile) {
options.push("duplicate");
}
// if (isFile) {
// options.push("duplicate");
// }
this.userAccess && options.push("rename");
isThirdPartyFolder &&
this.userAccess &&
options.push("change-thirdparty-info");
options.push("separator3");
this.userAccess && options.push("delete");
if (this.userAccess) {
options.push("separator3");
options.push("delete");
}
} else {
options.push("copy");
}
}
if (isFavorite && !isRecycleBinFolder) {
!this.userAccess && options.push("separator3");
options.push("remove-from-favorites");
}
@ -516,7 +541,7 @@ class FilesStore {
};
canShareOwnerChange = (item) => {
const userId = this.userStore.user.id;
const userId = this.userStore.user && this.userStore.user.id;
const isCommonFolder =
this.treeFoldersStore.commonFolder &&
this.selectedFolderStore.pathParts &&
@ -683,7 +708,7 @@ class FilesStore {
const contextOptions = this.getFilesContextOptions(item, canOpenPlayer);
//const isCanWebEdit = canWebEdit(item.fileExst);
const icon = getIcon(24, fileExst, providerKey);
const icon = getIcon(24, fileExst, providerKey, contentLength);
let isFolder = false;
this.folders.map((x) => {

View File

@ -172,8 +172,13 @@ class IconFormatsStore {
isSpreadsheet = (extension) => presentInArray(this.spreadsheet, extension);
getIcon = (size = 24, fileExst = null, providerKey = null) => {
if (fileExst) {
getIcon = (
size = 24,
fileExst = null,
providerKey = null,
contentLength = null
) => {
if (fileExst || contentLength) {
const isArchiveItem = this.isArchive(fileExst);
const isImageItem = this.isImage(fileExst);
const isSoundItem = this.isSound(fileExst);

View File

@ -567,7 +567,7 @@ class UploadDataStore {
if (totalErrorsCount > 0) console.log("Errors: ", totalErrorsCount);
const uploadData = {
files: this.uploadPanelVisible ? this.files : [],
files: this.files,
filesSize: 0,
uploadStatus: null,
uploadedFiles: 0,
@ -576,7 +576,8 @@ class UploadDataStore {
};
setTimeout(() => {
this.primaryProgressDataStore.clearPrimaryProgressData();
!this.primaryProgressDataStore.alert &&
this.primaryProgressDataStore.clearPrimaryProgressData();
this.setUploadData(uploadData);
}, TIMEOUT);
};

View File

@ -5,8 +5,9 @@ class VersionHistoryStore {
isVisible = false;
fileId = null;
versions = null;
filesStore = null;
constructor() {
constructor(filesStore) {
makeObservable(this, {
isVisible: observable,
fileId: observable,
@ -19,6 +20,7 @@ class VersionHistoryStore {
restoreVersion: action,
updateCommentVersion: action,
});
this.filesStore = filesStore;
}
setIsVerHistoryPanel = (isVisible) => {
@ -32,6 +34,26 @@ class VersionHistoryStore {
//setFileVersions
setVerHistoryFileVersions = (versions) => {
const file = this.filesStore.files.find((item) => item.id == this.fileId);
const currentVersionGroup = Math.max.apply(
null,
versions.map((ver) => ver.versionGroup)
);
if (
versions.length !== file.version ||
currentVersionGroup !== file.versionGroup
) {
const newFile = {
...file,
version: versions.length,
versionGroup: currentVersionGroup,
};
this.filesStore.setFile(newFile);
}
this.versions = versions;
};
@ -76,4 +98,4 @@ class VersionHistoryStore {
};
}
export default new VersionHistoryStore();
export default VersionHistoryStore;

View File

@ -15,7 +15,7 @@ import SecondaryProgressDataStore from "./SecondaryProgressDataStore";
import PrimaryProgressDataStore from "./PrimaryProgressDataStore";
import ContextOptionsStore from "./ContextOptionsStore";
import versionHistoryStore from "./VersionHistoryStore";
import VersionHistoryStore from "./VersionHistoryStore";
import dialogsStore from "./DialogsStore";
import store from "studio/store";
@ -57,7 +57,7 @@ const filesActionsStore = new FilesActionsStore(
);
const mediaViewerDataStore = new MediaViewerDataStore(filesStore);
const versionHistoryStore = new VersionHistoryStore(filesStore);
const contextOptionsStore = new ContextOptionsStore(
filesStore,
fileActionStore,

View File

@ -1319,29 +1319,25 @@ namespace ASC.Files.Core.Data
protected IQueryable<DbFileQuery> FromQueryWithShared(IQueryable<DbFile> dbFiles)
{
return dbFiles
.Select(r => new DbFileQuery
{
File = r,
Root =
FilesDbContext.Folders
.Join(FilesDbContext.Tree, a => a.Id, b => b.ParentId, (folder, tree) => new { folder, tree })
.Where(x => x.folder.TenantId == r.TenantId)
.Where(x => x.tree.FolderId == r.FolderId)
.OrderByDescending(r => r.tree.Level)
.Select(r => new DbFolder
{
FolderType = r.folder.FolderType,
CreateBy = r.folder.CreateBy,
Id = r.folder.Id
})
.FirstOrDefault(),
Shared =
FilesDbContext.Security
.Any(x=> x.TenantId == TenantID &&
x.EntryType == FileEntryType.File &&
x.EntryId == r.Id.ToString())
});
return from r in dbFiles
select new DbFileQuery
{
File = r,
Root = (from f in FilesDbContext.Folders
where f.Id ==
(from t in FilesDbContext.Tree
where t.FolderId == r.FolderId
orderby t.Level descending
select t.ParentId
).FirstOrDefault()
where f.TenantId == r.TenantId
select f
).FirstOrDefault(),
Shared = (from f in FilesDbContext.Security
where f.EntryType == FileEntryType.File && f.EntryId == r.Id.ToString() && f.TenantId == r.TenantId
select f
).Any()
};
}
protected IQueryable<DbFileQuery> FromQuery(IQueryable<DbFile> dbFiles)

View File

@ -1044,24 +1044,25 @@ namespace ASC.Files.Core.Data
protected IQueryable<DbFolderQuery> FromQueryWithShared(IQueryable<DbFolder> dbFiles)
{
return dbFiles
.Select(r => new DbFolderQuery
{
Folder = r,
Root = FilesDbContext.Folders
.Join(FilesDbContext.Tree, a => a.Id, b => b.ParentId, (folder, tree) => new { folder, tree })
.Where(x => x.folder.TenantId == r.TenantId && x.tree.FolderId == r.ParentId)
.OrderByDescending(r => r.tree.Level)
.Select(r => new DbFolder
{
FolderType = r.folder.FolderType,
CreateBy = r.folder.CreateBy,
Id = r.folder.Id
})
.FirstOrDefault(),
Shared = FilesDbContext.Security
.Any(x => x.TenantId == TenantID && x.EntryType == FileEntryType.Folder && x.EntryId == r.Id.ToString())
});
return from r in dbFiles
select new DbFolderQuery
{
Folder = r,
Root = (from f in FilesDbContext.Folders
where f.Id ==
(from t in FilesDbContext.Tree
where t.FolderId == r.ParentId
orderby t.Level descending
select t.ParentId
).FirstOrDefault()
where f.TenantId == r.TenantId
select f
).FirstOrDefault(),
Shared = (from f in FilesDbContext.Security
where f.EntryType == FileEntryType.Folder && f.EntryId == r.Id.ToString() && f.TenantId == r.TenantId
select f
).Any()
};
}
protected IQueryable<DbFolderQuery> FromQuery(IQueryable<DbFolder> dbFiles)

View File

@ -11,6 +11,7 @@
<Copyright>(c) Ascensio System SIA. All rights reserved</Copyright>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<EnableNETAnalyzers>false</EnableNETAnalyzers>
<EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>full</DebugType>
@ -20,11 +21,11 @@
<Optimize>true</Optimize>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.4">
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.4">
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

View File

@ -22,7 +22,7 @@
<PackageReference Include="Google.Apis.Drive.v3" Version="1.49.0.2111" />
<PackageReference Include="Google.Protobuf" Version="3.13.0" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="5.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.5" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" />
<PackageReference Include="Microsoft.Graph.Core" Version="1.20.1.4" />

View File

@ -1,6 +1,6 @@
{
"name": "@appserver/people",
"version": "0.1.0",
"version": "0.1.2",
"private": "true",
"homepage": "/products/people",
"id": "f4d98afd-d336-4332-8778-3c6945c81ea0",

View File

@ -12,6 +12,7 @@
"UpdatingProcess": "Updating...",
"CancelButton": "Cancel",
"CopyEmailAndPassword": "Copy e-mail & password",
"CopiedResourceText": "Copied",
"UserType": "Type",
"AddButton": "Add",
"ContactInformation": "Contact information",
@ -42,9 +43,7 @@
"ErrorPasswordNoUpperCase": "capital letters",
"ErrorPasswordNoSpecialSymbols": "special characters",
"ErrorPasswordLength": "from {{from}} to {{to}} characters",
"CustomCreation": "{{user}} (creation)",
"ActivationLink": "Activation link",
"AddPhoto": "Add photo",
"TemporaryPassword": "Temporary password",
@ -61,4 +60,4 @@
"Calendar": "Calendar",
"ViewAccess": "View",
"ProfileAction": "Profile action"
}
}

View File

@ -12,6 +12,7 @@
"UpdatingProcess": "Обновление...",
"CancelButton": "Отмена",
"CopyEmailAndPassword": "Копировать email и пароль",
"CopiedResourceText": "Скопировано",
"UserType": "Тип",
"AddButton": "Добавить",
"ContactInformation": "Контактные данные",
@ -41,9 +42,7 @@
"ErrorPasswordNoUpperCase": "заглавные буквы",
"ErrorPasswordNoSpecialSymbols": "специальные символы",
"ErrorPasswordLength": "от {{from}} до {{to}} символов",
"CustomCreation": "{{user}} (создание)",
"ActivationLink": "Ссылка для активации",
"AddPhoto": "Добавить фотографию",
"TemporaryPassword": "Временный пароль",
@ -60,4 +59,4 @@
"Calendar": "Календарь",
"ViewAccess": "Просмотр",
"ProfileAction": "Работа с профилем"
}
}

View File

@ -2,46 +2,8 @@ import App from "./App";
import React from "react";
import ReactDOM from "react-dom";
import config from "../package.json";
import { Workbox, messageSW } from "workbox-window";
import { registerSW } from "@appserver/common/utils/sw-helper";
ReactDOM.render(<App />, document.getElementById("root"));
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
const wb = new Workbox(`${config.homepage}/sw.js`);
//TODO: watch https://developers.google.com/web/tools/workbox/guides/advanced-recipes and https://github.com/webmaxru/prog-web-news/blob/5ff94b45c9d317409c21c0fbb7d76e92f064471b/src/app/app-shell/app-shell.component.ts
// const showSkipWaitingPrompt = (event) => {
// let snackBarRef = this.snackBar.open(
// "A new version of the website available",
// "Reload page",
// {
// duration: 5000,
// }
// );
// // Displaying prompt
// snackBarRef.onAction().subscribe(() => {
// // Assuming the user accepted the update, set up a listener
// // that will reload the page as soon as the previously waiting
// // service worker has taken control.
// wb.addEventListener("controlling", () => {
// window.location.reload();
// });
// // This will postMessage() to the waiting service worker.
// wb.messageSkipWaiting();
// });
// };
// // Add an event listener to detect when the registered
// // service worker has installed but is waiting to activate.
// wb.addEventListener("waiting", showSkipWaitingPrompt);
wb.register()
.then((reg) => {
console.log("Successful service worker registration", reg);
})
.catch((err) => console.error("Service worker registration failed", err));
}
registerSW(config.homepage);

View File

@ -43,6 +43,7 @@ class ChangePasswordDialogComponent extends React.Component {
<Trans
i18nKey="MessageSendPasswordChangeInstructionsOnEmail"
ns="ChangePasswordDialog"
t={t}
>
Send the password change instructions to the
<Link

View File

@ -65,6 +65,7 @@ class DeleteProfileEverDialogComponent extends React.Component {
<Trans
i18nKey="DeleteUserConfirmation"
ns="DeleteProfileEverDialog"
t={t}
>
{{ userCaption }} <strong>{{ user: user.displayName }}</strong>{" "}
will be deleted.

View File

@ -287,7 +287,7 @@ const SectionBodyContent = ({
opened={isHeadSelectorOpen}
selectedOption={
newGroupManager.default ||
newGroupManager.id === ID_NO_GROUP_MANAGER ||
newGroupManager.key === ID_NO_GROUP_MANAGER ||
newGroupManager.displayName === "profile removed"
? { ...newGroupManager, label: t("LblSelect") }
: newGroupManager

View File

@ -139,6 +139,7 @@ const SimpleUserRow = ({
<Trans
i18nKey="MessageEmailActivationInstuctionsSentOnEmail"
ns="Home"
t={t}
>
The email activation instructions have been sent to the
<strong>{{ email: email }}</strong> email address

View File

@ -24,6 +24,7 @@ const Home = ({
getUsersList,
setIsLoading,
setIsRefresh,
selectedGroup,
}) => {
const { location } = history;
const { pathname } = location;
@ -41,6 +42,14 @@ const Home = ({
});
}
}, [pathname, location]);
useEffect(() => {
if (isMobile) {
const customScrollElm = document.querySelector(
"#customScrollBar > .scroll-body"
);
customScrollElm && customScrollElm.scrollTo(0, 0);
}
}, [selectedGroup]);
useEffect(() => {
isLoading ? showLoader() : hideLoader();
@ -92,4 +101,5 @@ export default inject(({ peopleStore }) => ({
getUsersList: peopleStore.usersStore.getUsersList,
setIsLoading: peopleStore.setIsLoading,
setIsRefresh: peopleStore.setIsRefresh,
selectedGroup: peopleStore.selectedGroupStore.selectedGroup,
}))(observer(withRouter(Home)));

View File

@ -11,6 +11,11 @@ import toastr from "studio/toastr";
import Loaders from "@appserver/common/components/Loaders";
import { inject, observer } from "mobx-react";
import { showLoader, hideLoader } from "@appserver/common/utils";
import { withRouter } from "react-router";
import { AppServerConfig } from "@appserver/common/constants";
import { combineUrl } from "@appserver/common/utils";
import config from "../../../../../../package.json";
const InfoContainer = styled.div`
margin-bottom: 24px;
@ -99,12 +104,22 @@ class ProfileInfo extends React.PureComponent {
onGroupClick = (e) => {
const group = e.currentTarget.dataset.id;
const { filter, setIsLoading, fetchPeople } = this.props;
const { filter, setIsLoading, fetchPeople, history } = this.props;
const newFilter = filter.clone();
newFilter.group = group;
setIsLoading(true);
const urlFilter = newFilter.toUrlParams();
const url = combineUrl(
AppServerConfig.proxyURL,
config.homepage,
`/filter?${urlFilter}`
);
history.push(url);
fetchPeople(newFilter).finally(() => setIsLoading(false));
};
@ -217,7 +232,7 @@ class ProfileInfo extends React.PureComponent {
const supportEmail = "documentation@onlyoffice.com";
const tooltipLanguage = (
<Text fontSize="13px">
<Trans i18nKey="NotFoundLanguage" ns="Profile">
<Trans t={t} i18nKey="NotFoundLanguage" ns="Profile">
"In case you cannot find your language in the list of the available
ones, feel free to write to us at
<Link href={`mailto:${supportEmail}`} isHovered={true}>
@ -351,15 +366,17 @@ class ProfileInfo extends React.PureComponent {
}
}
export default inject(({ auth, peopleStore }) => ({
groupCaption: auth.settingsStore.customNames.groupCaption,
regDateCaption: auth.settingsStore.customNames.regDateCaption,
userPostCaption: auth.settingsStore.customNames.userPostCaption,
userCaption: auth.settingsStore.customNames.userCaption,
guestCaption: auth.settingsStore.customNames.guestCaption,
fetchPeople: peopleStore.usersStore.getUsersList,
filter: peopleStore.filterStore.filter,
setIsLoading: peopleStore.setIsLoading,
isLoading: peopleStore.isLoading,
updateProfileCulture: peopleStore.targetUserStore.updateProfileCulture,
}))(observer(withTranslation("Profile")(ProfileInfo)));
export default withRouter(
inject(({ auth, peopleStore }) => ({
groupCaption: auth.settingsStore.customNames.groupCaption,
regDateCaption: auth.settingsStore.customNames.regDateCaption,
userPostCaption: auth.settingsStore.customNames.userPostCaption,
userCaption: auth.settingsStore.customNames.userCaption,
guestCaption: auth.settingsStore.customNames.guestCaption,
fetchPeople: peopleStore.usersStore.getUsersList,
filter: peopleStore.filterStore.filter,
setIsLoading: peopleStore.setIsLoading,
isLoading: peopleStore.isLoading,
updateProfileCulture: peopleStore.targetUserStore.updateProfileCulture,
}))(observer(withTranslation("Profile")(ProfileInfo)))
);

View File

@ -98,7 +98,9 @@ class SectionBodyContent extends React.PureComponent {
onEditSubscriptionsClick = () => console.log("Edit subscriptions onClick()");
onEditProfileClick = () =>
onEditProfileClick = () => {
this.props.avatarMax && this.props.setAvatarMax(null);
this.props.history.push(
combineUrl(
AppServerConfig.proxyURL,
@ -106,6 +108,7 @@ class SectionBodyContent extends React.PureComponent {
`/edit/${this.props.profile.userName}`
)
);
};
render() {
const {
@ -208,5 +211,7 @@ export default withRouter(
viewer: auth.userStore.user,
isTabletView: auth.settingsStore.isTabletView,
isSelf: peopleStore.targetUserStore.isMe,
avatarMax: peopleStore.avatarEditorStore.avatarMax,
setAvatarMax: peopleStore.avatarEditorStore.setAvatarMax,
}))(observer(withTranslation("Profile")(SectionBodyContent)))
);

View File

@ -288,6 +288,7 @@ class SectionHeaderContent extends React.PureComponent {
<Trans
i18nKey="MessageEmailActivationInstuctionsSentOnEmail"
ns="Profile"
t={this.props.t}
>
The email activation instructions have been sent to the
<strong>{{ email: this.state.profile.email }}</strong> email address
@ -399,8 +400,15 @@ class SectionHeaderContent extends React.PureComponent {
onClickBack = () => {
const { filter, setFilter, history, resetProfile } = this.props;
resetProfile();
const backUrl = combineUrl(AppServerConfig.proxyURL, config.homepage);
history.push(backUrl);
const url = filter.toUrlParams();
const backUrl = combineUrl(
AppServerConfig.proxyURL,
config.homepage,
`filter?/${url}`
);
history.push(backUrl, url);
setFilter(filter);
};

View File

@ -32,6 +32,7 @@ class PasswordField extends React.Component {
inputTabIndex,
copyLinkText,
copiedResourceText,
t,
} = this.props;
@ -60,6 +61,7 @@ class PasswordField extends React.Component {
inputTabIndex={inputTabIndex}
onChange={inputOnChange}
clipActionResource={copyLinkText}
clipCopiedResource={copiedResourceText}
clipEmailResource={`${t("Email")}: `}
clipPasswordResource={`${t("Password")}: `}
tooltipPasswordTitle={`${t("ErrorPasswordMessage")}:`}

View File

@ -178,11 +178,10 @@ class AvatarEditorPage extends React.PureComponent {
.then(() => {
this.setState(this.mapPropsToState(this.props));
})
.then(() => {
this.props.fetchProfile(profile.id);
})
.then(() => {
toggleAvatarEditor(false);
.then(() => this.props.fetchProfile(profile.id))
.then((res) => {
this.props.isMe && this.props.setUser(res);
return toggleAvatarEditor(false);
});
} else {
deleteAvatar(profile.id)
@ -198,7 +197,10 @@ class AvatarEditorPage extends React.PureComponent {
this.setState(this.mapPropsToState(this.props));
})
.then(() => this.props.fetchProfile(profile.id))
.then(() => toggleAvatarEditor(false));
.then((res) => {
this.props.isMe && this.props.setUser(res);
return toggleAvatarEditor(false);
});
}
};
@ -313,9 +315,11 @@ class AvatarEditorPage extends React.PureComponent {
export default withRouter(
inject(({ auth, peopleStore }) => ({
setDocumentTitle: auth.setDocumentTitle,
setUser: auth.userStore.setUser,
toggleAvatarEditor: peopleStore.avatarEditorStore.toggleAvatarEditor,
fetchProfile: peopleStore.targetUserStore.getTargetUser,
profile: peopleStore.targetUserStore.targetUser,
isMe: peopleStore.targetUserStore.isMe,
avatarMax: peopleStore.avatarEditorStore.avatarMax,
setAvatarMax: peopleStore.avatarEditorStore.setAvatarMax,
updateProfile: peopleStore.targetUserStore.updateProfile,

View File

@ -491,7 +491,7 @@ class CreateUserForm extends React.Component {
helpButtonHeaderContent={t("Mail")}
tooltipContent={
<Text fontSize="13px" as="div">
<Trans i18nKey="EmailPopupHelper" ns="ProfileAction">
<Trans t={t} i18nKey="EmailPopupHelper" ns="ProfileAction">
The main e-mail is needed to restore access to the portal in
case of loss of the password and send notifications.
<p className="tooltip_email" style={{ margin: "1rem 0" }}>
@ -524,6 +524,7 @@ class CreateUserForm extends React.Component {
inputIsDisabled={isLoading || profile.passwordType === "link"}
inputOnChange={this.onInputChange}
copyLinkText={t("CopyEmailAndPassword")}
copiedResourceText={t("CopiedResourceText")}
inputTabIndex={4}
passwordSettings={passwordSettings}
t={t}

View File

@ -681,7 +681,7 @@ class UpdateUserForm extends React.Component {
helpButtonHeaderContent={t("Mail")}
tooltipContent={
<Text fontSize="13px" as="div">
<Trans i18nKey="EmailPopupHelper" ns="ProfileAction">
<Trans t={t} i18nKey="EmailPopupHelper" ns="ProfileAction">
The main e-mail is needed to restore access to the portal in
case of loss of the password and send notifications.
<p

View File

@ -72,8 +72,14 @@ const SectionHeaderContent = (props) => {
);
const goBackAndReset = useCallback(() => {
if (!profile || !document.referrer) setFilterAndReset(filter);
else props.resetProfile();
if (!profile || !document.referrer) {
setFilterAndReset(filter);
const urlFilter = filter.toUrlParams();
return history.push(
combineUrl(AppServerConfig.proxyURL, homepage, `/filter?${urlFilter}`)
);
}
history.push(
combineUrl(
AppServerConfig.proxyURL,
@ -81,6 +87,8 @@ const SectionHeaderContent = (props) => {
`/view/${profile.userName}`
)
);
return props.resetProfile();
}, [history, props]);
const onClickBack = useCallback(() => {

View File

@ -16,7 +16,7 @@ class GroupsStore {
}
getGroupList = async () => {
const res = await api.groups.getGroupListFull();
const res = await api.groups.getGroupList(); //TODO: replace with getGroupListFull() after fixing problems on the server
this.groups = res;
};

View File

@ -59,8 +59,15 @@ class SelectedGroupStore {
const { group, search, role, activationStatus, employeeStatus } = filter;
let countMembers;
groups.filter((el) => {
if (el.id === group) countMembers = el.members.length;
groups.filter(async (el) => {
if (el.id === group) {
if (!el.members) {
const currGroup = await getGroup(el.id);
countMembers = currGroup.members.length; // TODO: simplify after fixing server issues with getGroupListFull
} else {
countMembers = el.members.length;
}
}
});
const filterIsClear =

View File

@ -36,7 +36,8 @@ class TargetUserStore {
return this.setTargetUser(authStore.userStore.user);
} else {*/
const user = await api.people.getUser(userName);
return this.setTargetUser(user);
this.setTargetUser(user);
return user;
//}
};

View File

@ -1,6 +1,6 @@
{
"name": "@appserver/projects",
"version": "0.1.0",
"version": "0.1.2",
"private": "true",
"homepage": "/products/projects",
"id": "1e044602-43b5-4d79-82f3-fd6208a11960",

View File

@ -2,46 +2,8 @@ import App from "./App";
import React from "react";
import ReactDOM from "react-dom";
import config from "../package.json";
import { Workbox, messageSW } from "workbox-window";
import { registerSW } from "@appserver/common/utils/sw-helper";
ReactDOM.render(<App />, document.getElementById("root"));
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
const wb = new Workbox(`${config.homepage}/sw.js`);
//TODO: watch https://developers.google.com/web/tools/workbox/guides/advanced-recipes and https://github.com/webmaxru/prog-web-news/blob/5ff94b45c9d317409c21c0fbb7d76e92f064471b/src/app/app-shell/app-shell.component.ts
// const showSkipWaitingPrompt = (event) => {
// let snackBarRef = this.snackBar.open(
// "A new version of the website available",
// "Reload page",
// {
// duration: 5000,
// }
// );
// // Displaying prompt
// snackBarRef.onAction().subscribe(() => {
// // Assuming the user accepted the update, set up a listener
// // that will reload the page as soon as the previously waiting
// // service worker has taken control.
// wb.addEventListener("controlling", () => {
// window.location.reload();
// });
// // This will postMessage() to the waiting service worker.
// wb.messageSkipWaiting();
// });
// };
// // Add an event listener to detect when the registered
// // service worker has installed but is waiting to activate.
// wb.addEventListener("waiting", showSkipWaitingPrompt);
wb.register()
.then((reg) => {
console.log("Successful service worker registration", reg);
})
.catch((err) => console.error("Service worker registration failed", err));
}
registerSW(config.homepage);

View File

@ -19,6 +19,7 @@ import { setDocumentTitle } from "../../helpers/utils";
import { inject } from "mobx-react";
import i18n from "../../i18n";
import { I18nextProvider } from "react-i18next";
import { combineUrl, deleteCookie } from "@appserver/common/utils";
const commonStyles = `
.link-box {
@ -90,12 +91,13 @@ const StyledDesktopContainer = styled(EmptyScreenContainer)`
}
`;
const ExternalLink = ({ label, href }) => (
const ExternalLink = ({ label, href, onClick }) => (
<Box className="link-box">
<ExternalLinkIcon color="#333333" size={isMobile ? "small" : "medium"} />
<Link
as="a"
href={href}
onClick={onClick}
target="_blank"
className="view-web-link"
color="#555F65"
@ -122,7 +124,10 @@ const Body = ({ modules, match, isLoaded, setCurrentProductId }) => {
helpUrl,
} = currentModule;
const url = originUrl ? originUrl : link;
const webLink = protocol + "//" + hostname + url;
const webLink = combineUrl(
protocol + "//" + hostname,
`${url}?desktop_view=true`
);
const appLink = isIOS
? id === "2A923037-8B2D-487b-9A22-5AC0918ACF3F"
? "message:"
@ -147,7 +152,13 @@ const Body = ({ modules, match, isLoaded, setCurrentProductId }) => {
borderRadius="2px"
className="coming-soon-badge"
/>
<ExternalLink label={t("ViewWeb")} href={webLink} />
<ExternalLink
label={t("ViewWeb")}
onClick={() => {
deleteCookie("desktop_view");
window.open(webLink, "_self", "", true);
}}
/>
{appLink && (
<ExternalLink
label={t("OpenApp", {

View File

@ -99,7 +99,7 @@ namespace ASC.Projects.Configuration
public override string HelpURL
{
get { return string.Concat(PathProvider.BaseVirtualPath, "Help.aspx"); }
get { return "https://helpcenter.onlyoffice.com/userguides/projects.aspx"; }
}
public override string ProductClassName

View File

@ -1,6 +1,6 @@
{
"name": "@appserver/studio",
"version": "0.1.0",
"version": "0.1.2",
"private": "true",
"homepage": "",
"title": "ONLYOFFICE",

View File

@ -12,5 +12,6 @@
"LogoutButton": "Sign Out",
"Settings": "Settings",
"Version": "Version",
"AboutShort": "About"
"AboutShort": "About",
"TurnOnDesktopVersion": "Turn on desktop version"
}

Some files were not shown because too many files have changed in this diff Show More