Merge branch 'develop' into feature/fix-whitelable

This commit is contained in:
Viktor Fomin 2022-11-24 02:33:13 +05:00
commit 1fb1228dbd
105 changed files with 1687 additions and 843 deletions

1
.gitignore vendored
View File

@ -50,4 +50,3 @@ TestsResults/
**/.yarn/cache
**/.yarn/install-state.gz
config/appsettings.dev.json

View File

@ -0,0 +1,81 @@
$PSversionMajor = $PSVersionTable.PSVersion | sort-object major | ForEach-Object { $_.major }
$PSversionMinor = $PSVersionTable.PSVersion | sort-object minor | ForEach-Object { $_.minor }
if ($PSversionMajor -lt 7 -or $PSversionMinor -lt 2) {
Write-Error "Powershell version must be greater than or equal to 7.2."
exit
}
$Branch = git branch --show-current
$BranchExistRemote = git ls-remote --heads origin $Branch
if (-not $BranchExistRemote) {
Write-Error "The current branch does not exist in the remote repository. Please push changes."
exit
}
$RootDir = Split-Path -Parent $PSScriptRoot
$DockerDir = ($RootDir + "\build\install\docker")
$BuildDate = Get-Date -Format "yyyy-MM-dd"
$LocalIp = (Get-WmiObject -Class Win32_NetworkAdapterConfiguration | Where-Object { $_.DHCPEnabled -ne $null -and $_.DefaultIPGateway -ne $null }).IPAddress | Select-Object -First 1
$Doceditor = ($LocalIp + ":5013")
$Login = ($LocalIp + ":5011")
$Client = ($LocalIp + ":5001")
$DockerFile = "Dockerfile.dev"
$EnvExtension = "dev"
$CoreBaseDomain = "localhost"
# Stop all backend services"
& "$PSScriptRoot\start\stop.backend.docker.ps1"
$Env:COMPOSE_IGNORE_ORPHANS = "True"
$Containers = docker ps -a -f "name=^onlyoffice" --format="{{.ID}} {{.Names}}" | Select-String -Pattern ("mysql|rabbitmq|redis|elasticsearch|documentserver") -NotMatch | ConvertFrom-String | ForEach-Object P1
$Images = docker images onlyoffice/docspace* -q
if ($Containers) {
Write-Host "Remove all backend containers" -ForegroundColor Blue
docker rm -f $Containers
}
if ($Images) {
Write-Host "Remove all docker images except 'mysql, rabbitmq, redis, elasticsearch, documentserver'" -ForegroundColor Blue
docker rmi -f $Images
}
Write-Host "Run MySQL" -ForegroundColor Green
docker compose -f ($DockerDir + "\db.yml") up -d
Write-Host "Run environments (redis, rabbitmq)" -ForegroundColor Green
$Env:DOCKERFILE = $DockerFile
docker compose -f ($DockerDir + "\redis.yml") -f ($DockerDir + "\rabbitmq.yml") up -d
if ($args[0] -eq "--no_ds") {
Write-Host "SKIP Document server" -ForegroundColor Blue
}
else {
Write-Host "Run Document server" -ForegroundColor Green
$Env:DOCUMENT_SERVER_IMAGE_NAME = "onlyoffice/documentserver-de:latest"
$Env:ROOT_DIR = $RootDir
docker compose -f ($DockerDir + "\ds.dev.yml") up -d
}
Write-Host "Build all backend services" -ForegroundColor Blue
$Env:DOCKERFILE = $DockerFile
$Env:RELEASE_DATE = $BuildDate
$Env:GIT_BRANCH = $Branch
$Env:SERVICE_DOCEDITOR = $Doceditor
$Env:SERVICE_LOGIN = $Login
$Env:SERVICE_CLIENT = $Client
$Env:APP_CORE_BASE_DOMAIN = $CoreBaseDomain
$Env:ENV_EXTENSION = $EnvExtension
docker compose -f ($DockerDir + "\build.dev.yml") build --build-arg GIT_BRANCH=$Branch --build-arg RELEASE_DATE=$BuildDate
Write-Host "Run DB migration" -ForegroundColor Green
$Env:DOCKERFILE = $DockerFile
docker compose -f ($DockerDir + "\migration-runner.yml") up -d
# Start all backend services"
& "$PSScriptRoot\start\start.backend.docker.ps1"

View File

@ -9,10 +9,17 @@ echo "Root directory:" $dir
cd $dir
branch=$(git branch | sed -n -e 's/^\* \(.*\)/\1/p')
branch=$(git branch --show-current)
echo "GIT_BRANCH:" $branch
branch_exist_remote=$(git ls-remote --heads origin $branch)
if [ -z "$branch_exist_remote" ]; then
echo "The current branch does not exist in the remote repository. Please push changes."
exit 1
fi
cd $dir/build/install/docker/
docker_dir="$( pwd )"
@ -43,11 +50,9 @@ $dir/build/start/stop.backend.docker.sh
echo "Remove all backend containers"
docker rm -f $(docker ps -a | egrep "onlyoffice" | egrep -v "mysql|rabbitmq|redis|elasticsearch|documentserver" | awk 'NR>0 {print $1}')
echo "Remove all backend images"
docker rmi -f $(docker images -a | egrep "onlyoffice" | egrep -v "mysql|rabbitmq|redis|elasticsearch|documentserver" | awk 'NR>0 {print $3}')
echo "Remove all docker images except 'mysql, rabbitmq, redis, elasticsearch, documentserver'"
docker image rm -f $(docker images -a | egrep "onlyoffice" | egrep -v "mysql|rabbitmq|redis|elasticsearch|documentserver" | awk 'NR>0 {print $3}')
docker rmi -f $(docker images -a | egrep "onlyoffice" | egrep -v "mysql|rabbitmq|redis|elasticsearch|documentserver" | awk 'NR>0 {print $3}')
echo "Run MySQL"
@ -58,7 +63,7 @@ if [ "${arch_name}" = "x86_64" ]; then
docker compose -f db.yml up -d
elif [ "${arch_name}" = "arm64" ]; then
echo "CPU Type: arm64 -> run db.yml with arm64v8 image"
MYSQL_IMAGE=arm64v8/mysql:oracle \
MYSQL_IMAGE=arm64v8/mysql:8.0.31-oracle \
docker compose -f db.yml up -d
else
echo "Error: Unknown CPU Type: ${arch_name}."

9
build/build.docker.bat Normal file
View File

@ -0,0 +1,9 @@
@echo off
if %errorlevel% == 0 (
pwsh %~dp0/build.backend.docker.ps1 "start"
)
echo.
pause

View File

@ -0,0 +1,21 @@
$Containers = docker ps -aqf "name=^onlyoffice"
$Images = docker images onlyoffice/docspace* -q
if ($Containers) {
Write-Host "Stop all backend containers" -ForegroundColor Blue
docker stop $Containers
Write-Host "Remove all backend containers" -ForegroundColor Blue
docker rm -f $Containers
}
if ($Images) {
Write-Host "Remove all docker images except 'mysql, rabbitmq, redis, elasticsearch, documentserver'" -ForegroundColor Blue
docker rmi -f $Images
}
Write-Host "Remove unused volumes." -ForegroundColor Blue
docker volume prune -f
Write-Host "Remove unused networks." -ForegroundColor Blue
docker network prune -f

View File

@ -5,7 +5,7 @@
DOCKER_IMAGE_PREFIX=${STATUS}docspace
DOCKER_TAG=latest
CONTAINER_PREFIX=${PRODUCT}-
MYSQL_VERSION=8.0.18
MYSQL_VERSION=8.0.31
MYSQL_IMAGE=mysql:${MYSQL_VERSION}
ELK_VERSION=7.13.1
SERVICE_PORT=5050

View File

@ -319,26 +319,7 @@ ARG SRC_PATH
ENV BUILD_PATH=${BUILD_PATH}
ENV SRC_PATH=${SRC_PATH}
WORKDIR ${BUILD_PATH}/services/ASC.Migration.Runner/
COPY ./docker-migration-entrypoint.sh ./docker-migration-entrypoint.sh
COPY docker-migration-entrypoint.sh docker-migration-entrypoint.sh
COPY --from=base ${SRC_PATH}/ASC.Migration.Runner/service/ .
ENTRYPOINT ["./docker-migration-entrypoint.sh"]
## image for k8s bin-share ##
FROM busybox:latest AS bin_share
RUN mkdir -p /app/appserver/ASC.Files/server && \
mkdir -p /app/appserver/ASC.People/server/ && \
addgroup --system --gid 107 onlyoffice && \
adduser -u 104 onlyoffice --home /var/www/onlyoffice --system -G onlyoffice
COPY bin-share-docker-entrypoint.sh /app/docker-entrypoint.sh
COPY --from=base /var/www/products/ASC.Files/server/ /app/appserver/ASC.Files/server/
COPY --from=base /var/www/products/ASC.People/server/ /app/appserver/ASC.People/server/
ENTRYPOINT ["./app/docker-entrypoint.sh"]
## image for k8s wait-bin-share ##
FROM busybox:latest AS wait_bin_share
RUN mkdir /app
COPY wait-bin-share-docker-entrypoint.sh /app/docker-entrypoint.sh
ENTRYPOINT ["./app/docker-entrypoint.sh"]

View File

@ -1,34 +1,33 @@
version: "3.8"
x-service:
&x-service-base
container_name: base
restart: always
expose:
x-service: &x-service-base
container_name: base
restart: always
expose:
- ${SERVICE_PORT}
environment:
MYSQL_HOST: ${MYSQL_HOST}
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
DATABASE_MIGRATION: ${DATABASE_MIGRATION}
APP_DOTNET_ENV: ${APP_DOTNET_ENV}
APP_CORE_BASE_DOMAIN: ${APP_CORE_BASE_DOMAIN}
APP_CORE_MACHINEKEY: ${APP_CORE_MACHINEKEY}
DOCUMENT_SERVER_JWT_SECRET: ${DOCUMENT_SERVER_JWT_SECRET}
DOCUMENT_SERVER_JWT_HEADER: ${DOCUMENT_SERVER_JWT_HEADER}
DOCUMENT_SERVER_URL_PUBLIC: ${DOCUMENT_SERVER_URL_PUBLIC}
DOCUMENT_SERVER_URL_INTERNAL: ${DOCUMENT_SERVER_URL_INTERNAL}
KAFKA_HOST: ${KAFKA_HOST}
ELK_HOST: ${ELK_HOST}
PROXY_HOST: ${PROXY_HOST}
volumes:
environment:
MYSQL_HOST: ${MYSQL_HOST}
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
DATABASE_MIGRATION: ${DATABASE_MIGRATION}
APP_DOTNET_ENV: ${APP_DOTNET_ENV}
APP_CORE_BASE_DOMAIN: ${APP_CORE_BASE_DOMAIN}
APP_CORE_MACHINEKEY: ${APP_CORE_MACHINEKEY}
DOCUMENT_SERVER_JWT_SECRET: ${DOCUMENT_SERVER_JWT_SECRET}
DOCUMENT_SERVER_JWT_HEADER: ${DOCUMENT_SERVER_JWT_HEADER}
DOCUMENT_SERVER_URL_PUBLIC: ${DOCUMENT_SERVER_URL_PUBLIC}
DOCUMENT_SERVER_URL_INTERNAL: ${DOCUMENT_SERVER_URL_INTERNAL}
KAFKA_HOST: ${KAFKA_HOST}
ELK_HOST: ${ELK_HOST}
PROXY_HOST: ${PROXY_HOST}
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/
services:
services:
onlyoffice-elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:${ELK_VERSION}
container_name: ${ELK_HOST}
@ -58,7 +57,7 @@ services:
<<: *x-service-base
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-backup:${DOCKER_TAG}"
container_name: ${BACKUP_HOST}
onlyoffice-clear-events:
<<: *x-service-base
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-clear-events:${DOCKER_TAG}"
@ -78,7 +77,7 @@ services:
<<: *x-service-base
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-files-services:${DOCKER_TAG}"
container_name: ${FILES_SERVICES_HOST}
onlyoffice-people-server:
<<: *x-service-base
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-people-server:${DOCKER_TAG}"
@ -89,8 +88,8 @@ services:
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-socket:${DOCKER_TAG}"
container_name: ${SOCKET_HOST}
expose:
- ${SERVICE_PORT}
- ${SERVICE_PORT}
onlyoffice-studio-notify:
<<: *x-service-base
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-studio-notify:${DOCKER_TAG}"
@ -106,8 +105,8 @@ services:
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-urlshortener:${DOCKER_TAG}"
container_name: ${URLSHORTENER_HOST}
expose:
- ${SERVICE_PORT}
- "9999"
- ${SERVICE_PORT}
- "9999"
onlyoffice-api:
<<: *x-service-base
@ -123,19 +122,19 @@ services:
<<: *x-service-base
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-studio:${DOCKER_TAG}"
container_name: ${STUDIO_HOST}
onlyoffice-ssoauth:
<<: *x-service-base
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-ssoauth:${DOCKER_TAG}"
container_name: ${SSOAUTH_HOST}
expose:
- ${SERVICE_PORT}
- "9834"
- ${SERVICE_PORT}
- "9834"
onlyoffice-webhooks-service:
<<: *x-service-base
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-webhooks-service:${DOCKER_TAG}"
container_name: ${WEBHOOKS_SERVICE_HOST}
container_name: ${WEBHOOKS_SERVICE_HOST}
onlyoffice-doceditor:
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-doceditor:${DOCKER_TAG}"
@ -160,7 +159,7 @@ services:
- "8099"
- "8092"
ports:
- 8092:8092
- 8092:8092
depends_on:
- onlyoffice-backup-background-tasks
- onlyoffice-backup
@ -206,8 +205,8 @@ services:
networks:
default:
external:
name: ${NETWORK_NAME}
name: ${NETWORK_NAME}
external: true
volumes:
es_data:

View File

@ -120,20 +120,6 @@ services:
target: webhooks-service
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-webhooks-service:${DOCKER_TAG}"
onlyoffice-bin-share:
build:
context: ./
dockerfile: "${DOCKERFILE}"
target: bin_share
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-bin-share:${DOCKER_TAG}"
onlyoffice-wait-bin-share:
build:
context: ./
dockerfile: "${DOCKERFILE}"
target: wait_bin_share
image: "${REPO}/${DOCKER_IMAGE_PREFIX}-wait-bin-share:${DOCKER_TAG}"
onlyoffice-proxy:
build:
context: ./

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/bin/bash
MYSQL_HOST=${MYSQL_HOST:-"localhost"}
MYSQL_DATABASE=${MYSQL_DATABASE:-"onlyoffice"}
@ -7,4 +7,4 @@ MYSQL_PASSWORD=${MYSQL_PASSWORD:-"onlyoffice_pass"}
sed -i "s!\"ConnectionString\".*!\"ConnectionString\": \"Server=${MYSQL_HOST};Database=${MYSQL_DATABASE};User ID=${MYSQL_USER};Password=${MYSQL_PASSWORD}\",!g" ./appsettings.json
dotnet ASC.Migration.Runner.dll
dotnet ASC.Migration.Runner.dll

View File

@ -196,8 +196,8 @@ services:
networks:
default:
external:
name: ${NETWORK_NAME}
name: ${NETWORK_NAME}
external: true
volumes:
es_data:

View File

@ -13,5 +13,5 @@ services:
networks:
default:
external:
name: ${NETWORK_NAME}
name: ${NETWORK_NAME}
external: true

View File

@ -1,2 +1,3 @@
#!/bin/sh
envsubst '$MAP_HASH_BUCKET_SIZE,$COUNT_WORKER_CONNECTIONS' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf
envsubst '$MAP_HASH_BUCKET_SIZE,$COUNT_WORKER_CONNECTIONS' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf

View File

@ -1,6 +1,6 @@
version: '3'
services:
onlyoffice-rabbitmq:
version: "3"
services:
onlyoffice-rabbitmq:
image: rabbitmq:3
container_name: onlyoffice-rabbitmq
restart: always
@ -9,5 +9,5 @@ services:
- "80"
networks:
default:
external:
name: ${NETWORK_NAME}
name: ${NETWORK_NAME}
external: true

View File

@ -1,6 +1,6 @@
version: '3'
services:
onlyoffice-redis:
version: "3"
services:
onlyoffice-redis:
image: redis:7
container_name: onlyoffice-redis
restart: always
@ -8,5 +8,5 @@ services:
- "6379"
networks:
default:
external:
name: ${NETWORK_NAME}
name: ${NETWORK_NAME}
external: true

View File

@ -0,0 +1,5 @@
# Stop all backend services"
& "$PSScriptRoot\stop.backend.docker.ps1"
# Start all backend services"
& "$PSScriptRoot\start.backend.docker.ps1"

View File

@ -0,0 +1,41 @@
$PSversionMajor = $PSVersionTable.PSVersion | sort-object major | ForEach-Object { $_.major }
$PSversionMinor = $PSVersionTable.PSVersion | sort-object minor | ForEach-Object { $_.minor }
if ($PSversionMajor -lt 7 -or $PSversionMinor -lt 2) {
Write-Error "Powershell version must be greater than or equal to 7.2."
exit
}
$Branch = git branch --show-current
$BranchExistRemote = git ls-remote --heads origin $Branch
if (-not $BranchExistRemote) {
Write-Error "The current branch does not exist in the remote repository. Please push changes."
exit
}
$RootDir = Split-Path (Split-Path -Parent $PSScriptRoot) -Parent
$DockerDir = ($RootDir + "\build\install\docker")
$BuildDate = Get-Date -Format "yyyy-MM-dd"
$LocalIp = (Get-WmiObject -Class Win32_NetworkAdapterConfiguration | Where-Object { $_.DHCPEnabled -ne $null -and $_.DefaultIPGateway -ne $null }).IPAddress | Select-Object -First 1
$Doceditor = ($LocalIp + ":5013")
$Login = ($LocalIp + ":5011")
$Client = ($LocalIp + ":5001")
$DockerFile = "Dockerfile.dev"
$EnvExtension = "dev"
$CoreBaseDomain = "localhost"
Write-Host "Start all backend services (containers)" -ForegroundColor Green
$Env:DOCKERFILE = $DockerFile
$Env:ROOT_DIR = $RootDir
$Env:RELEASE_DATE = $BuildDate
$Env:GIT_BRANCH = $Branch
$Env:SERVICE_DOCEDITOR = $Doceditor
$Env:SERVICE_LOGIN = $Login
$Env:SERVICE_CLIENT = $Client
$Env:APP_CORE_BASE_DOMAIN = $CoreBaseDomain
$Env:APP_URL_PORTAL = ("http://" + $LocalIp + ":8092")
$Env:ENV_EXTENSION = $EnvExtension
docker compose -f ($DockerDir + "\docspace.dev.yml") up -d

View File

@ -9,10 +9,17 @@ echo "Root directory:" $dir
cd $dir
branch=$(git branch | sed -n -e 's/^\* \(.*\)/\1/p')
branch=$(git branch --show-current)
echo "GIT_BRANCH:" $branch
branch_exist_remote=$(git ls-remote --heads origin $branch)
if [ -z "$branch_exist_remote" ]; then
echo "The current branch does not exist in the remote repository. Please push changes."
exit 1
fi
cd $dir/build/install/docker/
docker_dir="$( pwd )"

View File

@ -0,0 +1,17 @@
$PSversionMajor = $PSVersionTable.PSVersion | sort-object major | ForEach-Object { $_.major }
$PSversionMinor = $PSVersionTable.PSVersion | sort-object minor | ForEach-Object { $_.minor }
if ($PSversionMajor -lt 7 -or $PSversionMinor -lt 2) {
Write-Error "Powershell version must be greater than or equal to 7.2."
exit
}
$Containers = docker ps -a -f "name=^onlyoffice" --format="{{.ID}} {{.Names}}" | Select-String -Pattern ("mysql|rabbitmq|redis|elasticsearch|documentserver") -NotMatch | ConvertFrom-String | ForEach-Object P1
if (-not $Containers) {
Write-Host "No containers to stop" -ForegroundColor Blue
exit
}
Write-Host "Stop all backend services (containers)" -ForegroundColor Green
docker stop $Containers

View File

@ -59,7 +59,7 @@ public static class BaseDbContextExtension
{
case Provider.MySql:
optionsBuilder.ReplaceService<IMigrationsSqlGenerator, CustomMySqlMigrationsSqlGenerator>();
optionsBuilder.UseMySql(connectionString.ConnectionString, ServerVersion.Parse("8.0.25"), providerOptions =>
optionsBuilder.UseMySql(connectionString.ConnectionString, ServerVersion.AutoDetect(connectionString.ConnectionString), providerOptions =>
{
if (!string.IsNullOrEmpty(migrateAssembly))
{
@ -87,6 +87,11 @@ public static class BaseDbContextExtension
services.AddPooledDbContextFactory<T>(OptionsAction);
}
public static void AddBaseDbContext<T>(this IServiceCollection services) where T : DbContext
{
services.AddDbContext<T>(OptionsAction);
}
public static T AddOrUpdate<T, TContext>(this TContext b, Expression<Func<TContext, DbSet<T>>> expressionDbSet, T entity) where T : BaseEntity where TContext : DbContext
{
var dbSet = expressionDbSet.Compile().Invoke(b);

View File

@ -0,0 +1 @@
{}

View File

@ -37,7 +37,7 @@
"intervalCheckRegisterInstanceInSeconds": "1",
"timeUntilUnregisterInSeconds": "15"
},
"themelimit": "10",
"themelimit": "9",
"oidc": {
"authority" : ""
}
@ -250,4 +250,4 @@
"logStreamName": "${hostname} - ${applicationContext} - ${date} - ${guid}"
}
}
}
}

View File

@ -44,6 +44,7 @@
"element-resize-detector": "^1.2.4",
"file-saver": "^2.0.5",
"firebase": "^8.10.0",
"hex-to-rgba": "^2.0.1",
"react-avatar-editor": "^13.0.0",
"react-colorful": "^5.5.1",
"react-hotkeys-hook": "^3.4.4",

View File

@ -1,4 +1,5 @@
{
"Accent": "Accent",
"AccessRightsAccessToProduct": "Access to {{product}} module is given to",
"AccessRightsAllUsers": "All {{users}}",
"AccessRightsChangeOwnerConfirmText": "Changes will be applied after the confirmation via email.",
@ -50,6 +51,7 @@
"BrowserNoCanvasSupport": "Your browser does not support the HTML5 canvas tag.",
"BreakpointWarningText": "This section is only available in desktop version",
"BreakpointWarningTextPrompt": "Please use the desktop site to access <1>{{content}}</1>",
"Buttons": "Buttons",
"ByApp": "By authenticator app",
"BySms": "By sms",
"ChangeLogoButton": "Change Logo",
@ -62,6 +64,7 @@
"CompanyInfoSettingsDescription": "This information will be displayed in the <1>{{link}}</1> window.",
"ConfirmEmailSended": "Confirmation e-mail has been sent to {{ownerName}}",
"PortalDeletionEmailSended": "A link to confirm the operation has been sent to {{ownerEmail}} (the email address of the portal owner).",
"Custom": "Custom",
"CustomDomains": "Custom domains",
"CustomTitles": "Custom titles",
"CustomTitlesFrom": "From",
@ -78,6 +81,9 @@
"DeleteDataHeader": "Portal deactivation/deletion",
"DeleteDocSpace": "Delete DocSpace",
"DeleteDocSpaceInfo": "Before you delete the portal, please make sure that automatic billing is turned off. You may check the status of automatic billing in <1>on your Stripe customer portal.</1>",
"DeleteTheme": "Delete theme",
"DeleteThemeForever": "Delete theme forever?",
"DeleteThemeNotice": "The theme will be deleted permanently. You will not be able to undo this action.",
"Disabled": "Disabled",
"DNSSettings": "DNS Settings",
"DNSSettingsDescription": "DNS Settings is a way to set an alternative URL for your portal.",
@ -87,6 +93,8 @@
"DocumentsAdministratorsCan": "Documents administrators can link Dropbox, Box, and other accounts to Common Documents and set up access rights in this section",
"DownloadCopy": "Download the copy",
"DownloadReportBtn": "Download and open report",
"EditColorScheme": "Edit color scheme",
"EditCurrentTheme": "Edit current theme",
"Employees": "users",
"EmptyBackupList": "No backups have been created yet. Create one or more backups for them to appear in this list.",
"EnableAutomaticBackup": "Enable automatic backup.",
@ -114,6 +122,7 @@
"LanguageTimeSettingsTooltip": "<0>{{text}}</0> is a way to change the language of the whole portal for all portal users and to configure the time zone so that all the events of the {{ organizationName }} portal will be shown with the correct date and time.",
"LanguageTimeSettingsTooltipDescription": "To make the parameters you set take effect click the <1>{{save}}</1> button at the bottom of the section.<3>{{learnMore}}</3>",
"Lifetime": "Lifetime (min)",
"LimitThemesTooltip": "You can only create 3 custom themes. To create a new one, you must delete one of the previous themes.",
"LocalFile": "Local file",
"LoginDownloadText": "You can download the report for the data available during the selected storage period to view the detailed statistics.",
"LoginHistoryTitle": "Login History",
@ -137,6 +146,7 @@
"ManualBackupHelpNote": "Select the storage for the data (do not forget to enter your third-party storage details to be able to access it).<br/><strong>Note:</strong> you need to connect your third-party account (DropBox, Box.com, OneDrive or Google Drive) to {{organizationName}} Common folder before you will be able to save your backup there.",
"MaxCopies": "{{copiesCount}} - maximum number of backup copies",
"Migration": "Migration",
"NewColorScheme": "New color scheme",
"NoAdmins": "No admins here yet",
"NoAdminsDescription": "You can add new administrator manually",
"NotFoundDescription": "Change filter settings or add people to the section.",

View File

@ -28,24 +28,30 @@ const StyledButton = styled(Button)`
opacity: 1;
background-color: ${({ currentColorScheme }) =>
currentColorScheme.accentColor};
currentColorScheme.main.accent} !important;
background: ${({ currentColorScheme }) => currentColorScheme.main.accent};
border: ${({ currentColorScheme }) => currentColorScheme.main.accent};
:hover {
background-color: ${({ currentColorScheme }) =>
currentColorScheme.accentColor};
currentColorScheme.main.accent};
opacity: 0.85;
background: ${({ currentColorScheme }) => currentColorScheme.main.accent};
border: ${({ currentColorScheme }) => currentColorScheme.main.accent};
}
:active {
background-color: ${({ currentColorScheme }) =>
currentColorScheme.accentColor};
currentColorScheme.main.accent};
background: ${({ currentColorScheme }) => currentColorScheme.main.accent};
border: ${({ currentColorScheme }) => currentColorScheme.main.accent};
opacity: 1;
filter: brightness(90%);
cursor: pointer;
}
.button-content {
color: ${({ currentColorScheme }) => currentColorScheme.text.accent};
position: relative;
display: flex;
justify-content: space-between;

View File

@ -9,7 +9,6 @@ const StyledWrapper = styled.div`
left: -6px;
width: 0%;
height: 3px;
background-color: #eb835f;
-moz-border-radius: 1px;
-webkit-border-radius: 1px;
border-radius: 1px;

View File

@ -57,7 +57,14 @@ class ChangePasswordDialogComponent extends React.Component {
render() {
// console.log("ChangePasswordDialog render");
const { t, tReady, visible, email, onClose, theme } = this.props;
const {
t,
tReady,
visible,
email,
onClose,
currentColorScheme,
} = this.props;
const { isRequestRunning } = this.state;
return (
@ -80,7 +87,7 @@ class ChangePasswordDialogComponent extends React.Component {
type="page"
href={`mailto:${email}`}
noHover
color={theme.peopleDialogs.changePassword.linkColor}
color={currentColorScheme.main.accent}
title={email}
>
{{ email }}
@ -114,7 +121,7 @@ class ChangePasswordDialogComponent extends React.Component {
}
const ChangePasswordDialog = inject(({ auth }) => ({
theme: auth.settingsStore.theme,
currentColorScheme: auth.settingsStore.currentColorScheme,
}))(
observer(
withTranslation(["ChangePasswordDialog", "Common"])(

View File

@ -142,53 +142,11 @@ const StyledSelectedOwnerContainer = styled.div`
StyledSelectedOwnerContainer.defaultProps = { theme: Base };
const StyledSelectedOwner = styled.div`
width: fit-content;
height: 28px;
display: flex;
flex-direction: row;
align-items: center;
padding: 4px 15px;
gap: 8px;
box-sizing: border-box;
background: ${(props) =>
props.theme.filterInput.filter.selectedItem.background};
border-radius: 16px;
.text {
color: ${(props) => props.theme.filterInput.filter.selectedItem.color};
font-weight: 600;
font-size: 13px;
line-height: 20px;
}
.cross-icon {
display: flex;
align-items: center;
svg {
cursor: pointer;
path {
fill: ${(props) => props.theme.filterInput.filter.selectedItem.color};
}
}
}
`;
StyledSelectedOwner.defaultProps = { theme: Base };
export {
StyledOwnerInfo,
StyledPeopleSelectorInfo,
StyledPeopleSelector,
StyledAvailableList,
StyledFooterWrapper,
StyledSelectedOwner,
StyledSelectedOwnerContainer,
};

View File

@ -6,7 +6,8 @@ import { withTranslation } from "react-i18next";
import PeopleSelector from "SRC_DIR/components/PeopleSelector";
import Filter from "@docspace/common/api/people/filter";
import styled from "styled-components";
import { Base } from "@docspace/components/themes";
import ModalDialog from "@docspace/components/modal-dialog";
import Avatar from "@docspace/components/avatar";
import Text from "@docspace/components/text";
@ -21,10 +22,49 @@ import {
StyledPeopleSelector,
StyledAvailableList,
StyledFooterWrapper,
StyledSelectedOwner,
StyledSelectedOwnerContainer,
} from "./StyledDialog";
const StyledSelectedOwner = styled.div`
width: fit-content;
height: 28px;
display: flex;
flex-direction: row;
align-items: center;
padding: 4px 15px;
gap: 8px;
box-sizing: border-box;
background: ${({ currentColorScheme }) => currentColorScheme.main.accent};
border-radius: 16px;
.text {
color: ${({ currentColorScheme }) => currentColorScheme.text.accent};
font-weight: 600;
font-size: 13px;
line-height: 20px;
}
.cross-icon {
display: flex;
align-items: center;
svg {
cursor: pointer;
path {
fill: ${({ currentColorScheme }) => currentColorScheme.text.accent};
}
}
}
`;
StyledSelectedOwner.defaultProps = { theme: Base };
const filter = new Filter();
filter.employeeStatus = 1;
@ -39,6 +79,7 @@ const ChangePortalOwnerDialog = ({
displayName,
avatar,
id,
currentColorScheme,
}) => {
const [selectorVisible, setSelectorVisible] = React.useState(false);
const [isLoading, setIsLoading] = React.useState(false);
@ -144,7 +185,7 @@ const ChangePortalOwnerDialog = ({
{selectedUser ? (
<StyledSelectedOwnerContainer>
<StyledSelectedOwner>
<StyledSelectedOwner currentColorScheme={currentColorScheme}>
<Text className="text">{selectedUser.label}</Text>
<ReactSVG
className="cross-icon"
@ -223,10 +264,10 @@ const ChangePortalOwnerDialog = ({
export default inject(({ auth, setup }) => {
const { displayName, avatar, id } = auth.userStore.user;
const { currentColorScheme } = auth.settingsStore;
const { sendOwnerChange } = setup;
return { displayName, avatar, id, sendOwnerChange };
return { displayName, avatar, id, sendOwnerChange, currentColorScheme };
})(
withTranslation([
"ChangePortalOwner",

View File

@ -102,9 +102,9 @@ const StyledComboBox = styled(ComboBox)`
}
.combo-buttons_arrow-icon {
margin-top: 12px;
margin-top: 6px;
margin-right: 8px;
margin-left: 0px;
margin-left: 2px;
}
padding: 0px;

View File

@ -310,6 +310,7 @@ class SectionHeaderContent extends React.Component {
backgroundColor="#EDC409"
label="Paid"
className="settings-section_badge"
isPaidBadge={true}
/>
) : (
""

View File

@ -14,7 +14,7 @@ const StyledComponent = styled.div`
padding-bottom: 20px;
}
.theme-standard {
.theme-standard-container {
padding-top: 21px;
}
@ -29,16 +29,18 @@ const StyledComponent = styled.div`
display: flex;
}
.box {
.custom-themes {
display: flex;
}
.theme-add {
width: 46px;
height: 46px;
margin-right: 12px;
border-radius: 8px;
cursor: pointer;
}
.check-img {
padding: 18px 0 0 15px;
background: ${(props) => (props.theme.isBase ? "#eceef1" : "#474747")}
url("/static/images/plus.theme.svg") no-repeat center;
}
.add-theme {
@ -51,6 +53,39 @@ const StyledComponent = styled.div`
.buttons-container {
padding-top: 24px;
}
.button:not(:last-child) {
margin-right: 8px;
}
.check-img {
padding: 18px 0 0 15px;
svg path {
fill: ${(props) => props.colorCheckImg};
}
}
`;
export { StyledComponent };
const StyledTheme = styled.div`
width: 46px;
height: 46px;
margin-right: 12px;
border-radius: 8px;
cursor: pointer;
.check-hover {
visibility: hidden;
}
&:hover {
.check-hover {
padding: 18px 0 0 15px;
visibility: visible;
opacity: 0.5;
svg path {
fill: ${(props) => props.colorCheckImgHover};
}
}
}
`;
export { StyledComponent, StyledTheme };

View File

@ -227,14 +227,14 @@ const StyledComponent = styled.div`
}
.tablet-tile-name {
width: 33% !important;
width: 44% !important;
margin-left: 16px;
border-right: none !important;
border-radius: 12px 0 16px 0 !important;
}
.half {
width: ${(props) => props.isViewTablet && "51%"};
.only-tile-name {
width: ${(props) => props.isViewTablet && "66%"};
border-top-width: 1px;
border-right-width: 1px;
border-left-width: 1px;
@ -314,7 +314,7 @@ const IconBox = styled.div`
svg {
path {
fill: ${(props) => (props.themePreview === "Light" ? "#FFF" : "#292929")};
fill: ${(props) => props.colorCheckImg};
}
}
`;

View File

@ -12,15 +12,16 @@ import ButtonPlusIcon from "../../../../../../../../public/images/actions.button
const Preview = (props) => {
const {
selectAccentColor,
previewAccent,
themePreview,
selectThemeId,
withBorder,
withTileActions,
floatingButtonClass,
colorCheckImg,
} = props;
const [colorPreview, setColorPreview] = useState(selectAccentColor);
const [colorPreview, setColorPreview] = useState(previewAccent);
const [isViewTablet, setIsViewTablet] = useState(false);
const onCheckView = () => {
@ -30,8 +31,8 @@ const Preview = (props) => {
};
useEffect(() => {
setColorPreview(selectAccentColor);
}, [selectAccentColor]);
setColorPreview(previewAccent);
}, [previewAccent]);
useEffect(() => {
onCheckView();
@ -335,7 +336,7 @@ const Preview = (props) => {
</div>
<div className="section-flex-tablet">
<div className="tile-name half background border-color">
<div className="tile-name only-tile-name background border-color">
<div className="tile-container">
<div className="tile-icon">
<Loaders.Rectangle
@ -378,7 +379,7 @@ const Preview = (props) => {
</div>
{isViewTablet && (
<div className="tile-name half background border-color tablet-tile-name">
<div className="tile-name only-tile-name background border-color tablet-tile-name">
<div className="tile-container">
<div className="tile-icon">
<Loaders.Rectangle
@ -414,6 +415,7 @@ const Preview = (props) => {
colorPreview={colorPreview}
themePreview={themePreview}
selectThemeId={selectThemeId}
colorCheckImg={colorCheckImg}
>
<ButtonPlusIcon />
</IconBox>

View File

@ -160,7 +160,9 @@ const WhiteLabel = (props) => {
<Text fontSize="16px" fontWeight="700">
{t("WhiteLabel")}
</Text>
{!isSettingPaid && <Badge backgroundColor="#EDC409" label="Paid" />}
{!isSettingPaid && (
<Badge backgroundColor="#EDC409" label="Paid" isPaidBadge={true} />
)}
</div>
<Text className="wl-subtitle settings_unavailable" fontSize="12px">
{t("WhiteLabelSubtitle")}

View File

@ -130,7 +130,9 @@ const DNSSettings = (props) => {
tooltipContent={tooltipDNSSettingsTooltip}
className="dns-setting_helpbutton "
/>
{!isSettingPaid && <Badge backgroundColor="#EDC409" label="Paid" />}
{!isSettingPaid && (
<Badge backgroundColor="#EDC409" label="Paid" isPaidBadge={true} />
)}
</div>
)}
{(isMobileOnly && isSmallTablet()) || isSmallTablet() ? (

View File

@ -414,6 +414,7 @@ class LanguageAndTimeZone extends React.Component {
isLoadedPage,
helpLink,
organizationName,
currentColorScheme,
} = this.props;
const {
@ -434,6 +435,7 @@ class LanguageAndTimeZone extends React.Component {
t={t}
helpLink={helpLink}
organizationName={organizationName}
currentColorScheme={currentColorScheme}
/>
);
@ -533,6 +535,7 @@ export default inject(({ auth, setup, common }) => {
getCurrentCustomSchema,
cultures,
helpLink,
currentColorScheme,
} = auth.settingsStore;
const { user } = auth.userStore;
@ -563,6 +566,7 @@ export default inject(({ auth, setup, common }) => {
helpLink,
initSettings,
setIsLoaded,
currentColorScheme,
};
})(
withLoading(

View File

@ -4,7 +4,8 @@ import { withRouter } from "react-router";
import toastr from "@docspace/components/toast/toastr";
import { inject, observer } from "mobx-react";
import Button from "@docspace/components/button";
import Tooltip from "@docspace/components/tooltip";
import Text from "@docspace/components/text";
import TabContainer from "@docspace/components/tabs-container";
import Preview from "./Appearance/preview";
@ -18,9 +19,11 @@ import { isMobileOnly } from "react-device-detect";
import Loader from "./sub-components/loaderAppearance";
import { StyledComponent } from "./Appearance/StyledApperance.js";
import { StyledComponent, StyledTheme } from "./Appearance/StyledApperance.js";
import { ReactSVG } from "react-svg";
import BreakpointWarning from "../../../../components/BreakpointWarning/index";
import ModalDialogDelete from "./sub-components/modalDialogDelete";
import hexToRgba from "hex-to-rgba";
const Appearance = (props) => {
const {
@ -29,16 +32,23 @@ const Appearance = (props) => {
sendAppearanceTheme,
getAppearanceTheme,
currentColorScheme,
deleteAppearanceTheme,
tReady,
t,
} = props;
const [previewTheme, setPreviewTheme] = useState("Light theme");
const defaultAppliedColor = "#AABBCC";
const headerAddTheme = t("Settings:NewColorScheme");
const headerEditTheme = t("Settings:EditColorScheme");
const checkImg = "static/images/check.white.svg";
const checkImgHover = <ReactSVG className="check-hover" src={checkImg} />;
const [showColorSchemeDialog, setShowColorSchemeDialog] = useState(false);
const [headerColorSchemeDialog, setHeaderColorSchemeDialog] = useState(
"Edit color scheme"
headerEditTheme
);
const [currentColorAccent, setCurrentColorAccent] = useState(null);
@ -51,9 +61,12 @@ const Appearance = (props) => {
false
);
//TODO: Add default color
const [appliedColorAccent, setAppliedColorAccent] = useState("#F97A0B");
const [appliedColorButtons, setAppliedColorButtons] = useState("#FF9933");
const [appliedColorAccent, setAppliedColorAccent] = useState(
defaultAppliedColor
);
const [appliedColorButtons, setAppliedColorButtons] = useState(
defaultAppliedColor
);
const [changeCurrentColorAccent, setChangeCurrentColorAccent] = useState(
false
@ -65,23 +78,34 @@ const Appearance = (props) => {
const [viewMobile, setViewMobile] = useState(false);
const [showSaveButtonDialog, setShowSaveButtonDialog] = useState(false);
const [
showRestoreToDefaultButtonDialog,
setShowRestoreToDefaultButtonDialog,
] = useState(false);
const [isEditDialog, setIsEditDialog] = useState(false);
const [isAddThemeDialog, setIsAddThemeDialog] = useState(false);
const [selectAccentColor, setSelectAccentColor] = useState(
currentColorScheme.accentColor
const [previewAccent, setPreviewAccent] = useState(
currentColorScheme.main.accent
);
const [selectThemeId, setSelectThemeId] = useState(selectedThemeId);
const [changeColorTheme, setChangeColorTheme] = useState(false);
const checkImg = (
<img className="check-img" src="/static/images/check.white.svg" />
const [colorCheckImg, setColorCheckImg] = useState(
currentColorScheme.text.accent
);
const [colorCheckImgHover, setColorCheckImgHover] = useState(
currentColorScheme.text.accent
);
const [selectThemeId, setSelectThemeId] = useState(selectedThemeId);
const [isDisabledSaveButton, setIsDisabledSaveButton] = useState(true);
const [abilityAddTheme, setAbilityAddTheme] = useState(true);
const [isDisabledEditButton, setIsDisabledEditButton] = useState(true);
const [isDisabledDeleteButton, setIsDisabledDeleteButton] = useState(true);
const [isShowDeleteButton, setIsShowDeleteButton] = useState(false);
const [visibleDialog, setVisibleDialog] = useState(false);
const [theme, setTheme] = useState(appearanceTheme);
const array_items = useMemo(
() => [
@ -90,9 +114,9 @@ const Appearance = (props) => {
title: t("Profile:LightTheme"),
content: (
<Preview
previewTheme={previewTheme}
selectAccentColor={selectAccentColor}
previewAccent={previewAccent}
selectThemeId={selectThemeId}
colorCheckImg={colorCheckImg}
themePreview="Light"
/>
),
@ -102,30 +126,78 @@ const Appearance = (props) => {
title: t("Profile:DarkTheme"),
content: (
<Preview
previewTheme={previewTheme}
selectAccentColor={selectAccentColor}
previewAccent={previewAccent}
selectThemeId={selectThemeId}
colorCheckImg={colorCheckImg}
themePreview="Dark"
/>
),
},
],
[selectAccentColor, previewTheme, selectThemeId, tReady]
[previewAccent, selectThemeId, colorCheckImg, tReady]
);
useEffect(() => {
onCheckView();
window.addEventListener("resize", onCheckView);
return () => window.removeEventListener("resize", onCheckView);
return () => {
window.removeEventListener("resize", onCheckView);
};
}, []);
useEffect(() => {
// Set the Save button to disabled
if (selectAccentColor !== currentColorScheme.accentColor) {
setChangeColorTheme(true);
onColorCheck(appearanceTheme);
// Setting a checkbox for a new theme
setTheme(appearanceTheme);
if (appearanceTheme.length > theme.length) {
const newTheme = appearanceTheme[appearanceTheme.length - 1];
const idNewTheme = newTheme.id;
const accentNewTheme = newTheme.main.accent;
setSelectThemeId(idNewTheme);
setPreviewAccent(accentNewTheme);
}
if (appearanceTheme.length === 9) {
setAbilityAddTheme(false);
} else {
setChangeColorTheme(false);
setAbilityAddTheme(true);
}
if (appearanceTheme.length === 6) {
setIsShowDeleteButton(false);
} else {
setIsShowDeleteButton(true);
}
}, [
appearanceTheme,
theme,
setSelectThemeId,
setPreviewAccent,
setAbilityAddTheme,
setIsShowDeleteButton,
]);
useEffect(() => {
onColorCheck(appearanceTheme);
if (appearanceTheme.find((theme) => theme.id == selectThemeId).name) {
setIsDisabledEditButton(true);
setIsDisabledDeleteButton(true);
return;
}
setIsDisabledEditButton(false);
setIsDisabledDeleteButton(false);
}, [selectThemeId]);
useEffect(() => {
if (selectThemeId === selectedThemeId) {
setIsDisabledSaveButton(true);
} else {
setIsDisabledSaveButton(false);
}
if (
@ -142,14 +214,47 @@ const Appearance = (props) => {
) {
setShowSaveButtonDialog(true);
}
if (
!changeCurrentColorAccent &&
!changeCurrentColorButtons &&
isEditDialog
) {
setShowSaveButtonDialog(false);
}
}, [
selectedThemeId,
selectThemeId,
changeCurrentColorAccent,
changeCurrentColorButtons,
isAddThemeDialog,
isEditDialog,
selectAccentColor,
previewAccent,
]);
const onColorCheck = useCallback(
(themes) => {
const colorCheckImg = themes.find((theme) => theme.id == selectThemeId)
?.text.accent;
setColorCheckImg(colorCheckImg);
},
[selectThemeId]
);
const onColorCheckImgHover = useCallback(
(e) => {
const id = e.target.id;
if (!id) return;
const colorCheckImg = appearanceTheme.find((theme) => theme.id == id).text
.accent;
setColorCheckImgHover(colorCheckImg);
},
[appearanceTheme]
);
const onCheckView = () => {
if (isMobileOnly || window.innerWidth < 600) {
setViewMobile(true);
@ -158,47 +263,78 @@ const Appearance = (props) => {
}
};
const onColorSelection = (item) => {
setSelectAccentColor(item.accentColor);
setSelectThemeId(item.id);
const onColorSelection = useCallback(
(e) => {
const theme = e.currentTarget;
const id = +theme.id;
const accent = appearanceTheme.find((theme) => theme.id == id).main
.accent;
setPreviewAccent(accent);
setSelectThemeId(id);
},
[appearanceTheme, setPreviewAccent, setSelectThemeId]
);
const onSave = useCallback(async () => {
setIsDisabledSaveButton(true);
if (!selectThemeId) return;
try {
await sendAppearanceTheme({ selected: selectThemeId });
await getAppearanceTheme();
toastr.success(t("Settings:SuccessfullySaveSettingsMessage"));
} catch (error) {
toastr.error(error);
}
}, [
selectThemeId,
setIsDisabledSaveButton,
sendAppearanceTheme,
getAppearanceTheme,
]);
// Open HexColorPicker
const onClickColor = (e) => {
if (e.target.id === "accent") {
setOpenHexColorPickerAccent(true);
setOpenHexColorPickerButtons(false);
} else {
setOpenHexColorPickerButtons(true);
setOpenHexColorPickerAccent(false);
}
};
const onShowCheck = (colorNumber) => {
return selectThemeId && selectThemeId === colorNumber && checkImg;
};
const onClickDeleteModal = useCallback(async () => {
try {
await deleteAppearanceTheme(selectThemeId);
await getAppearanceTheme();
const onChangePreviewTheme = (e) => {
setPreviewTheme(e.title);
};
const onSaveSelectedColor = () => {
sendAppearanceTheme({ selected: selectThemeId })
.then(() => {
toastr.success(t("Settings:SuccessfullySaveSettingsMessage"));
getAppearanceTheme();
setChangeColorTheme(false);
})
.catch((error) => {
toastr.error(error);
});
};
const onClickEdit = () => {
appearanceTheme.map((item) => {
if (item.id === selectThemeId) {
setCurrentColorAccent(item.accentColor);
setCurrentColorButtons(item.buttonsMain);
if (selectedThemeId !== selectThemeId) {
setSelectThemeId(selectedThemeId);
setPreviewAccent(currentColorScheme.main.accent);
}
});
setIsEditDialog(true);
if (selectedThemeId === selectThemeId) {
setSelectThemeId(appearanceTheme[0].id);
setPreviewAccent(appearanceTheme[0].main.accent);
}
setHeaderColorSchemeDialog("Edit color scheme");
onCloseDialogDelete();
setShowRestoreToDefaultButtonDialog(true);
setShowColorSchemeDialog(true);
};
toastr.success(t("Settings:SuccessfullySaveSettingsMessage"));
} catch (error) {
toastr.error(error);
}
}, [
selectThemeId,
selectedThemeId,
onCloseDialogDelete,
deleteAppearanceTheme,
getAppearanceTheme,
]);
const onCloseColorSchemeDialog = () => {
setShowColorSchemeDialog(false);
@ -213,88 +349,204 @@ const Appearance = (props) => {
setIsAddThemeDialog(false);
setShowSaveButtonDialog(false);
setCurrentColorAccent(null);
setCurrentColorButtons(null);
setAppliedColorAccent(defaultAppliedColor);
setAppliedColorButtons(defaultAppliedColor);
};
const onAddTheme = () => {
if (!abilityAddTheme) return;
setIsAddThemeDialog(true);
setCurrentColorAccent(
"url(/static/images/plus.theme.svg) 15px 15px no-repeat #D0D5DA"
);
setCurrentColorButtons(
"url(/static/images/plus.theme.svg) 15px 15px no-repeat #D0D5DA"
);
setHeaderColorSchemeDialog("New color scheme");
setHeaderColorSchemeDialog(headerAddTheme);
setShowColorSchemeDialog(true);
};
const onClickColor = (e) => {
if (e.target.id === "accent") {
setOpenHexColorPickerAccent(true);
setOpenHexColorPickerButtons(false);
} else {
setOpenHexColorPickerButtons(true);
setOpenHexColorPickerAccent(false);
}
const onClickEdit = () => {
appearanceTheme.map((item) => {
if (item.id === selectThemeId) {
setCurrentColorAccent(item.main.accent.toUpperCase());
setCurrentColorButtons(item.main.buttons.toUpperCase());
setAppliedColorAccent(item.main.accent.toUpperCase());
setAppliedColorButtons(item.main.buttons.toUpperCase());
}
});
setIsEditDialog(true);
setHeaderColorSchemeDialog(headerEditTheme);
setShowColorSchemeDialog(true);
};
const onCloseHexColorPicker = () => {
const onCloseHexColorPickerAccent = useCallback(() => {
setOpenHexColorPickerAccent(false);
if (!currentColorAccent) return;
setAppliedColorAccent(currentColorAccent);
}, [currentColorAccent, setOpenHexColorPickerAccent, setAppliedColorAccent]);
const onCloseHexColorPickerButtons = useCallback(() => {
setOpenHexColorPickerButtons(false);
if (!currentColorButtons) return;
setAppliedColorButtons(currentColorButtons);
}, [
currentColorButtons,
setOpenHexColorPickerButtons,
setAppliedColorButtons,
]);
const getTextColor = (color) => {
const black = "#333333";
const white = "#FFFFFF";
const rgba = hexToRgba(color)
.replace("rgba(", "")
.replace(")", "")
.split(", ");
const r = rgba[0];
const g = rgba[1];
const b = rgba[2];
const textColor =
(r * 299 + g * 587 + b * 114) / 1000 > 128 ? black : white;
return textColor;
};
const onAppliedColorAccent = useCallback(() => {
if (appliedColorAccent.toUpperCase() !== currentColorAccent) {
setChangeCurrentColorAccent(true);
}
setCurrentColorAccent(appliedColorAccent);
onCloseHexColorPicker();
if (appliedColorAccent === currentColorAccent) return;
setChangeCurrentColorAccent(true);
}, [appliedColorAccent, currentColorAccent]);
setOpenHexColorPickerAccent(false);
}, [
appliedColorAccent,
currentColorAccent,
setChangeCurrentColorAccent,
setOpenHexColorPickerAccent,
]);
const onAppliedColorButtons = useCallback(() => {
if (appliedColorButtons.toUpperCase() !== currentColorButtons) {
setChangeCurrentColorButtons(true);
}
setCurrentColorButtons(appliedColorButtons);
onCloseHexColorPicker();
setOpenHexColorPickerButtons(false);
}, [
appliedColorButtons,
currentColorButtons,
setChangeCurrentColorButtons,
setOpenHexColorPickerButtons,
]);
if (appliedColorButtons === currentColorButtons) return;
const onSaveNewThemes = useCallback(
async (theme) => {
try {
await sendAppearanceTheme({ theme: theme });
await getAppearanceTheme();
setChangeCurrentColorButtons(true);
}, [appliedColorButtons]);
toastr.success(t("Settings:SuccessfullySaveSettingsMessage"));
} catch (error) {
toastr.error(error);
}
},
[sendAppearanceTheme, getAppearanceTheme]
);
const onSaveChangedThemes = useCallback(
async (editTheme) => {
try {
await sendAppearanceTheme({ theme: editTheme });
await getAppearanceTheme();
setPreviewAccent(editTheme.main.accent);
toastr.success(t("Settings:SuccessfullySaveSettingsMessage"));
} catch (error) {
toastr.error(error);
}
},
[sendAppearanceTheme, getAppearanceTheme]
);
const onSaveColorSchemeDialog = () => {
const theme = {
id: selectTheme.id,
accentColor: currentColorAccent,
buttonsMain: currentColorButtons,
textColor: "#FFFFFF",
const textColorAccent = getTextColor(currentColorAccent);
const textColorButtons = getTextColor(currentColorButtons);
if (isAddThemeDialog) {
// Saving a new custom theme
const theme = {
main: {
accent: currentColorAccent,
buttons: currentColorButtons,
},
text: {
accent: textColorAccent,
buttons: textColorButtons,
},
};
onSaveNewThemes(theme);
setCurrentColorAccent(null);
setCurrentColorButtons(null);
onCloseColorSchemeDialog();
return;
}
// Editing themes
const editTheme = {
id: selectThemeId,
main: {
accent: currentColorAccent,
buttons: currentColorButtons,
},
text: {
accent: textColorAccent,
buttons: textColorButtons,
},
};
onSaveChangedThemes(editTheme);
setCurrentColorAccent(appliedColorAccent);
setCurrentColorButtons(appliedColorButtons);
onCloseColorSchemeDialog();
};
const nodeHexColorPickerButtons = viewMobile ? (
<HexColorPickerComponent
id="buttons-hex"
onCloseHexColorPicker={onCloseHexColorPicker}
onAppliedColor={onAppliedColorButtons}
color={appliedColorButtons}
setColor={setAppliedColorButtons}
viewMobile={viewMobile}
/>
) : (
const onCloseDialogDelete = () => {
setVisibleDialog(false);
};
const onOpenDialogDelete = () => {
setVisibleDialog(true);
};
const nodeHexColorPickerButtons = (
<DropDownContainer
directionX="right"
manualY="62px"
withBackdrop={false}
isDefaultMode={false}
open={openHexColorPickerButtons}
clickOutsideAction={onCloseHexColorPicker}
clickOutsideAction={onCloseHexColorPickerButtons}
>
<DropDownItem className="drop-down-item-hex">
<HexColorPickerComponent
id="buttons-hex"
onCloseHexColorPicker={onCloseHexColorPicker}
onCloseHexColorPicker={onCloseHexColorPickerButtons}
onAppliedColor={onAppliedColorButtons}
color={appliedColorButtons}
setColor={setAppliedColorButtons}
@ -304,29 +556,20 @@ const Appearance = (props) => {
</DropDownContainer>
);
const nodeHexColorPickerAccent = viewMobile ? (
<HexColorPickerComponent
id="accent-hex"
onCloseHexColorPicker={onCloseHexColorPicker}
onAppliedColor={onAppliedColorAccent}
color={appliedColorAccent}
setColor={setAppliedColorAccent}
viewMobile={viewMobile}
/>
) : (
const nodeHexColorPickerAccent = (
<DropDownContainer
directionX="right"
manualY="62px"
withBackdrop={false}
isDefaultMode={false}
open={openHexColorPickerAccent}
clickOutsideAction={onCloseHexColorPicker}
clickOutsideAction={onCloseHexColorPickerAccent}
viewMobile={viewMobile}
>
<DropDownItem className="drop-down-item-hex">
<HexColorPickerComponent
id="accent-hex"
onCloseHexColorPicker={onCloseHexColorPicker}
onCloseHexColorPicker={onCloseHexColorPickerAccent}
onAppliedColor={onAppliedColorAccent}
color={appliedColorAccent}
setColor={setAppliedColorAccent}
@ -336,80 +579,147 @@ const Appearance = (props) => {
</DropDownContainer>
);
const nodeAccentColor = (
<div
id="accent"
style={{ background: currentColorAccent }}
className="color-button"
onClick={onClickColor}
></div>
);
const nodeButtonsColor = (
<div
id="buttons"
style={{ background: currentColorButtons }}
className="color-button"
onClick={onClickColor}
></div>
);
const textTooltip = () => {
return (
<Text fontSize="12px" noSelect>
{t("Settings:LimitThemesTooltip")}
</Text>
);
};
return viewMobile ? (
<BreakpointWarning sectionName={t("Settings:Appearance")} />
) : !tReady ? (
<Loader />
) : (
<StyledComponent>
<div className="header">{t("Common:Color")}</div>
<div className="theme-standard">
<div className="theme-name">{t("Common:Standard")}</div>
<div className="theme-container">
{appearanceTheme.map((item, index) => {
return (
<div
key={index}
id={item.id}
style={{ background: item.accentColor }}
className="box"
onClick={() => onColorSelection(item)}
>
{onShowCheck(item.id)}
</div>
);
})}
</div>
</div>
<ColorSchemeDialog
nodeButtonsColor={nodeButtonsColor}
nodeAccentColor={nodeAccentColor}
nodeHexColorPickerAccent={nodeHexColorPickerAccent}
nodeHexColorPickerButtons={nodeHexColorPickerButtons}
visible={showColorSchemeDialog}
onClose={onCloseColorSchemeDialog}
header={headerColorSchemeDialog}
viewMobile={viewMobile}
openHexColorPickerButtons={openHexColorPickerButtons}
openHexColorPickerAccent={openHexColorPickerAccent}
showRestoreToDefaultButtonDialog={showRestoreToDefaultButtonDialog}
showSaveButtonDialog={showSaveButtonDialog}
onSaveColorSchemeDialog={onSaveColorSchemeDialog}
<>
<ModalDialogDelete
visible={visibleDialog}
onClose={onCloseDialogDelete}
onClickDelete={onClickDeleteModal}
/>
<div className="header preview-header">{t("Common:Preview")}</div>
<TabContainer elements={array_items} onSelect={onChangePreviewTheme} />
<div className="buttons-container">
<Button
label="Save"
onClick={onSaveSelectedColor}
primary
size="small"
isDisabled={!changeColorTheme}
<StyledComponent colorCheckImg={colorCheckImg}>
<div className="header">{t("Common:Color")}</div>
<div className="theme-standard-container">
<div className="theme-name">{t("Common:Standard")}</div>
<div className="theme-container">
{appearanceTheme.map((item, index) => {
if (!item.name) return;
return (
<StyledTheme
key={index}
id={item.id}
colorCheckImgHover={colorCheckImgHover}
style={{ background: item.main.accent }}
onClick={onColorSelection}
onMouseOver={onColorCheckImgHover}
>
{selectThemeId === item.id && (
<ReactSVG className="check-img" src={checkImg} />
)}
{selectThemeId !== item.id && checkImgHover}
</StyledTheme>
);
})}
</div>
</div>
<div className="theme-custom-container">
<div className="theme-name">{t("Settings:Custom")}</div>
<div className="theme-container">
<div className="custom-themes">
{appearanceTheme.map((item, index) => {
if (item.name) return;
return (
<StyledTheme
key={index}
id={item.id}
style={{ background: item.main.accent }}
colorCheckImgHover={colorCheckImgHover}
onClick={onColorSelection}
onMouseOver={onColorCheckImgHover}
>
{selectThemeId === item.id && (
<ReactSVG className="check-img" src={checkImg} />
)}
{selectThemeId !== item.id && checkImgHover}
</StyledTheme>
);
})}
</div>
<div
data-for="theme-add"
data-tip="tooltip"
className="theme-add"
onClick={onAddTheme}
/>
{!abilityAddTheme && (
<Tooltip
id="theme-add"
offsetBottom={0}
offsetRight={130}
effect="solid"
place="bottom"
getContent={textTooltip}
maxWidth="300px"
/>
)}
</div>
</div>
<ColorSchemeDialog
onClickColor={onClickColor}
currentColorAccent={currentColorAccent}
currentColorButtons={currentColorButtons}
nodeHexColorPickerAccent={nodeHexColorPickerAccent}
nodeHexColorPickerButtons={nodeHexColorPickerButtons}
visible={showColorSchemeDialog}
onClose={onCloseColorSchemeDialog}
header={headerColorSchemeDialog}
viewMobile={viewMobile}
openHexColorPickerButtons={openHexColorPickerButtons}
openHexColorPickerAccent={openHexColorPickerAccent}
showSaveButtonDialog={showSaveButtonDialog}
onSaveColorSchemeDialog={onSaveColorSchemeDialog}
/>
</div>
</StyledComponent>
<div className="header preview-header">{t("Common:Preview")}</div>
<TabContainer elements={array_items} />
<div className="buttons-container">
<Button
className="button"
label={t("Common:SaveButton")}
onClick={onSave}
primary
size="small"
isDisabled={isDisabledSaveButton}
/>
<Button
className="button"
label={t("Settings:EditCurrentTheme")}
onClick={onClickEdit}
size="small"
isDisabled={isDisabledEditButton}
/>
{isShowDeleteButton && (
<Button
className="button"
label={t("Settings:DeleteTheme")}
onClick={onOpenDialogDelete}
size="small"
isDisabled={isDisabledDeleteButton}
/>
)}
</div>
</StyledComponent>
</>
);
};
@ -421,6 +731,8 @@ export default inject(({ auth }) => {
sendAppearanceTheme,
getAppearanceTheme,
currentColorScheme,
deleteAppearanceTheme,
theme,
} = settingsStore;
return {
@ -429,6 +741,8 @@ export default inject(({ auth }) => {
sendAppearanceTheme,
getAppearanceTheme,
currentColorScheme,
deleteAppearanceTheme,
theme,
};
})(
withTranslation(["Profile", "Common", "Settings"])(

View File

@ -68,6 +68,7 @@ const CustomizationNavbar = ({
setIsLoadedCustomizationNavbar,
isLoadedPage,
isSettingPaid,
currentColorScheme,
}) => {
const isLoadedSetting = isLoaded && tReady;
useEffect(() => {
@ -104,7 +105,7 @@ const CustomizationNavbar = ({
<Box paddingProp="10px 0 3px 0">
<Link
className="link-learn-more"
color={theme.client.settings.common.linkColorHelp}
color={currentColorScheme.main.accent}
target="_blank"
isHovered={true}
href={helpUrlCommonSettings}
@ -147,7 +148,13 @@ const CustomizationNavbar = ({
>
{t("DNSSettings")}
</Link>
{!isSettingPaid && <Badge backgroundColor="#EDC409" label="Paid" />}
{!isSettingPaid && (
<Badge
backgroundColor="#EDC409"
label={t("Common:Paid")}
isPaidBadge={true}
/>
)}
<StyledArrowRightIcon size="small" color="#333333" />
</div>
</div>
@ -156,7 +163,7 @@ const CustomizationNavbar = ({
</Text>
<Box paddingProp="10px 0 3px 0">
<Link
color={theme.client.settings.common.linkColorHelp}
color={currentColorScheme.main.accent}
target="_blank"
isHovered={true}
href={helpUrlCommonSettings}
@ -190,13 +197,18 @@ const CustomizationNavbar = ({
};
export default inject(({ auth, common }) => {
const { helpUrlCommonSettings, theme } = auth.settingsStore;
const {
helpUrlCommonSettings,
theme,
currentColorScheme,
} = auth.settingsStore;
const { isLoaded, setIsLoadedCustomizationNavbar } = common;
return {
theme,
helpUrlCommonSettings,
isLoaded,
setIsLoadedCustomizationNavbar,
currentColorScheme,
};
})(
withRouter(

View File

@ -1,7 +1,8 @@
import React from "react";
import React, { useEffect } from "react";
import ModalDialog from "@docspace/components/modal-dialog";
import styled from "styled-components";
import Button from "@docspace/components/button";
import { withTranslation } from "react-i18next";
const StyledComponent = styled(ModalDialog)`
.modal-dialog-aside-footer {
@ -21,20 +22,40 @@ const StyledComponent = styled(ModalDialog)`
}
}
.text {
.name-color {
font-weight: 700;
font-size: 18px;
line-height: 24px;
}
.color-button {
width: 46px;
height: 46px;
}
.relative {
position: relative;
}
.accent-box {
background: ${(props) =>
props.currentColorAccent
? props.currentColorAccent
: props.theme.isBase
? `#eceef1 url("/static/images/plus.theme.svg") no-repeat center`
: `#474747 url("/static/images/plus.theme.svg") no-repeat center`};
}
.buttons-box {
background: ${(props) =>
props.currentColorButtons
? props.currentColorButtons
: props.theme.isBase
? `#eceef1 url("/static/images/plus.theme.svg") no-repeat center`
: `#474747 url("/static/images/plus.theme.svg") no-repeat center`};
}
.modal-add-theme {
width: 46px;
height: 46px;
border-radius: 8px;
cursor: pointer;
}
`;
const ColorSchemeDialog = (props) => {
@ -42,40 +63,55 @@ const ColorSchemeDialog = (props) => {
visible,
onClose,
header,
nodeButtonsColor,
nodeAccentColor,
nodeHexColorPickerAccent,
nodeHexColorPickerButtons,
viewMobile,
openHexColorPickerButtons,
openHexColorPickerAccent,
showRestoreToDefaultButtonDialog,
showSaveButtonDialog,
onSaveColorSchemeDialog,
t,
onClickColor,
currentColorAccent,
currentColorButtons,
} = props;
const onKeyPress = (e) =>
(e.key === "Esc" || e.key === "Escape") && onClose();
useEffect(() => {
window.addEventListener("keyup", onKeyPress);
return () => window.removeEventListener("keyup", onKeyPress);
});
return (
<StyledComponent visible={visible} onClose={onClose} displayType="aside">
<StyledComponent
visible={visible}
onClose={onClose}
displayType="aside"
currentColorAccent={currentColorAccent}
currentColorButtons={currentColorButtons}
withFooterBorder={showSaveButtonDialog}
>
<ModalDialog.Header>{header}</ModalDialog.Header>
<ModalDialog.Body>
<div>
<div className="flex relative">
<div className="text">Accent</div>
{nodeAccentColor}
<div className="name-color">{t("Settings:Accent")}</div>
<div
id="accent"
className="modal-add-theme accent-box"
onClick={onClickColor}
/>
{!viewMobile && nodeHexColorPickerAccent}
</div>
<div className="flex relative">
<div className="text">Buttons</div>
{nodeButtonsColor}
<div className="name-color">{t("Settings:Buttons")}</div>
<div
id="buttons"
className="modal-add-theme buttons-box"
onClick={onClickColor}
/>
{!viewMobile && nodeHexColorPickerButtons}
</div>
@ -83,29 +119,26 @@ const ColorSchemeDialog = (props) => {
</ModalDialog.Body>
<ModalDialog.Footer>
<>
{showSaveButtonDialog && (
{showSaveButtonDialog && (
<>
<Button
label="Save"
label={t("Common:SaveButton")}
size="normal"
className="save-button"
primary={true}
scale={true}
primary
scale
onClick={onSaveColorSchemeDialog}
/>
)}
{showRestoreToDefaultButtonDialog && (
<Button
label="Restore to default"
className="button"
label={t("Common:CancelButton")}
size="normal"
scale={true}
scale
onClick={onClose}
/>
)}
</>
</>
)}
</ModalDialog.Footer>
</StyledComponent>
);
};
export default ColorSchemeDialog;
export default withTranslation(["Common", "Settings"])(ColorSchemeDialog);

View File

@ -23,6 +23,7 @@ export const LanguageTimeSettingsTooltip = ({
theme,
helpLink,
organizationName,
currentColorScheme,
}) => {
const learnMore = t("Common:LearnMore");
const text = t("Settings:StudioTimeLanguageSettings");
@ -47,7 +48,7 @@ export const LanguageTimeSettingsTooltip = ({
<div className="bold display-inline font-size"> {{ save }}</div>
button at the bottom of the section.
<Link
color={theme.client.settings.common.linkColorHelp}
color={currentColorScheme.main.accent}
className="display-block font-size"
isHovered={true}
target="_blank"

View File

@ -1,10 +1,7 @@
import React, { useState, useCallback, useEffect } from "react";
import styled, { css } from "styled-components";
import { inject, observer } from "mobx-react";
import React from "react";
import styled from "styled-components";
import Button from "@docspace/components/button";
import { HexColorPicker, HexColorInput } from "react-colorful";
import { isMobileOnly } from "react-device-detect";
const StyledComponent = styled.div`
.save-button {
@ -13,15 +10,19 @@ const StyledComponent = styled.div`
.hex-color-picker .react-colorful {
width: auto;
height: 239px;
padding-bottom: 16px;
height: 250px;
padding-bottom: 26px;
}
.react-colorful__saturation {
margin: 16px 0;
margin: 16px 0 26px 0;
border-radius: 3px;
}
.hex-color-picker .react-colorful__interactive {
width: 183px;
}
.hex-color-picker .react-colorful__saturation-pointer {
width: 14px;
height: 14px;
@ -34,21 +35,22 @@ const StyledComponent = styled.div`
}
.hex-color-picker .react-colorful__hue-pointer {
width: 24px;
height: 24px;
width: 30px;
height: 30px;
box-shadow: 0px 3px 10px rgba(0, 0, 0, 0.25);
border: 6px solid #fff;
border: 8px solid #fff;
}
.hex-value {
height: 32px;
outline: none;
padding: 6px 8px;
border: 1px solid #d0d5da;
border: 1px solid ${(props) => (props.theme.isBase ? "#d0d5da" : "#474747")};
border-radius: 3px;
width: 100%;
box-sizing: border-box;
background: ${(props) => !props.theme.isBase && "#282828"};
color: ${(props) => !props.theme.isBase && "#5C5C5C"};
}
.hex-value-label {
@ -63,46 +65,35 @@ const StyledComponent = styled.div`
}
}
@media (min-width: 428px) {
${!isMobileOnly &&
css`
.hex-color-picker {
display: flex;
flex-direction: column;
padding-bottom: 16px;
width: 195px;
}
.hex-color-picker {
display: flex;
flex-direction: column;
padding-bottom: 16px;
width: 195px;
}
.hex-value-container {
order: 2;
padding-bottom: 16px;
}
.hex-value-container {
order: 2;
padding-bottom: 16px;
}
.hex-color-picker .react-colorful {
order: 1;
}
.hex-color-picker .react-colorful {
order: 1;
}
.hex-button {
order: 3;
}
`}
.hex-button {
order: 3;
}
`;
const HexColorPickerComponent = (props) => {
const {
onCloseHexColorPicker,
onAppliedColor,
setColor,
color,
viewMobile,
} = props;
const { onCloseHexColorPicker, onAppliedColor, setColor, color } = props;
return (
<StyledComponent viewMobile={viewMobile}>
<StyledComponent>
<div className="hex-color-picker">
<div className="hex-value-container">
{!viewMobile && <div className="hex-value-label">Hex code:</div>}
<div className="hex-value-label">Hex code:</div>
<HexColorInput
className="hex-value"
@ -112,7 +103,7 @@ const HexColorPickerComponent = (props) => {
/>
</div>
<HexColorPicker color={color} onChange={setColor} />
<HexColorPicker color={color.toUpperCase()} onChange={setColor} />
<div className="hex-button">
<Button

View File

@ -0,0 +1,53 @@
import React, { useEffect } from "react";
import ModalDialog from "@docspace/components/modal-dialog";
import Button from "@docspace/components/button";
import styled from "styled-components";
import { withTranslation } from "react-i18next";
const StyledModalDialogDelete = styled(ModalDialog)`
.button-modal {
width: 50%;
}
`;
const ModalDialogDelete = (props) => {
const { visible, onClose, onClickDelete, t } = props;
const onKeyPress = (e) =>
(e.key === "Esc" || e.key === "Escape") && onClose();
useEffect(() => {
window.addEventListener("keyup", onKeyPress);
return () => window.removeEventListener("keyup", onKeyPress);
});
return (
<StyledModalDialogDelete
visible={visible}
onClose={onClose}
displayType="modal"
>
<ModalDialog.Header>
{t("Settings:DeleteThemeForever")}
</ModalDialog.Header>
<ModalDialog.Body>{t("Settings:DeleteThemeNotice")}</ModalDialog.Body>
<ModalDialog.Footer>
<Button
className="button-modal"
label={t("Common:Delete")}
onClick={onClickDelete}
primary
size="normal"
/>
<Button
className="button-modal"
label={t("Common:CancelButton")}
size="normal"
onClick={onClose}
/>
</ModalDialog.Footer>
</StyledModalDialogDelete>
);
};
export default withTranslation(["Common", "Settings"])(ModalDialogDelete);

View File

@ -447,6 +447,7 @@ class AutomaticBackup extends React.PureComponent {
backgroundColor="#EDC409"
label="Paid"
className="auto-backup_badge"
isPaidBadge={true}
/>
)}
</div>
@ -547,101 +548,101 @@ class AutomaticBackup extends React.PureComponent {
}
export default inject(
({ auth, backup, treeFoldersStore, selectFolderDialogStore }) => {
const { language, settingsStore, currentQuotaStore } = auth;
const { isRestoreAndAutoBackupAvailable } = currentQuotaStore;
const { organizationName, theme } = settingsStore;
const {
downloadingProgress,
backupSchedule,
//commonThirdPartyList,
clearProgressInterval,
deleteSchedule,
getProgress,
setThirdPartyStorage,
setDefaultOptions,
setBackupSchedule,
selectedStorageType,
seStorageType,
//setCommonThirdPartyList,
selectedPeriodLabel,
selectedWeekdayLabel,
selectedWeekday,
selectedHour,
selectedMonthDay,
selectedMaxCopiesNumber,
selectedPeriodNumber,
selectedFolderId,
selectedStorageId,
toDefault,
isFormReady,
getStorageParams,
setSelectedEnableSchedule,
selectedEnableSchedule,
updatePathSettings,
const { language, settingsStore, currentQuotaStore } = auth;
const { isRestoreAndAutoBackupAvailable } = currentQuotaStore;
const { organizationName, theme } = settingsStore;
const {
downloadingProgress,
backupSchedule,
//commonThirdPartyList,
clearProgressInterval,
deleteSchedule,
getProgress,
setThirdPartyStorage,
setDefaultOptions,
setBackupSchedule,
selectedStorageType,
seStorageType,
//setCommonThirdPartyList,
selectedPeriodLabel,
selectedWeekdayLabel,
selectedWeekday,
selectedHour,
selectedMonthDay,
selectedMaxCopiesNumber,
selectedPeriodNumber,
selectedFolderId,
selectedStorageId,
toDefault,
isFormReady,
getStorageParams,
setSelectedEnableSchedule,
selectedEnableSchedule,
updatePathSettings,
setStorageRegions,
setStorageRegions,
defaultFolderId,
} = backup;
} = backup;
const {
updateBaseFolderPath,
resetNewFolderPath,
} = selectFolderDialogStore;
const isCheckedDocuments = selectedStorageType === `${DocumentModuleType}`;
const isCheckedDocuments = selectedStorageType === `${DocumentModuleType}`;
const isCheckedThirdParty =
selectedStorageType === `${ResourcesModuleType}`;
const isCheckedThirdPartyStorage =
selectedStorageType === `${StorageModuleType}`;
const isCheckedThirdPartyStorage =
selectedStorageType === `${StorageModuleType}`;
const { rootFoldersTitles, fetchTreeFolders } = treeFoldersStore;
const { rootFoldersTitles, fetchTreeFolders } = treeFoldersStore;
return {
return {
defaultFolderId,
isEnableAuto: isRestoreAndAutoBackupAvailable,
fetchTreeFolders,
rootFoldersTitles,
downloadingProgress,
theme,
language,
isFormReady,
organizationName,
backupSchedule,
//commonThirdPartyList,
clearProgressInterval,
deleteSchedule,
getProgress,
setThirdPartyStorage,
setDefaultOptions,
setBackupSchedule,
selectedStorageType,
seStorageType,
//setCommonThirdPartyList,
selectedPeriodLabel,
selectedWeekdayLabel,
selectedWeekday,
selectedHour,
selectedMonthDay,
selectedMaxCopiesNumber,
selectedPeriodNumber,
selectedFolderId,
selectedStorageId,
isEnableAuto: isRestoreAndAutoBackupAvailable,
fetchTreeFolders,
rootFoldersTitles,
downloadingProgress,
theme,
language,
isFormReady,
organizationName,
backupSchedule,
//commonThirdPartyList,
clearProgressInterval,
deleteSchedule,
getProgress,
setThirdPartyStorage,
setDefaultOptions,
setBackupSchedule,
selectedStorageType,
seStorageType,
//setCommonThirdPartyList,
selectedPeriodLabel,
selectedWeekdayLabel,
selectedWeekday,
selectedHour,
selectedMonthDay,
selectedMaxCopiesNumber,
selectedPeriodNumber,
selectedFolderId,
selectedStorageId,
toDefault,
toDefault,
isCheckedThirdPartyStorage,
isCheckedThirdParty,
isCheckedDocuments,
isCheckedThirdPartyStorage,
isCheckedThirdParty,
isCheckedDocuments,
getStorageParams,
getStorageParams,
setSelectedEnableSchedule,
selectedEnableSchedule,
setSelectedEnableSchedule,
selectedEnableSchedule,
updatePathSettings,
updatePathSettings,
resetNewFolderPath,
setStorageRegions,
setStorageRegions,
updateBaseFolderPath,
};
};
}
)(withTranslation(["Settings", "Common"])(observer(AutomaticBackup)));

View File

@ -16,6 +16,7 @@ const Backup = ({
t,
history,
isNotPaidPeriod,
currentColorScheme,
}) => {
const renderTooltip = (helpInfo) => {
return (
@ -32,7 +33,7 @@ const Backup = ({
as="a"
href={helpUrlCreatingBackup}
target="_blank"
color="#555F65"
color={currentColorScheme.main.accent}
isBold
isHovered
>
@ -84,7 +85,11 @@ export default inject(({ auth }) => {
const { settingsStore, currentTariffStatusStore } = auth;
const { isNotPaidPeriod } = currentTariffStatusStore;
const { helpUrlCreatingBackup, isTabletView } = settingsStore;
const {
helpUrlCreatingBackup,
isTabletView,
currentColorScheme,
} = settingsStore;
const buttonSize = isTabletView ? "normal" : "small";
@ -92,5 +97,6 @@ export default inject(({ auth }) => {
helpUrlCreatingBackup,
buttonSize,
isNotPaidPeriod,
currentColorScheme,
};
})(observer(withTranslation(["Settings", "Common"])(Backup)));

View File

@ -72,6 +72,7 @@ const ToggleSSO = (props) => {
label="Paid"
maxWidth="31px"
className="toggle-caption_title_badge"
isPaidBadge={true}
/>
)}
</div>

View File

@ -121,6 +121,7 @@ class ThirdPartyServices extends React.Component {
updateConsumerProps,
urlAuthKeys,
theme,
currentColorScheme,
} = this.props;
const { dialogVisible, isLoading } = this.state;
const { onModalClose, onModalOpen, setConsumer, onChangeLoading } = this;
@ -131,7 +132,7 @@ class ThirdPartyServices extends React.Component {
<Text>{t("ThirdPartyTitleDescription")}</Text>
<Box marginProp="8px 0 24px 0">
<Link
color={theme.client.settings.integration.linkColor}
color={currentColorScheme.main.accent}
isHovered
target="_blank"
href={urlAuthKeys}
@ -186,7 +187,7 @@ ThirdPartyServices.propTypes = {
export default inject(({ setup, auth }) => {
const { settingsStore, setDocumentTitle } = auth;
const { urlAuthKeys, theme } = settingsStore;
const { urlAuthKeys, theme, currentColorScheme } = settingsStore;
const {
getConsumers,
integration,
@ -203,5 +204,6 @@ export default inject(({ setup, auth }) => {
updateConsumerProps,
setSelectedConsumer,
setDocumentTitle,
currentColorScheme,
};
})(withTranslation(["Settings", "Common"])(observer(ThirdPartyServices)));

View File

@ -17,7 +17,7 @@ import { size } from "@docspace/components/utils/device";
import { inject, observer } from "mobx-react";
const AccessPortal = (props) => {
const { t, helpLink } = props;
const { t, helpLink, currentColorScheme } = props;
const [isMobileView, setIsMobileView] = useState(false);
useEffect(() => {
@ -42,6 +42,7 @@ const AccessPortal = (props) => {
title={t("SettingPasswordStrength")}
tooltipTitle={t("SettingPasswordStrengthDescription")}
tooltipUrl={`${helpLink}/administration/configuration.aspx#ChangingSecuritySettings_block`}
currentColorScheme={currentColorScheme}
/>
<PasswordStrengthSection />
<StyledSettingsSeparator />
@ -50,6 +51,7 @@ const AccessPortal = (props) => {
title={t("TwoFactorAuth")}
tooltipTitle={t("TwoFactorAuthDescription")}
tooltipUrl={`${helpLink}/administration/two-factor-authentication.aspx`}
currentColorScheme={currentColorScheme}
/>
<TfaSection />
<StyledSettingsSeparator />
@ -58,6 +60,7 @@ const AccessPortal = (props) => {
title={t("TrustedMail")}
tooltipTitle={t("TrustedMailDescription")}
tooltipUrl={`${helpLink}/administration/configuration.aspx#ChangingSecuritySettings_block`}
currentColorScheme={currentColorScheme}
/>
<TrustedMailSection />
<StyledSettingsSeparator />
@ -74,6 +77,7 @@ const AccessPortal = (props) => {
title={t("AdminsMessage")}
tooltipTitle={t("AdminsMessageDescription")}
tooltipUrl={`${helpLink}/administration/configuration.aspx#ChangingSecuritySettings_block`}
currentColorScheme={currentColorScheme}
/>
<AdminMessageSection />
@ -89,6 +93,6 @@ const AccessPortal = (props) => {
};
export default inject(({ auth }) => {
const { helpLink } = auth.settingsStore;
return { helpLink };
const { helpLink, currentColorScheme } = auth.settingsStore;
return { helpLink, currentColorScheme };
})(withTranslation("Settings")(withRouter(observer(AccessPortal))));

View File

@ -154,7 +154,9 @@ const HistoryMainContent = (props) => {
return (
<MainContainer isSettingNotPaid={isSettingNotPaid}>
{isSettingNotPaid && <Badge backgroundColor="#EDC409" label="Paid" />}
{isSettingNotPaid && (
<Badge backgroundColor="#EDC409" label="Paid" isPaidBadge={true} />
)}
<div className="main-wrapper">
<Text fontSize="13px" color="#657077" className="settings_unavailable">
{subHeader}

View File

@ -6,13 +6,25 @@ import { Base } from "@docspace/components/themes";
import { StyledCategoryWrapper, StyledTooltip } from "../StyledSecurity";
const CategoryWrapper = (props) => {
const { t, title, tooltipTitle, tooltipUrl, theme } = props;
const {
t,
title,
tooltipTitle,
tooltipUrl,
theme,
currentColorScheme,
} = props;
const tooltip = () => (
<StyledTooltip>
<Text className={tooltipUrl ? "subtitle" : ""}>{tooltipTitle}</Text>
{tooltipUrl && (
<Link target="_blank" isHovered href={tooltipUrl}>
<Link
target="_blank"
isHovered
href={tooltipUrl}
color={currentColorScheme.main.accent}
>
{t("Common:LearnMore")}
</Link>
)}

View File

@ -6,7 +6,6 @@ const StyledBodyPreparationPortal = styled.div`
margin-bottom: 24px;
width: 100%;
max-width: ${(props) => (props.errorMessage ? "560px" : "480px")};
padding: 0 24px;
box-sizing: border-box;
align-items: center;
@ -15,23 +14,29 @@ const StyledBodyPreparationPortal = styled.div`
margin-bottom: 16px;
position: relative;
.preparation-portal_progress-bar {
border-radius: 2px;
padding: 2px;
box-sizing: border-box;
border-radius: 6px;
width: 100%;
height: 24px;
background-color: #f3f4f4;
background-color: ${(props) =>
props.theme.preparationPortalProgress.backgroundColor};
}
.preparation-portal_progress-line {
border-radius: inherit;
border-radius: 5px;
width: ${(props) => props.percent}%;
background: #439ccd;
height: inherit;
height: 20px;
transition-property: width;
transition-duration: 0.9s;
background: #1f97ca;
}
.preparation-portal_percent {
position: absolute;
${(props) => props.percent > 50 && "color: white"};
font-size: 14px;
font-weight: 600;
color: ${(props) =>
props.percent > 50
? props.theme.preparationPortalProgress.colorPercentBig
: props.theme.preparationPortalProgress.colorPercentSmall};
top: 2px;
left: calc(50% - 9px);
}

View File

@ -10,6 +10,7 @@ import Text from "@docspace/components/text";
import { getRestoreProgress } from "@docspace/common/api/portal";
import { observer, inject } from "mobx-react";
import PropTypes from "prop-types";
import { ColorTheme, ThemeType } from "@docspace/common/components/ColorTheme";
const baseSize = 1073741824; //number of bytes in one GB
const unSizeMultiplicationFactor = 3;
@ -193,7 +194,8 @@ class PreparationPortal extends React.Component {
headerText={withoutHeader ? "" : t("Common:PreparationPortalTitle")}
style={style}
>
<StyledBodyPreparationPortal
<ColorTheme
themeId={ThemeType.Progress}
percent={percent}
errorMessage={errorMessage}
className="preparation-portal_body-wrapper"
@ -209,17 +211,14 @@ class PreparationPortal extends React.Component {
<div className="preparation-portal_progress-bar">
<div className="preparation-portal_progress-line"></div>
</div>
<Text
className="preparation-portal_percent"
color="#a3a9ae"
>{`${percent}%`}</Text>
<Text className="preparation-portal_percent">{`${percent} %`}</Text>
</div>
<Text className="preparation-portal_text">
{t("PreparationPortalDescription")}
</Text>
</>
)}
</StyledBodyPreparationPortal>
</ColorTheme>
</ErrorContainer>
</StyledPreparationPortal>
);

View File

@ -107,7 +107,7 @@ const InterfaceTheme = (props) => {
label={t("LightTheme")}
isDisabled={isSystemTheme}
theme="Light"
accentColor={currentColorScheme.accentColor}
accentColor={currentColorScheme.main.accent}
themeId={selectedThemeId}
value={ThemeKeys.BaseStr}
isChecked={currentTheme === ThemeKeys.BaseStr}
@ -117,7 +117,7 @@ const InterfaceTheme = (props) => {
label={t("DarkTheme")}
isDisabled={isSystemTheme}
theme="Dark"
accentColor={currentColorScheme.accentColor}
accentColor={currentColorScheme.main.accent}
themeId={selectedThemeId}
value={ThemeKeys.DarkStr}
isChecked={currentTheme === ThemeKeys.DarkStr}

View File

@ -1,8 +1,6 @@
import React from "react";
import styled, { css } from "styled-components";
import Text from "@docspace/components/text";
import Box from "@docspace/components/box";
import VersionSvg from "@docspace/client/public/images/versionrevision_active.react.svg";
import { StyledVersionSvg } from "@docspace/client/src/pages/VersionHistory/Section/Body/StyledVersionHistory";
import { ColorTheme, ThemeType } from "@docspace/common/components/ColorTheme";
const VersionBadge = ({
@ -14,13 +12,17 @@ const VersionBadge = ({
theme,
...rest
}) => (
<Box className={className} marginProp="0 8px" displayProp="flex" {...rest}>
<ColorTheme
themeId={ThemeType.VersionBadge}
isVersion={isVersion}
theme={theme}
index={index}
/>
<ColorTheme
themeId={ThemeType.VersionBadge}
className={className}
marginProp="0 8px"
displayProp="flex"
isVersion={isVersion}
theme={theme}
index={index}
{...rest}
>
<StyledVersionSvg isVersion={isVersion} theme={theme} index={index} />
<Text
className="version_badge-text"
@ -30,7 +32,7 @@ const VersionBadge = ({
>
{isVersion && t("Version", { version: versionGroup })}
</Text>
</Box>
</ColorTheme>
);
export default VersionBadge;

View File

@ -2630,6 +2630,14 @@ class FilesStore {
setCreatedItem = (createdItem) => {
this.createdItem = createdItem;
const { socketHelper } = this.authStore.settingsStore;
if (createdItem?.type == "file") {
socketHelper.emit({
command: "subscribe",
data: `FILE-${createdItem.id}`,
});
}
};
setScrollToItem = (item) => {

View File

@ -186,6 +186,13 @@ export function sendAppearanceTheme(data) {
});
}
export function deleteAppearanceTheme(id) {
return request({
method: "delete",
url: `/settings/colortheme?id=${id}`,
});
}
export function getLogoText() {
return request({
method: "get",

View File

@ -42,7 +42,7 @@ const StyledHideArticleMenuButton = styled.div`
.article-hide-menu-text {
margin-left: 8px;
color: ${({ currentColorScheme }) => currentColorScheme.accentColor};
color: ${({ currentColorScheme }) => currentColorScheme.main.accent};
}
@media ${tablet} {
@ -75,7 +75,7 @@ const StyledHideArticleMenuButton = styled.div`
svg {
path {
fill: ${({ currentColorScheme }) => currentColorScheme.accentColor};
fill: ${({ currentColorScheme }) => currentColorScheme.main.accent};
}
}
}

View File

@ -28,6 +28,8 @@ import {
LinkTheme,
SliderTheme,
IndicatorLoaderTheme,
ProgressTheme,
MobileProgressBarTheme,
} from "./styled";
import { ThemeType } from "./constants";
@ -269,6 +271,24 @@ const ColorTheme = forwardRef(
/>
);
}
case ThemeType.Progress: {
return (
<ProgressTheme
{...props}
$currentColorScheme={currentColorScheme}
ref={ref}
/>
);
}
case ThemeType.MobileProgressBar: {
return (
<MobileProgressBarTheme
{...props}
$currentColorScheme={currentColorScheme}
ref={ref}
/>
);
}
}
}
);

View File

@ -25,4 +25,6 @@ export const ThemeType = {
Link: "link",
Slider: "slider",
IndicatorLoader: "indicatorLoader",
Progress: "progress",
MobileProgressBar: "mobileProgressBar",
};

View File

@ -12,6 +12,7 @@ const getDefaultStyles = ({
backgroundColor,
color,
theme,
isPaidBadge,
}) =>
$currentColorScheme &&
!isVersionBadge &&
@ -19,33 +20,27 @@ const getDefaultStyles = ({
${StyledText} {
color: ${color
? color
: $currentColorScheme.id === 7 && !theme.isBase
? "#444444"
: theme.badge.color} !important;
: isPaidBadge
? theme.badge.color
: $currentColorScheme.text.accent} !important;
}
${StyledInner} {
background-color: ${backgroundColor
? backgroundColor
: $currentColorScheme.id === 7 && !theme.isBase
? "#ECEEF1"
: $currentColorScheme.accentColor};
: $currentColorScheme.main.accent};
&:hover {
background-color: ${backgroundColor
? backgroundColor
: $currentColorScheme.id === 7 && !theme.isBase
? "#ECEEF1"
: $currentColorScheme.accentColor};
: $currentColorScheme.main.accent};
}
}
&:hover {
border-color: ${backgroundColor
? backgroundColor
: $currentColorScheme.id === 7 && !theme.isBase
? "#ECEEF1"
: $currentColorScheme.accentColor};
: $currentColorScheme.main.accent};
}
`;

View File

@ -3,35 +3,27 @@ import StyledButton from "@docspace/components/button/styled-button";
import Base from "@docspace/components/themes/base";
const activeCss = css`
border-color: ${(props) =>
props.theme.isBase
? props.$currentColorScheme.buttonsMain
: props.primary
? props.$currentColorScheme.buttonsMain
: props.theme.button.border.baseActive};
border-color: ${(props) => props.$currentColorScheme.main.buttons};
background: ${(props) =>
props.primary && props.$currentColorScheme.buttonsMain};
props.primary && props.$currentColorScheme.main.buttons};
opacity: ${(props) => !props.isDisabled && "1"};
filter: ${(props) =>
props.primary &&
(props.theme.isBase ? "brightness(90%)" : "brightness(82%)")};
color: ${(props) => props.$currentColorScheme.text.buttons};
`;
const hoverCss = css`
border-color: ${(props) =>
props.theme.isBase
? props.$currentColorScheme.buttonsMain
: props.primary
? props.$currentColorScheme.buttonsMain
: props.theme.button.border.baseHover};
border-color: ${(props) => props.$currentColorScheme.main.buttons};
background: ${(props) =>
props.primary && props.$currentColorScheme.buttonsMain};
props.primary && props.$currentColorScheme.main.buttons};
opacity: ${(props) => props.primary && !props.isDisabled && "0.85"};
color: ${(props) => props.primary && props.$currentColorScheme.text.buttons};
`;
const getDefaultStyles = ({
@ -42,12 +34,25 @@ const getDefaultStyles = ({
isClicked,
isHovered,
disableHover,
title,
}) =>
$currentColorScheme &&
!title &&
css`
background: ${primary && $currentColorScheme.buttonsMain};
opacity: ${primary && isDisabled && "0.6"};
border-color: ${primary && $currentColorScheme.buttonsMain};
${primary &&
css`
background: ${$currentColorScheme.main.buttons};
opacity: ${isDisabled && "0.6"};
border: ${`1px solid`} ${$currentColorScheme.main.buttons};
color: ${$currentColorScheme.text.buttons};
.loader {
svg {
color: ${$currentColorScheme.text.buttons};
}
background-color: ${$currentColorScheme.main.buttons};
}
`}
${!isDisabled &&
!isLoading &&

View File

@ -5,9 +5,11 @@ const getDefaultStyles = ({ $currentColorScheme, color }) =>
$currentColorScheme &&
css`
.calendar-month_selected-day {
background-color: ${color ? color : $currentColorScheme.accentColor};
background-color: ${color ? color : $currentColorScheme.main.accent};
color: ${$currentColorScheme.text.accent};
&:hover {
background-color: ${color ? color : $currentColorScheme.accentColor};
background-color: ${color ? color : $currentColorScheme.main.accent};
color: ${$currentColorScheme.text.accent};
}
}
`;

View File

@ -12,10 +12,10 @@ const getDefaultStyles = ({ $currentColorScheme, isActive, theme }) =>
$currentColorScheme &&
css`
${StyledCatalogItemText} {
color: ${isActive && theme.isBase && $currentColorScheme.accentColor};
color: ${isActive && theme.isBase && $currentColorScheme.main.accent};
&:hover {
color: ${isActive && theme.isBase && $currentColorScheme.accentColor};
color: ${isActive && theme.isBase && $currentColorScheme.main.accent};
}
}
@ -24,12 +24,12 @@ const getDefaultStyles = ({ $currentColorScheme, isActive, theme }) =>
path {
fill: ${isActive &&
theme.isBase &&
$currentColorScheme.accentColor} !important;
$currentColorScheme.main.accent} !important;
}
circle {
fill: ${isActive &&
theme.isBase &&
$currentColorScheme.accentColor} !important;
$currentColorScheme.main.accent} !important;
}
}
@ -38,7 +38,7 @@ const getDefaultStyles = ({ $currentColorScheme, isActive, theme }) =>
path {
fill: ${isActive &&
theme.isBase &&
$currentColorScheme.accentColor} !important;
$currentColorScheme.main.accent} !important;
}
}
}

View File

@ -2,22 +2,14 @@ import styled, { css } from "styled-components";
import { StyledComboButton } from "@docspace/components/combobox/sub-components/styled-combobutton";
import Base from "@docspace/components/themes/base";
const getDefaultStyles = ({ $currentColorScheme, isOpen, theme }) =>
const getDefaultStyles = ({ $currentColorScheme, isOpen }) =>
$currentColorScheme &&
css`
border-color: ${isOpen &&
(theme.isBase
? $currentColorScheme.accentColor
: theme.comboBox.button.openBorderColor)};
border-color: ${isOpen && $currentColorScheme.main.accent};
:focus {
border-color: ${isOpen &&
(theme.isBase
? $currentColorScheme.accentColor
: theme.comboBox.button.hoverBorderColor)};
border-color: ${isOpen && $currentColorScheme.main.accent};
}
`;
StyledComboButton.defaultProps = { theme: Base };
export default styled(StyledComboButton)(getDefaultStyles);

View File

@ -4,20 +4,18 @@ import Base from "@docspace/components/themes/base";
const getDefaultStyles = ({ $currentColorScheme, isSelected, theme }) =>
$currentColorScheme &&
isSelected &&
css`
background: ${isSelected &&
theme.isBase &&
$currentColorScheme.accentColor};
border-color: ${isSelected &&
theme.isBase &&
$currentColorScheme.accentColor};
background: ${$currentColorScheme.main.accent};
border-color: ${$currentColorScheme.main.accent};
.filter-text {
color: ${$currentColorScheme.textColor};
}
&:hover {
background: ${isSelected &&
theme.isBase &&
$currentColorScheme.accentColor};
border-color: ${isSelected &&
theme.isBase &&
$currentColorScheme.accentColor};
background: ${$currentColorScheme.main.accent};
border-color: ${$currentColorScheme.main.accent};
}
`;

View File

@ -2,28 +2,34 @@ import styled, { css } from "styled-components";
import {
StyledCircleWrap,
StyledFloatingButton,
IconBox,
StyledCircle,
} from "@docspace/common/components/FloatingButton/StyledFloatingButton";
import Base from "@docspace/components/themes/base";
const getDefaultStyles = ({ $currentColorScheme, color, icon, theme }) =>
const getDefaultStyles = ({ $currentColorScheme, color, displayProgress }) =>
$currentColorScheme &&
css`
background: ${color
? color
: theme.isBase
? $currentColorScheme.accentColor
: icon === "upload"
? theme.floatingButton.backgroundColor
: $currentColorScheme.accentColor} !important;
background: ${color || $currentColorScheme.main.accent} !important;
${StyledFloatingButton} {
background: ${color
? color
: theme.isBase
? $currentColorScheme.accentColor
: icon === "upload"
? theme.floatingButton.backgroundColor
: $currentColorScheme.accentColor} !important;
background: ${color || $currentColorScheme.main.accent} !important;
}
${IconBox} {
svg {
path {
fill: ${$currentColorScheme.text.accent};
}
}
}
${StyledCircle} {
.circle__mask .circle__fill {
background-color: ${!displayProgress
? "transparent !important"
: $currentColorScheme.text.accent};
}
}
`;

View File

@ -17,15 +17,14 @@ const getDefaultStyles = ({
svg {
path {
fill: ${(shared || locked || isFavorite || isEditing) &&
theme.isBase &&
$currentColorScheme.accentColor};
$currentColorScheme.main.accent};
}
}
&:hover {
svg {
path {
fill: ${theme.isBase && $currentColorScheme.accentColor};
fill: ${$currentColorScheme.main.accent};
}
}
}

View File

@ -10,14 +10,14 @@ const getDefaultStyles = ({ $currentColorScheme, theme }) =>
${commonIconsStyles}
svg {
path {
fill: ${theme.isBase && $currentColorScheme.accentColor};
fill: ${theme.isBase && $currentColorScheme.main.accent};
}
}
&:hover {
svg {
path {
fill: ${theme.isBase && $currentColorScheme.accentColor};
fill: ${theme.isBase && $currentColorScheme.main.accent};
}
}
}

View File

@ -6,7 +6,7 @@ const getDefaultStyles = ({ $currentColorScheme }) =>
css`
svg {
path:nth-child(2) {
fill: ${$currentColorScheme.accentColor};
fill: ${$currentColorScheme.main.accent};
}
`;

View File

@ -49,3 +49,7 @@ export { default as LinkTheme } from "./link";
export { default as SliderTheme } from "./slider";
export { default as IndicatorLoaderTheme } from "./indicatorLoader";
export { default as ProgressTheme } from "./progress";
export { default as MobileProgressBarTheme } from "./mobileProgressBar";

View File

@ -4,10 +4,10 @@ import StyledIndicator from "@docspace/common/components/FilterInput/sub-compone
const getDefaultStyles = ({ $currentColorScheme }) =>
$currentColorScheme &&
css`
background: ${$currentColorScheme.accentColor};
background: ${$currentColorScheme.main.accent};
&:hover {
background: ${$currentColorScheme.accentColor};
background: ${$currentColorScheme.main.accent};
}
`;

View File

@ -1,16 +1,21 @@
import styled, { css } from "styled-components";
import StyledWrapper from "@docspace/client/src/components/IndicatorLoader/StyledWrapper";
import Base from "@docspace/components/themes/base";
const getDefaultStyles = ({ $currentColorScheme }) =>
const getDefaultStyles = ({ $currentColorScheme, theme }) =>
$currentColorScheme &&
css`
#ipl-progress-indicator {
background-color: ${$currentColorScheme.accentColor};
background-color: ${theme.isBase
? $currentColorScheme.main.accent
: "#FFFFFF"};
&:hover {
background-color: ${$currentColorScheme.accentColor};
background-color: ${theme.isBase
? $currentColorScheme.main.accent
: "#FFFFFF"};
}
}
`;
StyledWrapper.defaultProps = { theme: Base };
export default styled(StyledWrapper)(getDefaultStyles);

View File

@ -2,14 +2,17 @@ import styled, { css } from "styled-components";
import { StyledInfoPanelToggleWrapper } from "@docspace/client/src/pages/Home/InfoPanel/Header/styles/common";
import Base from "@docspace/components/themes/base";
const getDefaultStyles = ({ $currentColorScheme, theme }) =>
const getDefaultStyles = ({ $currentColorScheme }) =>
$currentColorScheme &&
css`
.info-panel-toggle-bg {
path {
fill: ${theme.isBase
? $currentColorScheme.accentColor
: theme.infoPanel.sectionHeaderToggleIconActive};
fill: ${$currentColorScheme.main.accent};
}
&:hover {
path {
fill: ${$currentColorScheme.main.accent};
}
}
}
`;

View File

@ -8,9 +8,7 @@ const getDefaultStyles = ({ $currentColorScheme, hasError, theme }) =>
css`
:focus-within {
border-color: ${(hasError && theme.input.focusErrorBorderColor) ||
(theme.isBase
? $currentColorScheme.accentColor
: theme.inputBlock.borderColor)};
$currentColorScheme.main.accent};
}
`;

View File

@ -4,10 +4,10 @@ import StyledText from "@docspace/components/link/styled-link";
const getDefaultStyles = ({ $currentColorScheme, noHover }) =>
$currentColorScheme &&
css`
color: ${$currentColorScheme.accentColor};
color: ${$currentColorScheme.main.accent};
&:hover {
color: ${!noHover && $currentColorScheme.accentColor};
color: ${!noHover && $currentColorScheme.main.accent};
text-decoration: underline;
}
`;

View File

@ -5,7 +5,7 @@ const getDefaultStyles = ({ $currentColorScheme }) =>
$currentColorScheme &&
css`
.login-link {
color: ${$currentColorScheme.accentColor};
color: ${$currentColorScheme.main.accent};
}
`;

View File

@ -11,16 +11,12 @@ const getDefaultStyles = ({ $currentColorScheme, theme }) =>
css`
${StyledCircle} {
.circle__mask .circle__fill {
background-color: ${theme.isBase
? $currentColorScheme.accentColor
: theme.filesPanels.upload.loadingButton.color};
background-color: ${$currentColorScheme.main.accent};
}
}
${StyledLoadingButton} {
color: ${theme.isBase
? $currentColorScheme.accentColor
: theme.filesPanels.upload.loadingButton.color};
color: ${$currentColorScheme.main.accent};
}
`;

View File

@ -20,21 +20,29 @@ const disableStyles = css`
const getDefaultStyles = ({ $currentColorScheme, isDisabled, theme }) =>
$currentColorScheme &&
css`
background-color: ${$currentColorScheme.accentColor};
background-color: ${$currentColorScheme.main.accent};
&:hover {
background-color: ${$currentColorScheme.accentColor};
background-color: ${$currentColorScheme.main.accent};
opacity: 0.85;
cursor: pointer;
}
&:active {
background-color: ${$currentColorScheme.accentColor};
background-color: ${$currentColorScheme.main.accent};
opacity: 1;
filter: ${theme.isBase ? "brightness(90%)" : "brightness(82%)"};
cursor: pointer;
}
.main-button_text {
color: ${$currentColorScheme.text.accent};
}
.main-button_img svg path {
fill: ${$currentColorScheme.text.accent};
}
${isDisabled &&
`
${disableStyles}

View File

@ -0,0 +1,14 @@
import styled, { css } from "styled-components";
import { StyledBar } from "@docspace/components/main-button-mobile/styled-main-button";
const getDefaultStyles = ({ $currentColorScheme, theme, error }) =>
$currentColorScheme &&
css`
background: ${error
? theme.mainButtonMobile.bar.errorBackground
: theme.isBase
? $currentColorScheme.main.accent
: "#FFFFFF"};
`;
export default styled(StyledBar)(getDefaultStyles);

View File

@ -0,0 +1,15 @@
import styled, { css } from "styled-components";
import { StyledBodyPreparationPortal } from "@docspace/client/src/pages/PreparationPortal/StyledPreparationPortal";
import Base from "@docspace/components/themes/base";
const getDefaultStyles = ({ $currentColorScheme, theme }) =>
$currentColorScheme &&
css`
.preparation-portal_progress-line {
background: ${theme.isBase ? $currentColorScheme.main.accent : "#FFFFFF"};
}
`;
StyledBodyPreparationPortal.defaultProps = { theme: Base };
export default styled(StyledBodyPreparationPortal)(getDefaultStyles);

View File

@ -11,11 +11,11 @@ const getDefaultStyles = ({
css`
background-image: ${withPouring &&
((theme.isBase &&
`linear-gradient( ${$currentColorScheme.accentColor}, ${$currentColorScheme.accentColor})`) ||
`linear-gradient( ${$currentColorScheme.main.accent}, ${$currentColorScheme.main.accent})`) ||
(!theme.isBase && `linear-gradient(#FFFFFF, #FFFFFF)`))};
&::-webkit-slider-thumb {
background: ${(theme.isBase && $currentColorScheme.accentColor) ||
background: ${(theme.isBase && $currentColorScheme.main.accent) ||
(!theme.isBase && "#FFFFFF")};
box-shadow: ${!theme.isBase &&
"0px 3px 12px rgba(0, 0, 0, 0.25); !important"};
@ -24,7 +24,7 @@ const getDefaultStyles = ({
&:hover {
background-image: ${withPouring &&
((theme.isBase &&
`linear-gradient( ${$currentColorScheme.accentColor}, ${$currentColorScheme.accentColor})`) ||
`linear-gradient( ${$currentColorScheme.main.accent}, ${$currentColorScheme.main.accent})`) ||
(!theme.isBase && `linear-gradient(#FFFFFF, #FFFFFF)`))};
}

View File

@ -5,10 +5,10 @@ import { StyledSubmenuItemLabel } from "@docspace/components/submenu/styled-subm
const getDefaultStyles = ({ $currentColorScheme, isActive }) =>
$currentColorScheme &&
css`
background-color: ${isActive ? $currentColorScheme.accentColor : "none"};
background-color: ${isActive ? $currentColorScheme.main.accent : "none"};
&:hover {
background-color: ${isActive && $currentColorScheme.accentColor};
background-color: ${isActive && $currentColorScheme.main.accent};
}
`;

View File

@ -7,12 +7,12 @@ const getDefaultStyles = ({ $currentColorScheme, isActive, theme }) =>
css`
color: ${isActive &&
theme.isBase &&
$currentColorScheme.accentColor} !important;
$currentColorScheme.main.accent} !important;
&:hover {
color: ${isActive &&
theme.isBase &&
$currentColorScheme.accentColor} !important;
$currentColorScheme.main.accent} !important;
}
`;

View File

@ -5,9 +5,11 @@ import Base from "@docspace/components/themes/base";
const getDefaultStyles = ({ $currentColorScheme, selected, theme }) =>
$currentColorScheme &&
css`
background-color: ${selected &&
theme.isBase &&
$currentColorScheme.accentColor} !important;
background-color: ${selected && $currentColorScheme.main.accent} !important;
.title_style {
color: ${selected && $currentColorScheme.text.accent};
}
`;
Label.defaultProps = { theme: Base };

View File

@ -15,9 +15,7 @@ const getDefaultStyles = ({
border-color: ${(hasError && theme.input.focusErrorBorderColor) ||
(hasWarning && theme.input.focusWarningBorderColor) ||
(isDisabled && theme.input.focusDisabledBorderColor) ||
(theme.isBase
? $currentColorScheme.accentColor
: theme.input.focusBorderColor)};
$currentColorScheme.main.accent};
}
`;

View File

@ -8,9 +8,7 @@ const getDefaultStyles = ({ $currentColorScheme, hasError, theme }) =>
:focus-within {
border-color: ${hasError
? theme.textArea.focusErrorBorderColor
: theme.isBase
? $currentColorScheme.accentColor
: theme.textArea.focusBorderColor};
: $currentColorScheme.main.accent};
}
`;

View File

@ -4,19 +4,23 @@ import {
ToggleButtonContainer,
} from "@docspace/components/toggle-button/styled-toggle-button";
const getDefaultStyles = ({ $currentColorScheme, isDisabled, isChecked }) =>
const getDefaultStyles = ({
$currentColorScheme,
isDisabled,
isChecked,
theme,
}) =>
$currentColorScheme &&
css`
${ToggleButtonContainer} {
svg {
rect {
fill: ${isChecked && $currentColorScheme.accentColor};
opacity: ${isDisabled && "0.6"};
fill: ${isChecked && $currentColorScheme.main.accent};
}
&:hover {
fill: ${isChecked && $currentColorScheme.accentColor};
opacity: ${isDisabled && "0.6"};
}
circle {
fill: ${(isChecked && isDisabled && theme.isBase && "#FFFFFF") ||
(isChecked && $currentColorScheme.text.accent)};
}
}
}

View File

@ -1,21 +1,28 @@
import styled, { css } from "styled-components";
import { StyledVersionSvg } from "@docspace/client/src/pages/VersionHistory/Section/Body/StyledVersionHistory";
import Box from "@docspace/components/box";
const getDefaultStyles = ({ $currentColorScheme, $isVersion, theme, index }) =>
$currentColorScheme &&
css`
path {
fill: ${!$isVersion
? theme.filesVersionHistory.badge.defaultFill
: index === 0
? theme.filesVersionHistory.badge.fill
: $currentColorScheme.accentColor};
${StyledVersionSvg} {
path {
fill: ${!$isVersion
? theme.filesVersionHistory.badge.defaultFill
: index === 0
? theme.filesVersionHistory.badge.fill
: $currentColorScheme.main.accent};
stroke: ${!$isVersion
? theme.filesVersionHistory.badge.stroke
: index === 0
? theme.filesVersionHistory.badge.fill
: $currentColorScheme.accentColor};
stroke: ${!$isVersion
? theme.filesVersionHistory.badge.stroke
: index === 0
? theme.filesVersionHistory.badge.fill
: $currentColorScheme.main.accent};
}
}
.version_badge-text {
color: ${$isVersion && index !== 0 && $currentColorScheme.text.accent};
}
`;
export default styled(StyledVersionSvg)(getDefaultStyles);
export default styled(Box)(getDefaultStyles);

View File

@ -104,6 +104,7 @@ const FilterBlockItem = ({
themeId={ThemeType.FilterBlockItemTag}
>
<StyledFilterBlockItemTagText
className="filter-text"
noSelect={true}
isSelected={item.isSelected}
>
@ -189,6 +190,7 @@ const FilterBlockItem = ({
themeId={ThemeType.FilterBlockItemTag}
>
<StyledFilterBlockItemTagText
className="filter-text"
noSelect={true}
isSelected={item.isSelected}
truncate

View File

@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react";
import React, { useEffect, useState, useMemo } from "react";
import PropTypes from "prop-types";
import styled from "styled-components";
@ -49,6 +49,10 @@ const FloatingButton = (props) => {
clearUploadedFilesHistory && clearUploadedFilesHistory();
};
const displayProgress = useMemo(() => {
return !(percent === 100 && animationCompleted) && icon != "minus";
}, [percent, animationCompleted, icon]);
let timerId = null;
useEffect(() => {
@ -73,13 +77,9 @@ const FloatingButton = (props) => {
style={style}
icon={icon}
onClick={onClick}
displayProgress={displayProgress}
>
<StyledCircle
displayProgress={
!(percent === 100 && animationCompleted) && icon != "minus"
}
percent={percent}
>
<StyledCircle displayProgress={displayProgress} percent={percent}>
<div className="circle__mask circle__full">
<div className="circle__fill"></div>
</div>

View File

@ -692,6 +692,10 @@ class SettingsStore {
sendAppearanceTheme = async (data) => {
return api.settings.sendAppearanceTheme(data);
};
deleteAppearanceTheme = async (id) => {
return api.settings.deleteAppearanceTheme(id);
};
}
export default SettingsStore;

View File

@ -265,7 +265,7 @@ const StyledCatalogItemImg = styled.div`
fill: ${(props) =>
props.isActive
? props.theme.catalogItem.img.svg.isActiveFill
: props.theme.catalogItem.img.svg.fill} !important;
: props.theme.catalogItem.img.svg.fill};
}
}

View File

@ -78,7 +78,11 @@ const ProgressBarMobile = ({
</div>
<StyledMobileProgressBar>
<StyledBar uploadPercent={uploadPercent} error={error} />
<ColorTheme
themeId={ThemeType.MobileProgressBar}
uploadPercent={uploadPercent}
error={error}
/>
</StyledMobileProgressBar>
</StyledProgressBarContainer>
);

View File

@ -275,10 +275,6 @@ const StyledBar = styled.div`
width: ${(props) => props.uploadPercent}%;
height: 4px;
opacity: 1;
background: ${(props) =>
props.error
? props.theme.mainButtonMobile.bar.errorBackground
: props.theme.mainButtonMobile.bar.background};
`;
const StyledAlertIcon = styled.div`

View File

@ -50,9 +50,9 @@ const MainButton = (props) => {
<Text className="main-button_text">{text}</Text>
{isDropdown && (
<>
<img
<ReactSVG
className="main-button_img"
src="/static/images/triangle-main-button.svg"
src={"/static/images/triangle-main-button.svg"}
/>
<ContextMenu

View File

@ -85,8 +85,9 @@ const StyledMainButton = styled.div`
}
.main-button_img {
padding-top: 9px;
height: 5px;
svg {
padding-bottom: 1px;
}
}
`;
StyledMainButton.defaultProps = { theme: Base };

View File

@ -193,7 +193,6 @@ const Base = {
mobileProgressBarBackground: "rgb(48%, 58%, 69%, 0.4)",
bar: {
background: "linear-gradient(225deg, #2274aa 0%, #0f4071 100%)",
errorBackground: orangePressed,
icon: "#A3A9AE",
@ -1662,23 +1661,10 @@ const Base = {
},
toggleButton: {
fillColor: blueMain,
fillColorOff: gray,
disableFillColor: grayLightMid,
disableFillColorOff: grayLightMid,
borderColor: "unset",
borderColorOff: "unset",
disableBorderColor: grayLightMid,
disableBorderColorOff: grayLightMid,
fillColorOff: "#D0D5DA",
hoverFillColorOff: "#A3A9AE",
fillCircleColor: white,
fillCircleColorOff: white,
disableFillCircleColor: white,
disableFillCircleColorOff: white,
},
contextMenuButton: {
@ -3020,6 +3006,13 @@ const Base = {
boxShadow: "0px 5px 20px rgba(4, 15, 27, 0.07)",
},
preparationPortalProgress: {
backgroundColor: "#F3F4F4",
colorPercentSmall: "#333333",
colorPercentBig: "#FFFFFF",
},
codeInput: {
background: white,
border: "1px solid #d0d5da",

View File

@ -188,7 +188,6 @@ const Dark = {
mobileProgressBarBackground: "#606060",
bar: {
background: "#858585",
errorBackground: orangePressed,
icon: "#858585",
@ -1654,23 +1653,11 @@ const Dark = {
},
toggleButton: {
fillColor: "#F0F0F0",
fillColorOff: "#292929",
hoverFillColorOff: "#3D3D3D",
disableFillColor: black,
disableFillColorOff: "#545454",
borderColor: "#474747",
borderColorOff: "#474747",
disableBorderColor: "#474747",
disableBorderColorOff: "#646464",
fillCircleColor: "#292929",
fillCircleColorOff: grayMaxLight,
disableFillCircleColor: "#545454",
disableFillCircleColorOff: black,
fillCircleColor: "#FFFFFF",
fillCircleColorOff: "#FFFFFF",
},
contextMenuButton: {
@ -3020,6 +3007,12 @@ const Dark = {
boxShadow: "0px 5px 20px rgba(0, 0, 0, 0.16);",
},
preparationPortalProgress: {
backgroundColor: "#282828",
colorPercentSmall: "#FFFFFF",
colorPercentBig: "#333333",
},
codeInput: {
background: "#282828",
border: "1px solid #474747",

View File

@ -75,6 +75,8 @@ class ToggleButton extends Component {
id={id}
className={className}
style={style}
isChecked={this.state.checked}
isDisabled={isDisabled}
>
<ToggleButtonContainer
id={id}

View File

@ -31,38 +31,41 @@ const ToggleButtonContainer = styled.label`
svg {
${(props) =>
props.isDisabled
props.isChecked
? css`
rect {
fill: ${props.isChecked
? props.theme.toggleButton.disableFillColor
: props.theme.toggleButton.disableFillColorOff};
stroke-width: 1px;
stroke-linecap: round;
stroke: ${props.isChecked
? props.theme.toggleButton.borderColor
: props.theme.toggleButton.borderColorOff};
fill: ${props.isDisabled &&
props.theme.isBase &&
props.theme.toggleButton.fillColorOff} !important;
&:hover {
opacity: ${!props.isDisabled && "0.85"};
}
}
circle {
fill: ${props.isChecked
? props.theme.toggleButton.disableFillCircleColor
: props.theme.toggleButton.disableFillCircleColorOff};
fill: ${props.theme.toggleButton.fillCircleColor};
opacity: ${props.isDisabled && "0.6"};
}
opacity: ${props.isDisabled && "0.6"};
`
: css`
rect {
fill: ${props.isChecked
? props.theme.toggleButton.fillColor
: props.theme.toggleButton.fillColorOff};
stroke-width: 1px;
stroke: ${props.isChecked
? props.theme.toggleButton.borderColor
: props.theme.toggleButton.borderColor};
fill: ${props.theme.toggleButton.fillColorOff};
}
circle {
fill: ${props.isChecked
? props.theme.toggleButton.fillCircleColor
: props.theme.toggleButton.fillCircleColorOff};
fill: ${props.theme.toggleButton.fillCircleColorOff};
opacity: ${props.isDisabled && "0.6"};
}
opacity: ${props.isDisabled && "0.6"};
&:hover {
rect {
fill: ${!props.isDisabled &&
props.theme.toggleButton.hoverFillColorOff};
}
}
`}
}

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