Merge branch 'develop' into feature/web-plugins
This commit is contained in:
commit
0d8bd872d6
@ -7,7 +7,7 @@ BUILD_PATH=${BUILD_PATH:-${SRC_PATH}/publish}
|
|||||||
BUILD_DOTNET_CORE_ARGS=${BUILD_DOTNET_CORE_ARGS:-"false"}
|
BUILD_DOTNET_CORE_ARGS=${BUILD_DOTNET_CORE_ARGS:-"false"}
|
||||||
PROPERTY_BUILD=${PROPERTY_BUILD:-"all"}
|
PROPERTY_BUILD=${PROPERTY_BUILD:-"all"}
|
||||||
|
|
||||||
BACKEND_NODEJS_SERVICES=${BACKEND_NODEJS_SERVICES:-"ASC.Socket.IO, ASC.SsoAuth"}
|
BACKEND_NODEJS_SERVICES=${BACKEND_NODEJS_SERVICES:-"ASC.Socket.IO, ASC.SsoAuth, ASC.TelegramReports"}
|
||||||
BACKEND_DOTNETCORE_SERVICES=${BACKEND_DOTNETCORE_SERVICES:-"ASC.Files, ASC.People, ASC.Data.Backup, ASC.Files.Service, ASC.Notify, \
|
BACKEND_DOTNETCORE_SERVICES=${BACKEND_DOTNETCORE_SERVICES:-"ASC.Files, ASC.People, ASC.Data.Backup, ASC.Files.Service, ASC.Notify, \
|
||||||
ASC.Studio.Notify, ASC.Web.Api, ASC.Web.Studio, ASC.Data.Backup.BackgroundTasks, ASC.ClearEvents, ASC.ApiSystem, ASC.Web.HealthChecks.UI"}
|
ASC.Studio.Notify, ASC.Web.Api, ASC.Web.Studio, ASC.Data.Backup.BackgroundTasks, ASC.ClearEvents, ASC.ApiSystem, ASC.Web.HealthChecks.UI"}
|
||||||
SELF_CONTAINED=${SELF_CONTAINED:-"false"}
|
SELF_CONTAINED=${SELF_CONTAINED:-"false"}
|
||||||
@ -179,6 +179,12 @@ function backend-nodejs-publish {
|
|||||||
yarn install --cwd ${SRC_PATH}/common/${ARRAY_NAME_SERVICES[$i]} --frozen-lockfile && \
|
yarn install --cwd ${SRC_PATH}/common/${ARRAY_NAME_SERVICES[$i]} --frozen-lockfile && \
|
||||||
mkdir -p ${BUILD_PATH}/services/${ARRAY_NAME_SERVICES[$i]}/service/ && \
|
mkdir -p ${BUILD_PATH}/services/${ARRAY_NAME_SERVICES[$i]}/service/ && \
|
||||||
cp -rfv ${SRC_PATH}/common/${ARRAY_NAME_SERVICES[$i]}/* ${BUILD_PATH}/services/${ARRAY_NAME_SERVICES[$i]}/service/
|
cp -rfv ${SRC_PATH}/common/${ARRAY_NAME_SERVICES[$i]}/* ${BUILD_PATH}/services/${ARRAY_NAME_SERVICES[$i]}/service/
|
||||||
|
|
||||||
|
if [[ ${ARRAY_NAME_SERVICES[$i]} == "ASC.TelegramReports" ]]
|
||||||
|
then
|
||||||
|
# build before run
|
||||||
|
yarn --cwd ${BUILD_PATH}/services/ASC.TelegramReports/service/ build
|
||||||
|
fi
|
||||||
if [[ ${DOCKER_ENTRYPOINT} != "false" ]]
|
if [[ ${DOCKER_ENTRYPOINT} != "false" ]]
|
||||||
then
|
then
|
||||||
echo "== ADD ${DOCKER_ENTRYPOINT} to ${ARRAY_NAME_SERVICES[$i]} =="
|
echo "== ADD ${DOCKER_ENTRYPOINT} to ${ARRAY_NAME_SERVICES[$i]} =="
|
||||||
|
@ -101,6 +101,7 @@ done
|
|||||||
services_name_backend_nodejs=()
|
services_name_backend_nodejs=()
|
||||||
services_name_backend_nodejs+=(ASC.Socket.IO)
|
services_name_backend_nodejs+=(ASC.Socket.IO)
|
||||||
services_name_backend_nodejs+=(ASC.SsoAuth)
|
services_name_backend_nodejs+=(ASC.SsoAuth)
|
||||||
|
services_name_backend_nodejs+=(ASC.TelegramReports)
|
||||||
|
|
||||||
# Publish backend services (Nodejs)
|
# Publish backend services (Nodejs)
|
||||||
for i in ${!services_name_backend_nodejs[@]}; do
|
for i in ${!services_name_backend_nodejs[@]}; do
|
||||||
|
@ -100,6 +100,7 @@
|
|||||||
API_HOST=${CONTAINER_PREFIX}api
|
API_HOST=${CONTAINER_PREFIX}api
|
||||||
STUDIO_HOST=${CONTAINER_PREFIX}studio
|
STUDIO_HOST=${CONTAINER_PREFIX}studio
|
||||||
SSOAUTH_HOST=${CONTAINER_PREFIX}ssoauth
|
SSOAUTH_HOST=${CONTAINER_PREFIX}ssoauth
|
||||||
|
TELEGRAMREPORTS_HOST=${CONTAINER_PREFIX}telegramreports
|
||||||
MIGRATION_RUNNER_HOST=${CONTAINER_PREFIX}migration-runner
|
MIGRATION_RUNNER_HOST=${CONTAINER_PREFIX}migration-runner
|
||||||
PROXY_HOST=${CONTAINER_PREFIX}proxy
|
PROXY_HOST=${CONTAINER_PREFIX}proxy
|
||||||
ROUTER_HOST=${CONTAINER_PREFIX}router
|
ROUTER_HOST=${CONTAINER_PREFIX}router
|
||||||
@ -122,6 +123,7 @@
|
|||||||
SERVICE_API=${API_HOST}:${SERVICE_PORT}
|
SERVICE_API=${API_HOST}:${SERVICE_PORT}
|
||||||
SERVICE_STUDIO=${STUDIO_HOST}:${SERVICE_PORT}
|
SERVICE_STUDIO=${STUDIO_HOST}:${SERVICE_PORT}
|
||||||
SERVICE_SSOAUTH=${SSOAUTH_HOST}:${SERVICE_PORT}
|
SERVICE_SSOAUTH=${SSOAUTH_HOST}:${SERVICE_PORT}
|
||||||
|
SERVICE_TELEGRAMREPORTS=${TELEGRAMREPORTS_HOST}:${SERVICE_PORT}
|
||||||
SERVICE_DOCEDITOR=${DOCEDITOR_HOST}:5013
|
SERVICE_DOCEDITOR=${DOCEDITOR_HOST}:5013
|
||||||
SERVICE_LOGIN=${LOGIN_HOST}:5011
|
SERVICE_LOGIN=${LOGIN_HOST}:5011
|
||||||
SERVICE_HELTHCHECKS=${HELTHCHECKS_HOST}:${SERVICE_PORT}
|
SERVICE_HELTHCHECKS=${HELTHCHECKS_HOST}:${SERVICE_PORT}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
version: "3.8"
|
version: "3.8"
|
||||||
services:
|
services:
|
||||||
onlyoffice-dns:
|
dnsmasq:
|
||||||
image: jpillora/dnsmasq
|
image: jpillora/dnsmasq
|
||||||
container_name: onlyoffice-dns
|
container_name: dnsmasq
|
||||||
restart: always
|
restart: always
|
||||||
expose:
|
expose:
|
||||||
- "5380"
|
- "5380"
|
||||||
|
@ -267,6 +267,7 @@ services:
|
|||||||
- SERVICE_API_SYSTEM=${SERVICE_API_SYSTEM}
|
- SERVICE_API_SYSTEM=${SERVICE_API_SYSTEM}
|
||||||
- SERVICE_STUDIO=${SERVICE_STUDIO}
|
- SERVICE_STUDIO=${SERVICE_STUDIO}
|
||||||
- SERVICE_SSOAUTH=${SERVICE_SSOAUTH}
|
- SERVICE_SSOAUTH=${SERVICE_SSOAUTH}
|
||||||
|
- SERVICE_TELEGRAMREPORTS=${SERVICE_TELEGRAMREPORTS}
|
||||||
- SERVICE_DOCEDITOR=${SERVICE_DOCEDITOR}
|
- SERVICE_DOCEDITOR=${SERVICE_DOCEDITOR}
|
||||||
- SERVICE_LOGIN=${SERVICE_LOGIN}
|
- SERVICE_LOGIN=${SERVICE_LOGIN}
|
||||||
- SERVICE_HELTHCHECKS=${SERVICE_HELTHCHECKS}
|
- SERVICE_HELTHCHECKS=${SERVICE_HELTHCHECKS}
|
||||||
|
@ -53,10 +53,13 @@ public class DistributedTaskProgress : DistributedTask
|
|||||||
[ProtoMember(3)]
|
[ProtoMember(3)]
|
||||||
protected int StepCount { get; set; }
|
protected int StepCount { get; set; }
|
||||||
|
|
||||||
|
protected CancellationToken CancellationToken { get; set; }
|
||||||
|
|
||||||
public virtual async Task RunJob(DistributedTask _, CancellationToken cancellationToken)
|
public virtual async Task RunJob(DistributedTask _, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
Percentage = 0;
|
Percentage = 0;
|
||||||
Status = DistributedTaskStatus.Running;
|
Status = DistributedTaskStatus.Running;
|
||||||
|
CancellationToken = cancellationToken;
|
||||||
|
|
||||||
await DoJob();
|
await DoJob();
|
||||||
}
|
}
|
||||||
|
@ -47,8 +47,6 @@ public class ReassignProgressItem : DistributedTaskProgress
|
|||||||
private bool _notify;
|
private bool _notify;
|
||||||
private bool _deleteProfile;
|
private bool _deleteProfile;
|
||||||
|
|
||||||
private CancellationToken _cancellationToken;
|
|
||||||
|
|
||||||
public ReassignProgressItem(IServiceScopeFactory serviceScopeFactory)
|
public ReassignProgressItem(IServiceScopeFactory serviceScopeFactory)
|
||||||
{
|
{
|
||||||
_serviceScopeFactory = serviceScopeFactory;
|
_serviceScopeFactory = serviceScopeFactory;
|
||||||
@ -70,13 +68,6 @@ public class ReassignProgressItem : DistributedTaskProgress
|
|||||||
IsCompleted = false;
|
IsCompleted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task RunJob(DistributedTask distributedTask, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
_cancellationToken = cancellationToken;
|
|
||||||
|
|
||||||
await base.RunJob(distributedTask, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task DoJob()
|
protected override async Task DoJob()
|
||||||
{
|
{
|
||||||
await using var scope = _serviceScopeFactory.CreateAsyncScope();
|
await using var scope = _serviceScopeFactory.CreateAsyncScope();
|
||||||
@ -167,7 +158,7 @@ public class ReassignProgressItem : DistributedTaskProgress
|
|||||||
PublishChanges();
|
PublishChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
_cancellationToken.ThrowIfCancellationRequested();
|
CancellationToken.ThrowIfCancellationRequested();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SendSuccessNotifyAsync(UserManager userManager, StudioNotifyService studioNotifyService, MessageService messageService, MessageTarget messageTarget, DisplayUserSettingsHelper displayUserSettingsHelper)
|
private async Task SendSuccessNotifyAsync(UserManager userManager, StudioNotifyService studioNotifyService, MessageService messageService, MessageTarget messageTarget, DisplayUserSettingsHelper displayUserSettingsHelper)
|
||||||
|
31
common/ASC.TelegramReports/.eslintrc.js
Executable file
31
common/ASC.TelegramReports/.eslintrc.js
Executable file
@ -0,0 +1,31 @@
|
|||||||
|
module.exports = {
|
||||||
|
parser: "@typescript-eslint/parser",
|
||||||
|
parserOptions: {
|
||||||
|
project: "tsconfig.json",
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
sourceType: "module",
|
||||||
|
},
|
||||||
|
plugins: ["@typescript-eslint/eslint-plugin"],
|
||||||
|
extends: [
|
||||||
|
"plugin:@typescript-eslint/recommended",
|
||||||
|
"plugin:prettier/recommended",
|
||||||
|
],
|
||||||
|
root: true,
|
||||||
|
env: {
|
||||||
|
node: true,
|
||||||
|
jest: true,
|
||||||
|
},
|
||||||
|
ignorePatterns: [".eslintrc.js"],
|
||||||
|
"prettier/prettier": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
endOfLine: "auto",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
"@typescript-eslint/interface-name-prefix": "off",
|
||||||
|
"@typescript-eslint/explicit-function-return-type": "off",
|
||||||
|
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||||
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
},
|
||||||
|
};
|
35
common/ASC.TelegramReports/.gitignore
vendored
Executable file
35
common/ASC.TelegramReports/.gitignore
vendored
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
# compiled output
|
||||||
|
/dist
|
||||||
|
/node_modules
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
/coverage
|
||||||
|
/.nyc_output
|
||||||
|
|
||||||
|
# IDEs and editors
|
||||||
|
/.idea
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.c9/
|
||||||
|
*.launch
|
||||||
|
.settings/
|
||||||
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# IDE - VSCode
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
14
common/ASC.TelegramReports/README.md
Executable file
14
common/ASC.TelegramReports/README.md
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
# ASC Telegram Reports
|
||||||
|
|
||||||
|
ASC.TelegramReports
|
||||||
|
|
||||||
|
### Installation and usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ npm install
|
||||||
|
$ npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
### License
|
||||||
|
|
||||||
|
[GNU GPL V3](LICENSE)
|
7
common/ASC.TelegramReports/config/config.json
Executable file
7
common/ASC.TelegramReports/config/config.json
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"app": {
|
||||||
|
"port": 5016,
|
||||||
|
"appsettings": "../../../../config",
|
||||||
|
"environment": "Development"
|
||||||
|
}
|
||||||
|
}
|
26
common/ASC.TelegramReports/config/index.ts
Executable file
26
common/ASC.TelegramReports/config/index.ts
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
import * as nconf from "nconf";
|
||||||
|
import * as path from "path";
|
||||||
|
import * as fs from "fs";
|
||||||
|
|
||||||
|
import * as conf from "./config.json";
|
||||||
|
|
||||||
|
nconf.argv().env().file("config", path.join(__dirname, "config.json"));
|
||||||
|
|
||||||
|
getAndSaveAppsettings();
|
||||||
|
|
||||||
|
export default nconf;
|
||||||
|
|
||||||
|
function getAndSaveAppsettings() {
|
||||||
|
var appsettings = nconf.get("app").appsettings;
|
||||||
|
|
||||||
|
if (!path.isAbsolute(appsettings)) {
|
||||||
|
appsettings = path.join(__dirname, appsettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
var env = nconf.get("app").environment;
|
||||||
|
console.log('environment: ' + env);
|
||||||
|
|
||||||
|
nconf.file("appsettingsWithEnv", path.join(appsettings, 'appsettings.' + env + '.json'));
|
||||||
|
nconf.file("appsettings", path.join(appsettings, 'appsettings.json'));
|
||||||
|
nconf.file("telegramConf", path.join(appsettings, "telegram.json"));
|
||||||
|
}
|
31
common/ASC.TelegramReports/index.ts
Executable file
31
common/ASC.TelegramReports/index.ts
Executable file
@ -0,0 +1,31 @@
|
|||||||
|
import firebase from "firebase/compat/app";
|
||||||
|
import "firebase/compat/database";
|
||||||
|
|
||||||
|
import { NestFactory } from "@nestjs/core";
|
||||||
|
import { AppModule } from "./src/app/app.module";
|
||||||
|
import { AppService } from "./src/app/app.service";
|
||||||
|
|
||||||
|
import * as config from "./config";
|
||||||
|
|
||||||
|
const winston = require("./src/log.js");
|
||||||
|
|
||||||
|
const firebaseConfig = config.default.get("firebase");
|
||||||
|
firebase.initializeApp(firebaseConfig);
|
||||||
|
|
||||||
|
async function bootstrap() {
|
||||||
|
try {
|
||||||
|
const app = await NestFactory.create(AppModule);
|
||||||
|
const appService = app.get(AppService);
|
||||||
|
|
||||||
|
winston.info(`Start TelegramReports Service listening`);
|
||||||
|
|
||||||
|
const ref = firebase.database().ref("reports").limitToLast(1);
|
||||||
|
|
||||||
|
ref.on("child_added", (data) => {
|
||||||
|
appService.sendMessage(data.val())
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
winston.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bootstrap();
|
9
common/ASC.TelegramReports/nest-cli.json
Executable file
9
common/ASC.TelegramReports/nest-cli.json
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/nest-cli",
|
||||||
|
"collection": "@nestjs/schematics",
|
||||||
|
"sourceRoot": "src",
|
||||||
|
"entryFile": "index.js",
|
||||||
|
"compilerOptions": {
|
||||||
|
"deleteOutDir": true
|
||||||
|
}
|
||||||
|
}
|
75
common/ASC.TelegramReports/package.json
Executable file
75
common/ASC.TelegramReports/package.json
Executable file
@ -0,0 +1,75 @@
|
|||||||
|
{
|
||||||
|
"name": "telegram-reports",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Server for telegram-reports",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"prebuild": "rimraf dist",
|
||||||
|
"build": "rimraf dist & nest build",
|
||||||
|
"start": "rimraf dist & nest start",
|
||||||
|
"start:dev": "rimraf dist & nest start --watch",
|
||||||
|
"start:debug": "nest start --debug --watch",
|
||||||
|
"start:prod": "node dist/index",
|
||||||
|
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@aws-sdk/client-cloudwatch-logs": "^3.199.0",
|
||||||
|
"@nestjs/common": "^9.0.0",
|
||||||
|
"@nestjs/core": "^9.0.0",
|
||||||
|
"@nestjs/platform-express": "^9.0.0",
|
||||||
|
"@nestjs/typeorm": "^9.0.0",
|
||||||
|
"date-and-time": "^2.4.1",
|
||||||
|
"firebase": "^10.4.0",
|
||||||
|
"mysql2": "^2.3.3",
|
||||||
|
"nconf": "^0.12.0",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"rxjs": "^7.2.0",
|
||||||
|
"telegraf": "^4.13.1",
|
||||||
|
"typeorm": "^0.3.7",
|
||||||
|
"winston": "^3.8.2",
|
||||||
|
"winston-cloudwatch": "^6.1.1",
|
||||||
|
"winston-daily-rotate-file": "^4.5.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@nestjs/cli": "^9.0.0",
|
||||||
|
"@nestjs/schematics": "^9.0.0",
|
||||||
|
"@nestjs/testing": "^9.0.0",
|
||||||
|
"@types/express": "^4.17.13",
|
||||||
|
"@types/jest": "28.1.4",
|
||||||
|
"@types/multer": "^1.4.7",
|
||||||
|
"@types/node": "^16.0.0",
|
||||||
|
"@types/supertest": "^2.0.11",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
||||||
|
"@typescript-eslint/parser": "^5.0.0",
|
||||||
|
"eslint": "^8.0.1",
|
||||||
|
"eslint-config-prettier": "^8.3.0",
|
||||||
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
|
"jest": "28.1.2",
|
||||||
|
"prettier": "^2.3.2",
|
||||||
|
"source-map-support": "^0.5.20",
|
||||||
|
"supertest": "^6.1.3",
|
||||||
|
"ts-jest": "28.0.5",
|
||||||
|
"ts-loader": "^9.2.3",
|
||||||
|
"ts-node": "^10.0.0",
|
||||||
|
"tsconfig-paths": "4.0.0",
|
||||||
|
"typescript": "^4.3.5"
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"moduleFileExtensions": [
|
||||||
|
"js",
|
||||||
|
"json",
|
||||||
|
"ts"
|
||||||
|
],
|
||||||
|
"rootDir": "src",
|
||||||
|
"testRegex": ".*\\.spec\\.ts$",
|
||||||
|
"transform": {
|
||||||
|
"^.+\\.(t|j)s$": "ts-jest"
|
||||||
|
},
|
||||||
|
"collectCoverageFrom": [
|
||||||
|
"**/*.(t|j)s"
|
||||||
|
],
|
||||||
|
"coverageDirectory": "../coverage",
|
||||||
|
"testEnvironment": "node"
|
||||||
|
}
|
||||||
|
}
|
9
common/ASC.TelegramReports/src/app/app.module.ts
Executable file
9
common/ASC.TelegramReports/src/app/app.module.ts
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
import { Module } from "@nestjs/common";
|
||||||
|
import { AppService } from "./app.service";
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [],
|
||||||
|
controllers: [],
|
||||||
|
providers: [AppService],
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
43
common/ASC.TelegramReports/src/app/app.service.ts
Executable file
43
common/ASC.TelegramReports/src/app/app.service.ts
Executable file
@ -0,0 +1,43 @@
|
|||||||
|
import { Injectable } from "@nestjs/common";
|
||||||
|
import { Telegraf } from "telegraf";
|
||||||
|
|
||||||
|
import * as config from "../../config";
|
||||||
|
|
||||||
|
const winston = require("../log.js");
|
||||||
|
|
||||||
|
const { botKey, chatId } = config.default.get("telegramConf");
|
||||||
|
|
||||||
|
const MAX_LENGTH = 4096; //TG Limit
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AppService {
|
||||||
|
bot = new Telegraf(botKey);
|
||||||
|
|
||||||
|
chunkMessage = (str: string, size: number): Array<string> =>
|
||||||
|
Array.from({ length: Math.ceil(str.length / size) }, (_, i) =>
|
||||||
|
str.slice(i * size, i * size + size),
|
||||||
|
);
|
||||||
|
|
||||||
|
async sendMessage(report): Promise<string> {
|
||||||
|
if (!botKey) throw new Error("Empty bot key");
|
||||||
|
if (!chatId) throw new Error("Empty chat ID");
|
||||||
|
|
||||||
|
const message = "New bug report:\n" + JSON.stringify(report);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (message.length > MAX_LENGTH) {
|
||||||
|
for (const part of this.chunkMessage(message, MAX_LENGTH)) {
|
||||||
|
await this.bot.telegram.sendMessage(chatId, part);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await this.bot.telegram.sendMessage(chatId, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
winston.info(`Report sent successfully`, message);
|
||||||
|
return "Report sent successfully"
|
||||||
|
} catch (e) {
|
||||||
|
winston.error(e);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
103
common/ASC.TelegramReports/src/log.ts
Executable file
103
common/ASC.TelegramReports/src/log.ts
Executable file
@ -0,0 +1,103 @@
|
|||||||
|
import * as winston from "winston";
|
||||||
|
import * as WinstonCloudWatch from "winston-cloudwatch";
|
||||||
|
import * as date from "date-and-time";
|
||||||
|
import * as os from "os";
|
||||||
|
import * as config from "../config";
|
||||||
|
import { randomUUID } from "crypto";
|
||||||
|
import "winston-daily-rotate-file";
|
||||||
|
import * as path from "path";
|
||||||
|
import * as fs from "fs";
|
||||||
|
|
||||||
|
let logpath = process.env.logpath || null;
|
||||||
|
|
||||||
|
if (logpath != null) {
|
||||||
|
if (!path.isAbsolute(logpath)) {
|
||||||
|
logpath = path.join(__dirname, "..", logpath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileName = logpath
|
||||||
|
? path.join(logpath, "telegramreports.%DATE%.log")
|
||||||
|
: path.join(__dirname, "..", "..", "..", "..", "Logs", "telegramreports.%DATE%.log");
|
||||||
|
|
||||||
|
const dirName = path.dirname(fileName);
|
||||||
|
|
||||||
|
if (!fs.existsSync(dirName)) {
|
||||||
|
fs.mkdirSync(dirName);
|
||||||
|
}
|
||||||
|
|
||||||
|
const aws = config.default.get("aws").cloudWatch;
|
||||||
|
|
||||||
|
const accessKeyId = aws.accessKeyId;
|
||||||
|
const secretAccessKey = aws.secretAccessKey;
|
||||||
|
const awsRegion = aws.region;
|
||||||
|
const logGroupName = aws.logGroupName;
|
||||||
|
const logStreamName = aws.logStreamName.replace("${hostname}", os.hostname())
|
||||||
|
.replace("${applicationContext}", "TelegramReports")
|
||||||
|
.replace("${guid}", randomUUID())
|
||||||
|
.replace("${date}", date.format(new Date(), 'YYYY/MM/DDTHH.mm.ss'));
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
file: {
|
||||||
|
filename: fileName,
|
||||||
|
datePattern: "MM-DD",
|
||||||
|
handleExceptions: true,
|
||||||
|
humanReadableUnhandledException: true,
|
||||||
|
zippedArchive: true,
|
||||||
|
maxSize: "50m",
|
||||||
|
maxFiles: "30d",
|
||||||
|
json: true,
|
||||||
|
},
|
||||||
|
console: {
|
||||||
|
level: "debug",
|
||||||
|
handleExceptions: true,
|
||||||
|
json: false,
|
||||||
|
colorize: true,
|
||||||
|
},
|
||||||
|
cloudWatch: {
|
||||||
|
name: 'aws',
|
||||||
|
level: "debug",
|
||||||
|
logStreamName: logStreamName,
|
||||||
|
logGroupName: logGroupName,
|
||||||
|
awsRegion: awsRegion,
|
||||||
|
jsonMessage: true,
|
||||||
|
awsOptions: {
|
||||||
|
credentials: {
|
||||||
|
accessKeyId: accessKeyId,
|
||||||
|
secretAccessKey: secretAccessKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const transports: winston.transport[] = [
|
||||||
|
new winston.transports.Console(options.console),
|
||||||
|
new winston.transports.DailyRotateFile(options.file)
|
||||||
|
];
|
||||||
|
|
||||||
|
if (aws != null && aws.accessKeyId !== '') {
|
||||||
|
transports.push(new WinstonCloudWatch(options.cloudWatch));
|
||||||
|
}
|
||||||
|
|
||||||
|
const customFormat = winston.format(info => {
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
info.date = date.format(now, 'YYYY-MM-DD HH:mm:ss');
|
||||||
|
info.applicationContext = "TelegramReports";
|
||||||
|
info.level = info.level.toUpperCase();
|
||||||
|
|
||||||
|
const hostname = os.hostname();
|
||||||
|
|
||||||
|
info["instance-id"] = hostname;
|
||||||
|
|
||||||
|
return info;
|
||||||
|
})();
|
||||||
|
|
||||||
|
module.exports = winston.createLogger({
|
||||||
|
format: winston.format.combine(
|
||||||
|
customFormat,
|
||||||
|
winston.format.json()
|
||||||
|
),
|
||||||
|
transports: transports,
|
||||||
|
exitOnError: false,
|
||||||
|
});
|
4
common/ASC.TelegramReports/tsconfig.build.json
Executable file
4
common/ASC.TelegramReports/tsconfig.build.json
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
|
||||||
|
}
|
22
common/ASC.TelegramReports/tsconfig.json
Executable file
22
common/ASC.TelegramReports/tsconfig.json
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "commonjs",
|
||||||
|
"declaration": true,
|
||||||
|
"removeComments": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"target": "es2017",
|
||||||
|
"sourceMap": true,
|
||||||
|
"outDir": "./dist",
|
||||||
|
"baseUrl": "./",
|
||||||
|
"incremental": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strictNullChecks": false,
|
||||||
|
"noImplicitAny": false,
|
||||||
|
"strictBindCallApply": false,
|
||||||
|
"forceConsistentCasingInFileNames": false,
|
||||||
|
"noFallthroughCasesInSwitch": false,
|
||||||
|
"resolveJsonModule": true
|
||||||
|
}
|
||||||
|
}
|
9534
common/ASC.TelegramReports/yarn.lock
Executable file
9534
common/ASC.TelegramReports/yarn.lock
Executable file
File diff suppressed because it is too large
Load Diff
@ -24,6 +24,8 @@
|
|||||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||||
|
|
||||||
|
using ASC.Core;
|
||||||
|
|
||||||
namespace ASC.ApiCache;
|
namespace ASC.ApiCache;
|
||||||
|
|
||||||
public class Startup
|
public class Startup
|
||||||
@ -117,6 +119,8 @@ public class Startup
|
|||||||
{
|
{
|
||||||
app.UseCors(CustomCorsPolicyName);
|
app.UseCors(CustomCorsPolicyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.UseSynchronizationContextMiddleware();
|
||||||
|
|
||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
|
|
||||||
|
@ -139,6 +139,8 @@ public class Startup
|
|||||||
{
|
{
|
||||||
app.UseCors(CustomCorsPolicyName);
|
app.UseCors(CustomCorsPolicyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.UseSynchronizationContextMiddleware();
|
||||||
|
|
||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
|
|
||||||
|
6
config/telegram.json
Normal file
6
config/telegram.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"telegramConf": {
|
||||||
|
"botKey": "",
|
||||||
|
"chatId": ""
|
||||||
|
}
|
||||||
|
}
|
@ -88,6 +88,9 @@ export default function withFileActions(WrappedFileItem) {
|
|||||||
e.target.classList.contains("item-file-name") ||
|
e.target.classList.contains("item-file-name") ||
|
||||||
e.target.classList.contains("row-content-link");
|
e.target.classList.contains("row-content-link");
|
||||||
|
|
||||||
|
if ((isRoomsFolder || isArchiveFolder) && isFileName && !isSelected)
|
||||||
|
setBufferSelection(item);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isPrivacy ||
|
isPrivacy ||
|
||||||
isTrashFolder ||
|
isTrashFolder ||
|
||||||
|
@ -5,33 +5,12 @@ import AutoSizer from "react-virtualized-auto-sizer";
|
|||||||
import CustomScrollbarsVirtualList from "@docspace/components/scrollbar/custom-scrollbars-virtual-list";
|
import CustomScrollbarsVirtualList from "@docspace/components/scrollbar/custom-scrollbars-virtual-list";
|
||||||
import InfiniteLoader from "react-window-infinite-loader";
|
import InfiniteLoader from "react-window-infinite-loader";
|
||||||
import User from "./User";
|
import User from "./User";
|
||||||
import { tablet, mobile, isMobile } from "@docspace/components/utils/device";
|
import { isMobile } from "@docspace/components/utils/device";
|
||||||
|
import throttle from "lodash/throttle";
|
||||||
|
import Loaders from "@docspace/common/components/Loaders";
|
||||||
|
|
||||||
const StyledMembersList = styled.div`
|
const StyledMembersList = styled.div`
|
||||||
height: ${({ withBanner, isPublicRoomType }) =>
|
height: ${({ offsetTop }) => `calc(100vh - ${offsetTop})`};
|
||||||
isPublicRoomType
|
|
||||||
? withBanner
|
|
||||||
? "calc(100vh - 442px)"
|
|
||||||
: "calc(100vh - 286px)"
|
|
||||||
: "calc(100vh - 266px)"};
|
|
||||||
|
|
||||||
@media ${tablet} {
|
|
||||||
height: ${({ withBanner, isPublicRoomType }) =>
|
|
||||||
isPublicRoomType
|
|
||||||
? withBanner
|
|
||||||
? "calc(100vh - 362px)"
|
|
||||||
: "calc(100vh - 206px)"
|
|
||||||
: "calc(100vh - 186px)"};
|
|
||||||
}
|
|
||||||
|
|
||||||
@media ${mobile} {
|
|
||||||
height: ${({ withBanner, isPublicRoomType }) =>
|
|
||||||
isPublicRoomType
|
|
||||||
? withBanner
|
|
||||||
? "calc(100vh - 426px)"
|
|
||||||
: "calc(100vh - 270px)"
|
|
||||||
: "calc(100vh - 250px)"};
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Item = memo(({ data, index, style }) => {
|
const Item = memo(({ data, index, style }) => {
|
||||||
@ -53,6 +32,18 @@ const Item = memo(({ data, index, style }) => {
|
|||||||
|
|
||||||
const user = members[index];
|
const user = members[index];
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return (
|
||||||
|
<div style={{ ...style, width: "calc(100% - 8px)", margin: "0 -16px" }}>
|
||||||
|
<Loaders.SelectorRowLoader
|
||||||
|
isMultiSelect={false}
|
||||||
|
isContainer={true}
|
||||||
|
isUser={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={user.id} style={{ ...style, width: "calc(100% - 8px)" }}>
|
<div key={user.id} style={{ ...style, width: "calc(100% - 8px)" }}>
|
||||||
<User
|
<User
|
||||||
@ -96,21 +87,34 @@ const MembersList = (props) => {
|
|||||||
itemCount,
|
itemCount,
|
||||||
onRepeatInvitation,
|
onRepeatInvitation,
|
||||||
loadNextPage,
|
loadNextPage,
|
||||||
isPublicRoomType,
|
|
||||||
withBanner,
|
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const itemsCount = members.length;
|
const itemsCount = hasNextPage ? members.length + 1 : members.length;
|
||||||
|
|
||||||
const canInviteUserInRoomAbility = security?.EditAccess;
|
const canInviteUserInRoomAbility = security?.EditAccess;
|
||||||
const [isNextPageLoading, setIsNextPageLoading] = useState(false);
|
const [isNextPageLoading, setIsNextPageLoading] = useState(false);
|
||||||
const [isMobileView, setIsMobileView] = useState(isMobile());
|
const [isMobileView, setIsMobileView] = useState(isMobile());
|
||||||
|
|
||||||
const onResize = () => {
|
const [offsetTop, setOffsetTop] = useState(0);
|
||||||
|
|
||||||
|
const onResize = throttle(() => {
|
||||||
const isMobileView = isMobile();
|
const isMobileView = isMobile();
|
||||||
setIsMobileView(isMobileView);
|
setIsMobileView(isMobileView);
|
||||||
|
setOffset();
|
||||||
|
}, 300);
|
||||||
|
|
||||||
|
const setOffset = () => {
|
||||||
|
const rect = document
|
||||||
|
.getElementById("infoPanelMembersList")
|
||||||
|
?.getBoundingClientRect();
|
||||||
|
|
||||||
|
setOffsetTop(Math.ceil(rect?.top) + 2 + "px");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setOffset();
|
||||||
|
}, [members]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.addEventListener("resize", onResize);
|
window.addEventListener("resize", onResize);
|
||||||
|
|
||||||
@ -138,10 +142,7 @@ const MembersList = (props) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledMembersList
|
<StyledMembersList id="infoPanelMembersList" offsetTop={offsetTop}>
|
||||||
withBanner={withBanner}
|
|
||||||
isPublicRoomType={isPublicRoomType}
|
|
||||||
>
|
|
||||||
<AutoSizer>
|
<AutoSizer>
|
||||||
{({ height, width }) => (
|
{({ height, width }) => (
|
||||||
<InfiniteLoader
|
<InfiniteLoader
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
RoomsType,
|
RoomsType,
|
||||||
ShareAccessRights,
|
ShareAccessRights,
|
||||||
} from "@docspace/common/constants";
|
} from "@docspace/common/constants";
|
||||||
|
import Loaders from "@docspace/common/components/Loaders";
|
||||||
import MembersHelper from "../../helpers/MembersHelper";
|
import MembersHelper from "../../helpers/MembersHelper";
|
||||||
import PublicRoomBlock from "./sub-components/PublicRoomBlock";
|
import PublicRoomBlock from "./sub-components/PublicRoomBlock";
|
||||||
import MembersList from "./MembersList";
|
import MembersList from "./MembersList";
|
||||||
@ -38,14 +38,16 @@ const Members = ({
|
|||||||
setExternalLinks,
|
setExternalLinks,
|
||||||
membersFilter,
|
membersFilter,
|
||||||
externalLinks,
|
externalLinks,
|
||||||
|
members,
|
||||||
|
setMembersList,
|
||||||
}) => {
|
}) => {
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const membersHelper = new MembersHelper({ t });
|
const membersHelper = new MembersHelper({ t });
|
||||||
|
|
||||||
const [members, setMembers] = useState(null);
|
|
||||||
|
|
||||||
const security = selectionParentRoom ? selectionParentRoom.security : {};
|
const security = selectionParentRoom ? selectionParentRoom.security : {};
|
||||||
|
|
||||||
const fetchMembers = async (roomId, clearFilter = true) => {
|
const fetchMembers = async (roomId, clearFilter = true) => {
|
||||||
|
if (isLoading) return;
|
||||||
const isPublic = selection?.roomType ?? selectionParentRoom?.roomType;
|
const isPublic = selection?.roomType ?? selectionParentRoom?.roomType;
|
||||||
const requests = [getRoomMembers(roomId, clearFilter)];
|
const requests = [getRoomMembers(roomId, clearFilter)];
|
||||||
|
|
||||||
@ -53,7 +55,12 @@ const Members = ({
|
|||||||
requests.push(getRoomLinks(roomId));
|
requests.push(getRoomLinks(roomId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let timerId;
|
||||||
|
if (clearFilter) timerId = setTimeout(() => setIsLoading(true), 300);
|
||||||
|
|
||||||
const [data, links] = await Promise.all(requests);
|
const [data, links] = await Promise.all(requests);
|
||||||
|
clearFilter && setIsLoading(false);
|
||||||
|
clearTimeout(timerId);
|
||||||
|
|
||||||
links && setExternalLinks(links);
|
links && setExternalLinks(links);
|
||||||
|
|
||||||
@ -131,11 +138,10 @@ const Members = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateSelectionParentRoomActionSelection = useCallback(async () => {
|
const updateSelectionParentRoomActionSelection = useCallback(async () => {
|
||||||
if (!selection.isRoom) return;
|
if (!selection.isRoom || selection.id === members?.roomId) return;
|
||||||
|
|
||||||
const fetchedMembers = await fetchMembers(selection.id);
|
const fetchedMembers = await fetchMembers(selection.id);
|
||||||
|
setMembersList(fetchedMembers);
|
||||||
setMembers(fetchedMembers);
|
|
||||||
|
|
||||||
setSelectionParentRoom({
|
setSelectionParentRoom({
|
||||||
...selection,
|
...selection,
|
||||||
@ -159,7 +165,7 @@ const Members = ({
|
|||||||
members: fetchedMembers,
|
members: fetchedMembers,
|
||||||
});
|
});
|
||||||
|
|
||||||
setMembers(fetchedMembers);
|
setMembersList(fetchedMembers);
|
||||||
}, [selectionParentRoom, selection?.id, updateRoomMembers]);
|
}, [selectionParentRoom, selection?.id, updateRoomMembers]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -179,12 +185,6 @@ const Members = ({
|
|||||||
.catch((err) => toastr.error(err));
|
.catch((err) => toastr.error(err));
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!selectionParentRoom || !members) return null;
|
|
||||||
|
|
||||||
const [currentMember] = members.administrators.filter(
|
|
||||||
(member) => member.id === selfId
|
|
||||||
);
|
|
||||||
|
|
||||||
const loadNextPage = async () => {
|
const loadNextPage = async () => {
|
||||||
const roomId = selectionParentRoom.id;
|
const roomId = selectionParentRoom.id;
|
||||||
const fetchedMembers = await fetchMembers(roomId, false);
|
const fetchedMembers = await fetchMembers(roomId, false);
|
||||||
@ -196,9 +196,16 @@ const Members = ({
|
|||||||
expected: [...members.expected, ...expected],
|
expected: [...members.expected, ...expected],
|
||||||
};
|
};
|
||||||
|
|
||||||
setMembers(newMembers);
|
setMembersList(newMembers);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (isLoading) return <Loaders.InfoPanelViewLoader view="members" />;
|
||||||
|
else if (!members) return <></>;
|
||||||
|
|
||||||
|
const [currentMember] = members.administrators.filter(
|
||||||
|
(member) => member.id === selfId
|
||||||
|
);
|
||||||
|
|
||||||
const { administrators, users, expected } = members;
|
const { administrators, users, expected } = members;
|
||||||
const membersList = [...administrators, ...users, ...expected];
|
const membersList = [...administrators, ...users, ...expected];
|
||||||
|
|
||||||
@ -224,11 +231,11 @@ const Members = ({
|
|||||||
changeUserType={changeUserType}
|
changeUserType={changeUserType}
|
||||||
setIsScrollLocked={setIsScrollLocked}
|
setIsScrollLocked={setIsScrollLocked}
|
||||||
hasNextPage={membersList.length - headersCount < membersFilter.total}
|
hasNextPage={membersList.length - headersCount < membersFilter.total}
|
||||||
itemCount={membersFilter.total}
|
itemCount={membersFilter.total + headersCount}
|
||||||
onRepeatInvitation={onRepeatInvitation}
|
onRepeatInvitation={onRepeatInvitation}
|
||||||
isPublicRoomType={isPublicRoomType}
|
isPublicRoomType={isPublicRoomType}
|
||||||
withBanner={isPublicRoomType && externalLinks.length > 0}
|
withBanner={isPublicRoomType && externalLinks.length > 0}
|
||||||
setMembers={setMembers}
|
setMembers={setMembersList}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@ -238,7 +245,6 @@ export default inject(
|
|||||||
({ auth, filesStore, peopleStore, selectedFolderStore, publicRoomStore }) => {
|
({ auth, filesStore, peopleStore, selectedFolderStore, publicRoomStore }) => {
|
||||||
const {
|
const {
|
||||||
selectionParentRoom,
|
selectionParentRoom,
|
||||||
selection,
|
|
||||||
setSelectionParentRoom,
|
setSelectionParentRoom,
|
||||||
setView,
|
setView,
|
||||||
roomsView,
|
roomsView,
|
||||||
@ -247,6 +253,8 @@ export default inject(
|
|||||||
setUpdateRoomMembers,
|
setUpdateRoomMembers,
|
||||||
|
|
||||||
setIsScrollLocked,
|
setIsScrollLocked,
|
||||||
|
membersList,
|
||||||
|
setMembersList,
|
||||||
} = auth.infoPanelStore;
|
} = auth.infoPanelStore;
|
||||||
const {
|
const {
|
||||||
getRoomMembers,
|
getRoomMembers,
|
||||||
@ -289,6 +297,8 @@ export default inject(
|
|||||||
setExternalLinks,
|
setExternalLinks,
|
||||||
membersFilter,
|
membersFilter,
|
||||||
externalLinks: roomLinks,
|
externalLinks: roomLinks,
|
||||||
|
members: membersList,
|
||||||
|
setMembersList,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
)(
|
)(
|
||||||
|
@ -1,17 +1,21 @@
|
|||||||
import InfoPanelRoomEmptyScreenSvgUrl from "PUBLIC_DIR/images/empty_screen_corporate.svg?url";
|
import InfoPanelRoomEmptyScreenSvgUrl from "PUBLIC_DIR/images/empty_screen_corporate.svg?url";
|
||||||
import InfoPanelRoomEmptyScreenDarkSvgUrl from "PUBLIC_DIR/images/empty_screen_corporate_dark.svg?url";
|
import InfoPanelRoomEmptyScreenDarkSvgUrl from "PUBLIC_DIR/images/empty_screen_corporate_dark.svg?url";
|
||||||
|
|
||||||
import React from "react";
|
import React, { useEffect } from "react";
|
||||||
import { inject, observer } from "mobx-react";
|
import { inject, observer } from "mobx-react";
|
||||||
import Text from "@docspace/components/text";
|
import Text from "@docspace/components/text";
|
||||||
|
|
||||||
import { StyledNoItemContainer } from "../../styles/noItem";
|
import { StyledNoItemContainer } from "../../styles/noItem";
|
||||||
|
|
||||||
const NoRoomItem = ({ t, theme }) => {
|
const NoRoomItem = ({ t, theme, setMembersList }) => {
|
||||||
const imageSrc = theme.isBase
|
const imageSrc = theme.isBase
|
||||||
? InfoPanelRoomEmptyScreenSvgUrl
|
? InfoPanelRoomEmptyScreenSvgUrl
|
||||||
: InfoPanelRoomEmptyScreenDarkSvgUrl;
|
: InfoPanelRoomEmptyScreenDarkSvgUrl;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setMembersList(null);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledNoItemContainer className="info-panel_gallery-empty-screen">
|
<StyledNoItemContainer className="info-panel_gallery-empty-screen">
|
||||||
<div className="no-thumbnail-img-wrapper">
|
<div className="no-thumbnail-img-wrapper">
|
||||||
@ -27,5 +31,6 @@ const NoRoomItem = ({ t, theme }) => {
|
|||||||
export default inject(({ auth }) => {
|
export default inject(({ auth }) => {
|
||||||
return {
|
return {
|
||||||
theme: auth.settingsStore.theme,
|
theme: auth.settingsStore.theme,
|
||||||
|
setMembersList: auth.infoPanelStore.setMembersList,
|
||||||
};
|
};
|
||||||
})(observer(NoRoomItem));
|
})(observer(NoRoomItem));
|
||||||
|
@ -1,24 +1,30 @@
|
|||||||
|
import IntegrationSvgUrl from "PUBLIC_DIR/images/integration.svg?url";
|
||||||
|
import IntegrationDarkSvgUrl from "PUBLIC_DIR/images/integration.dark.svg?url";
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import { withTranslation } from "react-i18next";
|
import { withTranslation } from "react-i18next";
|
||||||
|
import { inject, observer } from "mobx-react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
import { showLoader, hideLoader } from "@docspace/common/utils";
|
||||||
|
|
||||||
import Box from "@docspace/components/box";
|
import Box from "@docspace/components/box";
|
||||||
import Text from "@docspace/components/text";
|
import Text from "@docspace/components/text";
|
||||||
import Link from "@docspace/components/link";
|
import Link from "@docspace/components/link";
|
||||||
import Badge from "@docspace/components/badge";
|
import Badge from "@docspace/components/badge";
|
||||||
import toastr from "@docspace/components/toast/toastr";
|
import toastr from "@docspace/components/toast/toastr";
|
||||||
import Button from "@docspace/components/button";
|
import Button from "@docspace/components/button";
|
||||||
import { showLoader, hideLoader } from "@docspace/common/utils";
|
|
||||||
import ConsumerItem from "./sub-components/consumerItem";
|
|
||||||
import ConsumerModalDialog from "./sub-components/consumerModalDialog";
|
|
||||||
import { inject, observer } from "mobx-react";
|
|
||||||
import {
|
import {
|
||||||
mobile,
|
mobile,
|
||||||
smallTablet,
|
smallTablet,
|
||||||
isSmallTablet,
|
isSmallTablet,
|
||||||
} from "@docspace/components/utils/device";
|
} from "@docspace/components/utils/device";
|
||||||
import IntegrationSvgUrl from "PUBLIC_DIR/images/integration.svg?url";
|
|
||||||
import IntegrationDarkSvgUrl from "PUBLIC_DIR/images/integration.dark.svg?url";
|
import ConsumerItem from "./sub-components/consumerItem";
|
||||||
|
import ConsumerModalDialog from "./sub-components/consumerModalDialog";
|
||||||
|
|
||||||
|
import ThirdPartyLoader from "./sub-components/thirdPartyLoader";
|
||||||
|
|
||||||
const RootContainer = styled(Box)`
|
const RootContainer = styled(Box)`
|
||||||
max-width: 700px;
|
max-width: 700px;
|
||||||
@ -40,7 +46,6 @@ const RootContainer = styled(Box)`
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(293px, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(293px, 1fr));
|
||||||
gap: 20px;
|
gap: 20px;
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.consumer-item-wrapper {
|
.consumer-item-wrapper {
|
||||||
@ -66,10 +71,11 @@ const RootContainer = styled(Box)`
|
|||||||
}
|
}
|
||||||
|
|
||||||
.business-plan {
|
.business-plan {
|
||||||
|
grid-column: 1 / -1;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 16px;
|
margin-bottom: -4px;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -218,54 +224,56 @@ class ThirdPartyServices extends React.Component {
|
|||||||
scale={isSmallTablet()}
|
scale={isSmallTablet()}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<div className="consumers-list-container">
|
{!consumers.length ? (
|
||||||
{freeConsumers.map((consumer) => (
|
<ThirdPartyLoader />
|
||||||
<Box className="consumer-item-wrapper" key={consumer.name}>
|
) : (
|
||||||
<ConsumerItem
|
<div className="consumers-list-container">
|
||||||
consumer={consumer}
|
{freeConsumers.map((consumer) => (
|
||||||
dialogVisible={dialogVisible}
|
<Box className="consumer-item-wrapper" key={consumer.name}>
|
||||||
isLoading={isLoading}
|
<ConsumerItem
|
||||||
onChangeLoading={onChangeLoading}
|
consumer={consumer}
|
||||||
onModalClose={onModalClose}
|
dialogVisible={dialogVisible}
|
||||||
onModalOpen={onModalOpen}
|
isLoading={isLoading}
|
||||||
setConsumer={setConsumer}
|
onChangeLoading={onChangeLoading}
|
||||||
updateConsumerProps={updateConsumerProps}
|
onModalClose={onModalClose}
|
||||||
t={t}
|
onModalOpen={onModalOpen}
|
||||||
isThirdPartyAvailable={isThirdPartyAvailable}
|
setConsumer={setConsumer}
|
||||||
/>
|
updateConsumerProps={updateConsumerProps}
|
||||||
</Box>
|
t={t}
|
||||||
))}
|
isThirdPartyAvailable={isThirdPartyAvailable}
|
||||||
</div>
|
/>
|
||||||
{!isThirdPartyAvailable && (
|
</Box>
|
||||||
<div className="business-plan">
|
))}
|
||||||
<Text fontSize="16px" fontWeight={700}>
|
{!isThirdPartyAvailable && (
|
||||||
{t("IncludedInBusiness")}
|
<div className="business-plan">
|
||||||
</Text>
|
<Text fontSize="16px" fontWeight={700}>
|
||||||
<Badge
|
{t("IncludedInBusiness")}
|
||||||
backgroundColor="#EDC409"
|
</Text>
|
||||||
label={t("Common:Paid")}
|
<Badge
|
||||||
isPaidBadge={true}
|
backgroundColor="#EDC409"
|
||||||
/>
|
label={t("Common:Paid")}
|
||||||
|
isPaidBadge={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{paidConsumers.map((consumer) => (
|
||||||
|
<Box className="consumer-item-wrapper" key={consumer.name}>
|
||||||
|
<ConsumerItem
|
||||||
|
consumer={consumer}
|
||||||
|
dialogVisible={dialogVisible}
|
||||||
|
isLoading={isLoading}
|
||||||
|
onChangeLoading={onChangeLoading}
|
||||||
|
onModalClose={onModalClose}
|
||||||
|
onModalOpen={onModalOpen}
|
||||||
|
setConsumer={setConsumer}
|
||||||
|
updateConsumerProps={updateConsumerProps}
|
||||||
|
t={t}
|
||||||
|
isThirdPartyAvailable={isThirdPartyAvailable}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="consumers-list-container">
|
|
||||||
{paidConsumers.map((consumer) => (
|
|
||||||
<Box className="consumer-item-wrapper" key={consumer.name}>
|
|
||||||
<ConsumerItem
|
|
||||||
consumer={consumer}
|
|
||||||
dialogVisible={dialogVisible}
|
|
||||||
isLoading={isLoading}
|
|
||||||
onChangeLoading={onChangeLoading}
|
|
||||||
onModalClose={onModalClose}
|
|
||||||
onModalOpen={onModalOpen}
|
|
||||||
setConsumer={setConsumer}
|
|
||||||
updateConsumerProps={updateConsumerProps}
|
|
||||||
t={t}
|
|
||||||
isThirdPartyAvailable={isThirdPartyAvailable}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</RootContainer>
|
</RootContainer>
|
||||||
{dialogVisible && (
|
{dialogVisible && (
|
||||||
<ConsumerModalDialog
|
<ConsumerModalDialog
|
||||||
|
@ -28,7 +28,7 @@ const StyledBox = styled(Box)`
|
|||||||
css`
|
css`
|
||||||
path {
|
path {
|
||||||
fill: #ffffff;
|
fill: #ffffff;
|
||||||
opacity: ${props.isSet ? 1 : 0.16};
|
opacity: 1;
|
||||||
}
|
}
|
||||||
${props.isLinkedIn &&
|
${props.isLinkedIn &&
|
||||||
css`
|
css`
|
||||||
@ -45,7 +45,7 @@ const StyledBox = styled(Box)`
|
|||||||
|
|
||||||
${(props) =>
|
${(props) =>
|
||||||
!props.isThirdPartyAvailable &&
|
!props.isThirdPartyAvailable &&
|
||||||
!props.isSet &&
|
props.canSet &&
|
||||||
css`
|
css`
|
||||||
path {
|
path {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
@ -81,7 +81,7 @@ class ConsumerItem extends React.Component {
|
|||||||
widthProp="100%"
|
widthProp="100%"
|
||||||
>
|
>
|
||||||
<StyledBox
|
<StyledBox
|
||||||
isSet={isSet}
|
canSet={consumer.canSet}
|
||||||
isLinkedIn={consumer.name === "linkedin"}
|
isLinkedIn={consumer.name === "linkedin"}
|
||||||
isThirdPartyAvailable={isThirdPartyAvailable}
|
isThirdPartyAvailable={isThirdPartyAvailable}
|
||||||
>
|
>
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
import Loaders from "@docspace/common/components/Loaders";
|
||||||
|
|
||||||
|
const StyledLoader = styled.div`
|
||||||
|
max-width: 700px;
|
||||||
|
width: 100%;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(293px, 1fr));
|
||||||
|
gap: 20px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ThirdPartyLoader = () => {
|
||||||
|
const rectangles = new Array(6).fill(0);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledLoader>
|
||||||
|
{rectangles.map((_) => (
|
||||||
|
<Loaders.Rectangle height="120px" borderRadius="6px" />
|
||||||
|
))}
|
||||||
|
</StyledLoader>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ThirdPartyLoader;
|
@ -2480,7 +2480,7 @@ class FilesStore {
|
|||||||
};
|
};
|
||||||
|
|
||||||
getRoomMembers = (id, clearFilter = true) => {
|
getRoomMembers = (id, clearFilter = true) => {
|
||||||
let newFilter = this.membersFilter;
|
let newFilter = clone(this.membersFilter);
|
||||||
|
|
||||||
if (clearFilter) {
|
if (clearFilter) {
|
||||||
newFilter = this.getDefaultMembersFilter();
|
newFilter = this.getDefaultMembersFilter();
|
||||||
@ -2496,7 +2496,6 @@ class FilesStore {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return api.rooms.getRoomMembers(id, membersFilters).then((res) => {
|
return api.rooms.getRoomMembers(id, membersFilters).then((res) => {
|
||||||
const newFilter = clone(this.membersFilter);
|
|
||||||
newFilter.total = res.total;
|
newFilter.total = res.total;
|
||||||
this.setMembersFilter(newFilter);
|
this.setMembersFilter(newFilter);
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ class InfoPanelStore {
|
|||||||
filesStore = null;
|
filesStore = null;
|
||||||
selectedFolderStore = null;
|
selectedFolderStore = null;
|
||||||
treeFoldersStore = null;
|
treeFoldersStore = null;
|
||||||
|
membersList = null;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
@ -76,6 +77,7 @@ class InfoPanelStore {
|
|||||||
this.roomsView = view;
|
this.roomsView = view;
|
||||||
this.fileView = view === "info_members" ? "info_history" : view;
|
this.fileView = view === "info_members" ? "info_history" : view;
|
||||||
this.isScrollLocked = false;
|
this.isScrollLocked = false;
|
||||||
|
this.setMembersList(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
setUpdateRoomMembers = (updateRoomMembers) => {
|
setUpdateRoomMembers = (updateRoomMembers) => {
|
||||||
@ -329,6 +331,10 @@ class InfoPanelStore {
|
|||||||
const pathname = givenPathName || window.location.pathname.toLowerCase();
|
const pathname = givenPathName || window.location.pathname.toLowerCase();
|
||||||
return pathname.indexOf("files/trash") !== -1;
|
return pathname.indexOf("files/trash") !== -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
setMembersList = (membersList) => {
|
||||||
|
this.membersList = membersList;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default InfoPanelStore;
|
export default InfoPanelStore;
|
||||||
|
@ -214,7 +214,6 @@ abstract class FileOperation<T, TId> : FileOperation where T : FileOperationData
|
|||||||
protected ILinkDao LinkDao { get; private set; }
|
protected ILinkDao LinkDao { get; private set; }
|
||||||
protected IProviderDao ProviderDao { get; private set; }
|
protected IProviderDao ProviderDao { get; private set; }
|
||||||
protected ILogger Logger { get; private set; }
|
protected ILogger Logger { get; private set; }
|
||||||
protected CancellationToken CancellationToken { get; private set; }
|
|
||||||
protected internal List<TId> Folders { get; private set; }
|
protected internal List<TId> Folders { get; private set; }
|
||||||
protected internal List<TId> Files { get; private set; }
|
protected internal List<TId> Files { get; private set; }
|
||||||
protected ExternalShareData CurrentShareData { get; private set; }
|
protected ExternalShareData CurrentShareData { get; private set; }
|
||||||
|
Loading…
Reference in New Issue
Block a user