@neuralinnovations/dataisland-sdk 0.0.1-dev2 → 0.0.1-dev3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +4 -1
- package/.eslintrc.json +1 -1
- package/jest.config.ts +3 -3
- package/jest.setup.ts +2 -2
- package/package.json +3 -2
- package/src/appBuilder.ts +6 -6
- package/src/appSdk.ts +6 -6
- package/src/commands/startCommandHandler.ts +2 -2
- package/src/context.ts +3 -3
- package/src/credentials.ts +29 -7
- package/src/disposable.ts +1 -1
- package/src/dto/accessGroupResponse.ts +35 -0
- package/src/dto/chatResponse.ts +104 -0
- package/src/dto/userInfoResponse.ts +11 -1
- package/src/dto/workspacesResponse.ts +49 -0
- package/src/events.ts +1 -1
- package/src/index.ts +10 -12
- package/src/internal/app.impl.ts +21 -21
- package/src/internal/appBuilder.impl.ts +16 -16
- package/src/internal/createApp.impl.ts +3 -3
- package/src/services/commandService.ts +3 -3
- package/src/services/credentialService.ts +3 -3
- package/src/services/middlewareService.ts +3 -3
- package/src/services/organizationService.ts +18 -116
- package/src/services/requestBuilder.ts +6 -6
- package/src/services/responseUtils.ts +32 -0
- package/src/services/rpcService.ts +5 -5
- package/src/services/service.ts +3 -3
- package/src/services/userProfileService.ts +18 -66
- package/src/storages/chat.ts +37 -0
- package/src/storages/file.impl.ts +68 -0
- package/src/storages/files.impl.ts +192 -0
- package/src/storages/files.ts +67 -0
- package/src/storages/groups.impl.ts +337 -0
- package/src/storages/groups.ts +43 -0
- package/src/storages/organization.impl.ts +68 -0
- package/src/storages/organization.ts +33 -0
- package/src/storages/organizations.impl.ts +191 -0
- package/src/storages/organizations.ts +8 -28
- package/src/storages/userProfile.impl.ts +56 -0
- package/src/storages/userProfile.ts +2 -2
- package/src/storages/workspace.impl.ts +109 -0
- package/src/storages/workspace.ts +43 -0
- package/src/storages/workspaces.impl.ts +212 -0
- package/src/storages/workspaces.ts +53 -0
- package/test/commands.test.ts +8 -8
- package/test/disposable.test.ts +3 -3
- package/test/events.test.ts +4 -4
- package/test/index.test.ts +102 -40
- package/test/registry.test.ts +8 -8
- package/test/services.test.ts +15 -15
- package/test/unitTest.test.ts +2 -2
- package/test_file.pdf +0 -0
- package/src/services/organizationImpl.ts +0 -51
- package/src/services/organizationsImpl.ts +0 -55
- package/src/types.ts +0 -86
@@ -1,126 +1,28 @@
|
|
1
|
-
import { Service } from
|
2
|
-
import {
|
3
|
-
|
4
|
-
|
5
|
-
Organizations
|
6
|
-
} from '../storages/organizations'
|
7
|
-
import { OrganizationDto, UserSettings } from '../dto/userInfoResponse'
|
8
|
-
import { RpcService } from './rpcService'
|
9
|
-
import { OrganizationImpl } from './organizationImpl'
|
10
|
-
import { OrganizationsImpl } from './organizationsImpl'
|
1
|
+
import { Service } from "./service"
|
2
|
+
import { Organizations } from "../storages/organizations"
|
3
|
+
import { OrganizationDto, UserSettings } from "../dto/userInfoResponse"
|
4
|
+
import { OrganizationsImpl } from "../storages/organizations.impl"
|
11
5
|
|
12
6
|
export class OrganizationService extends Service {
|
13
|
-
private
|
7
|
+
private _impl?: OrganizationsImpl
|
8
|
+
|
9
|
+
private get impl(): OrganizationsImpl {
|
10
|
+
return this._impl ?? (this._impl = new OrganizationsImpl(this.context))
|
11
|
+
}
|
14
12
|
|
15
13
|
get organizations(): Organizations {
|
16
14
|
return this.impl
|
17
15
|
}
|
18
16
|
|
19
|
-
initFrom(
|
20
|
-
settings: UserSettings,
|
17
|
+
async initFrom(
|
21
18
|
adminInOrganization: string[],
|
22
|
-
organizations: OrganizationDto[]
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
// add organization to collection
|
31
|
-
this.impl.organizations.push(org)
|
32
|
-
|
33
|
-
// dispatch event, organization added
|
34
|
-
this.impl.dispatch({
|
35
|
-
type: OrganizationEvent.ADDED,
|
36
|
-
data: org
|
37
|
-
})
|
38
|
-
}
|
39
|
-
}
|
40
|
-
|
41
|
-
async deleteOrganization(id: OrganizationId): Promise<void> {
|
42
|
-
if (id === undefined || id === null) {
|
43
|
-
throw new Error('Organization delete, id is undefined or null')
|
44
|
-
}
|
45
|
-
if (id.length === 0 || id.trim().length === 0) {
|
46
|
-
throw new Error('Organization delete, id is empty')
|
47
|
-
}
|
48
|
-
if (!this.impl.contains(id)) {
|
49
|
-
throw new Error(`Organization delete, id: ${id} is not found`)
|
50
|
-
}
|
51
|
-
const response = await this.resolve(RpcService)
|
52
|
-
?.requestBuilder('/api/v1/Organizations')
|
53
|
-
.searchParam('id', id)
|
54
|
-
.sendDelete()
|
55
|
-
if (!response?.ok) {
|
56
|
-
let text: string = ''
|
57
|
-
try {
|
58
|
-
text = (await response?.text()) ?? ''
|
59
|
-
} catch (e) {
|
60
|
-
console.error(e)
|
61
|
-
}
|
62
|
-
|
63
|
-
throw new Error(
|
64
|
-
`Organization delete, response is not ok, status: ${response?.status},${response?.statusText} ${text}`
|
65
|
-
)
|
66
|
-
}
|
67
|
-
const org = <OrganizationImpl>this.impl.get(id)
|
68
|
-
const index = this.impl.organizations.indexOf(org)
|
69
|
-
if (index < 0) {
|
70
|
-
throw new Error('Organization delete, index is not found')
|
71
|
-
}
|
72
|
-
|
73
|
-
// remove organization from collection
|
74
|
-
this.impl.organizations.splice(index, 1)
|
75
|
-
|
76
|
-
// dispatch event, organization removed
|
77
|
-
this.impl.dispatch({
|
78
|
-
type: OrganizationEvent.REMOVED,
|
79
|
-
data: org
|
80
|
-
})
|
81
|
-
|
82
|
-
// dispose organization
|
83
|
-
org.dispose()
|
84
|
-
}
|
85
|
-
|
86
|
-
async createOrganization(
|
87
|
-
name: string,
|
88
|
-
description: string
|
89
|
-
): Promise<OrganizationImpl> {
|
90
|
-
if (name === undefined || name === null) {
|
91
|
-
throw new Error('Organization create, name is undefined or null')
|
92
|
-
}
|
93
|
-
if (description === undefined || description === null) {
|
94
|
-
throw new Error('Organization create, description is undefined or null')
|
95
|
-
}
|
96
|
-
if (name.length === 0 || name.trim().length === 0) {
|
97
|
-
throw new Error('Organization create, name is empty')
|
98
|
-
}
|
99
|
-
const response = await this.resolve(RpcService)
|
100
|
-
?.requestBuilder('api/v1/Organizations')
|
101
|
-
.sendPost({
|
102
|
-
profile: {
|
103
|
-
name: name,
|
104
|
-
description: description
|
105
|
-
}
|
106
|
-
})
|
107
|
-
if (!response?.ok) {
|
108
|
-
throw new Error('Organization create, response is not ok')
|
109
|
-
}
|
110
|
-
const content = (await response.json())['organization'] as OrganizationDto
|
111
|
-
|
112
|
-
// create organization and init from content
|
113
|
-
const org = new OrganizationImpl(this, this.impl).initFrom(content, true)
|
114
|
-
|
115
|
-
// add organization to collection
|
116
|
-
this.impl.organizations.push(org)
|
117
|
-
|
118
|
-
// dispatch event, organization added
|
119
|
-
this.impl.dispatch({
|
120
|
-
type: OrganizationEvent.ADDED,
|
121
|
-
data: org
|
122
|
-
})
|
123
|
-
|
124
|
-
return org
|
19
|
+
organizations: OrganizationDto[],
|
20
|
+
settings?: UserSettings | null
|
21
|
+
): Promise<void> {
|
22
|
+
await this.impl.internalInitFrom(
|
23
|
+
adminInOrganization,
|
24
|
+
organizations,
|
25
|
+
settings
|
26
|
+
)
|
125
27
|
}
|
126
28
|
}
|
@@ -51,12 +51,12 @@ export class RequestBuilder {
|
|
51
51
|
public async sendPost(body?: BodyInit | null | object): Promise<Response> {
|
52
52
|
const url = this._url
|
53
53
|
url.search = this._searchParams.toString()
|
54
|
-
if (body !== undefined && body !== null && typeof body ===
|
54
|
+
if (body !== undefined && body !== null && typeof body === "object") {
|
55
55
|
body = JSON.stringify(body)
|
56
56
|
}
|
57
57
|
return await this._request(
|
58
58
|
new Request(url, {
|
59
|
-
method:
|
59
|
+
method: "POST",
|
60
60
|
headers: this._headers,
|
61
61
|
body
|
62
62
|
})
|
@@ -68,7 +68,7 @@ export class RequestBuilder {
|
|
68
68
|
url.search = this._searchParams.toString()
|
69
69
|
return await this._request(
|
70
70
|
new Request(url, {
|
71
|
-
method:
|
71
|
+
method: "GET",
|
72
72
|
headers: this._headers
|
73
73
|
})
|
74
74
|
)
|
@@ -79,7 +79,7 @@ export class RequestBuilder {
|
|
79
79
|
url.search = this._searchParams.toString()
|
80
80
|
return await this._request(
|
81
81
|
new Request(url, {
|
82
|
-
method:
|
82
|
+
method: "DELETE",
|
83
83
|
headers: this._headers
|
84
84
|
})
|
85
85
|
)
|
@@ -88,12 +88,12 @@ export class RequestBuilder {
|
|
88
88
|
public async sendPut(body?: BodyInit | null | object): Promise<Response> {
|
89
89
|
const url = this._url
|
90
90
|
url.search = this._searchParams.toString()
|
91
|
-
if (body !== undefined && body !== null && typeof body ===
|
91
|
+
if (body !== undefined && body !== null && typeof body === "object") {
|
92
92
|
body = JSON.stringify(body)
|
93
93
|
}
|
94
94
|
return await this._request(
|
95
95
|
new Request(url, {
|
96
|
-
method:
|
96
|
+
method: "PUT",
|
97
97
|
headers: this._headers,
|
98
98
|
body
|
99
99
|
})
|
@@ -0,0 +1,32 @@
|
|
1
|
+
export class ResponseUtils {
|
2
|
+
public static isOk(response?: Response | null): boolean {
|
3
|
+
return response !== undefined && response !== null && response.ok
|
4
|
+
}
|
5
|
+
|
6
|
+
public static isFail(response?: Response | null): boolean {
|
7
|
+
return !ResponseUtils.isOk(response)
|
8
|
+
}
|
9
|
+
|
10
|
+
public static async throwError(
|
11
|
+
message: string,
|
12
|
+
response: Response | undefined | null
|
13
|
+
): Promise<void> {
|
14
|
+
if (response === undefined) {
|
15
|
+
throw new Error(`${message}. Response is undefined`)
|
16
|
+
}
|
17
|
+
if (response === null) {
|
18
|
+
throw new Error(`${message}. Response is null`)
|
19
|
+
}
|
20
|
+
let errorBody: string = ""
|
21
|
+
if (response) {
|
22
|
+
try {
|
23
|
+
errorBody = (await response.text()) ?? ""
|
24
|
+
} catch (e) {
|
25
|
+
console.error(e)
|
26
|
+
}
|
27
|
+
}
|
28
|
+
throw new Error(
|
29
|
+
`${message}. Response fail. Status: ${response?.status},${response?.statusText}, body: ${errorBody}`
|
30
|
+
)
|
31
|
+
}
|
32
|
+
}
|
@@ -1,6 +1,6 @@
|
|
1
|
-
import { Service, type ServiceContext } from
|
2
|
-
import { MiddlewareService } from
|
3
|
-
import { RequestBuilder } from
|
1
|
+
import { Service, type ServiceContext } from "./service"
|
2
|
+
import { MiddlewareService } from "./middlewareService"
|
3
|
+
import { RequestBuilder } from "./requestBuilder"
|
4
4
|
|
5
5
|
/**
|
6
6
|
* Options for the RpcService.
|
@@ -55,10 +55,10 @@ export class RpcService extends Service {
|
|
55
55
|
if (this.options !== undefined && this.options.urlBuilder !== undefined) {
|
56
56
|
return this.options.urlBuilder(path)
|
57
57
|
}
|
58
|
-
if (this.host.endsWith(
|
58
|
+
if (this.host.endsWith("/") && path.startsWith("/")) {
|
59
59
|
return new URL(`${this.host}${path.slice(1)}`)
|
60
60
|
}
|
61
|
-
if (!this.host.endsWith(
|
61
|
+
if (!this.host.endsWith("/") && !path.startsWith("/")) {
|
62
62
|
return new URL(`${this.host}/${path}`)
|
63
63
|
}
|
64
64
|
return new URL(`${this.host}${path}`)
|
package/src/services/service.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
import { type Context } from
|
2
|
-
import { type Constructor } from
|
3
|
-
import { type DisposableContainer, type Lifetime } from
|
1
|
+
import { type Context } from "../context"
|
2
|
+
import { type Constructor } from "../internal/registry"
|
3
|
+
import { type DisposableContainer, type Lifetime } from "../disposable"
|
4
4
|
|
5
5
|
export class ServiceContext {
|
6
6
|
constructor(
|
@@ -1,62 +1,10 @@
|
|
1
|
-
import { Service } from
|
2
|
-
import { RpcService } from
|
3
|
-
import {
|
4
|
-
import { UserInfoResponse } from
|
5
|
-
import { OrganizationService } from
|
6
|
-
|
7
|
-
|
8
|
-
private content?: UserInfoResponse
|
9
|
-
|
10
|
-
get id(): string {
|
11
|
-
if (this.content) {
|
12
|
-
return this.content.user.id
|
13
|
-
}
|
14
|
-
throw new Error('The profile is not loaded.')
|
15
|
-
}
|
16
|
-
|
17
|
-
get name(): string {
|
18
|
-
if (this.content) {
|
19
|
-
return this.content.user.profile.name
|
20
|
-
}
|
21
|
-
throw new Error('The profile is not loaded.')
|
22
|
-
}
|
23
|
-
|
24
|
-
get email(): string {
|
25
|
-
if (this.content) {
|
26
|
-
return this.content.user.profile.email
|
27
|
-
}
|
28
|
-
throw new Error('The profile is not loaded.')
|
29
|
-
}
|
30
|
-
|
31
|
-
get isDeleted(): boolean {
|
32
|
-
if (this.content) {
|
33
|
-
return this.content.user.isDeleted
|
34
|
-
}
|
35
|
-
throw new Error('The profile is not loaded.')
|
36
|
-
}
|
37
|
-
|
38
|
-
get createdAt(): Date {
|
39
|
-
if (this.content) {
|
40
|
-
return new Date(this.content.user.created_at)
|
41
|
-
}
|
42
|
-
throw new Error('The profile is not loaded.')
|
43
|
-
}
|
44
|
-
|
45
|
-
get modifiedAt(): Date {
|
46
|
-
if (this.content) {
|
47
|
-
return new Date(this.content.user.modified_at)
|
48
|
-
}
|
49
|
-
throw new Error('The profile is not loaded.')
|
50
|
-
}
|
51
|
-
|
52
|
-
initFrom(content: UserInfoResponse) {
|
53
|
-
this.content = content
|
54
|
-
this.dispatch({
|
55
|
-
type: UserEvent.CHANGED,
|
56
|
-
data: this
|
57
|
-
})
|
58
|
-
}
|
59
|
-
}
|
1
|
+
import { Service } from "./service"
|
2
|
+
import { RpcService } from "./rpcService"
|
3
|
+
import { UserProfile } from "../storages/userProfile"
|
4
|
+
import { UserInfoResponse } from "../dto/userInfoResponse"
|
5
|
+
import { OrganizationService } from "./organizationService"
|
6
|
+
import { UserProfileImpl } from "../storages/userProfile.impl"
|
7
|
+
import { ResponseUtils } from "./responseUtils"
|
60
8
|
|
61
9
|
export class UserProfileService extends Service {
|
62
10
|
private readonly impl: UserProfileImpl = new UserProfileImpl()
|
@@ -65,22 +13,26 @@ export class UserProfileService extends Service {
|
|
65
13
|
return this.impl
|
66
14
|
}
|
67
15
|
|
68
|
-
async fetch(
|
16
|
+
async fetch() {
|
69
17
|
const rpc = this.resolve(RpcService) as RpcService
|
70
|
-
const response = await rpc.requestBuilder(
|
71
|
-
if (
|
72
|
-
|
18
|
+
const response = await rpc.requestBuilder("api/v1/Users/self2").sendGet()
|
19
|
+
if (ResponseUtils.isFail(response)) {
|
20
|
+
await ResponseUtils.throwError("Failed to fetch user profile", response)
|
73
21
|
}
|
74
22
|
const content = (await response.json()) as UserInfoResponse
|
23
|
+
|
24
|
+
// init user profile from the server's response
|
75
25
|
this.impl.initFrom(content)
|
76
26
|
|
77
27
|
const organizationService = this.resolve(
|
78
28
|
OrganizationService
|
79
29
|
) as OrganizationService
|
80
|
-
|
81
|
-
|
30
|
+
|
31
|
+
// init organization service from user profile
|
32
|
+
await organizationService.initFrom(
|
82
33
|
content.adminInOrganization,
|
83
|
-
content.organizations
|
34
|
+
content.organizations,
|
35
|
+
content.user.settings
|
84
36
|
)
|
85
37
|
}
|
86
38
|
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import { EventDispatcher } from "../events"
|
2
|
+
|
3
|
+
export type ChatId = string
|
4
|
+
|
5
|
+
export enum ChatsEvent {
|
6
|
+
ADDED = "added",
|
7
|
+
REMOVED = "removed"
|
8
|
+
}
|
9
|
+
|
10
|
+
export enum ChatAnswer {
|
11
|
+
SHORT = "short",
|
12
|
+
LONG = "long"
|
13
|
+
}
|
14
|
+
|
15
|
+
export abstract class Chat {
|
16
|
+
/**
|
17
|
+
* Chat id.
|
18
|
+
*/
|
19
|
+
abstract get id(): ChatId
|
20
|
+
|
21
|
+
/**
|
22
|
+
* Chat name.
|
23
|
+
*/
|
24
|
+
abstract get name(): string
|
25
|
+
|
26
|
+
abstract question(message: string, answer?: ChatAnswer): Promise<void>
|
27
|
+
}
|
28
|
+
|
29
|
+
/**
|
30
|
+
* Chats storage.
|
31
|
+
*/
|
32
|
+
export abstract class Chats extends EventDispatcher<ChatsEvent, Chat> {
|
33
|
+
/**
|
34
|
+
* Create new chat.
|
35
|
+
*/
|
36
|
+
abstract create(): Promise<Chat>
|
37
|
+
}
|
@@ -0,0 +1,68 @@
|
|
1
|
+
import { Context } from "../context"
|
2
|
+
import { Disposable } from "../disposable"
|
3
|
+
import { FileDto, FileProgressDto } from "../dto/workspacesResponse"
|
4
|
+
import { RpcService } from "../services/rpcService"
|
5
|
+
import { File } from "./files"
|
6
|
+
import { ResponseUtils } from "../services/responseUtils"
|
7
|
+
|
8
|
+
export class FileImpl extends File implements Disposable {
|
9
|
+
private _isDisposed: boolean = false
|
10
|
+
private _content?: FileDto
|
11
|
+
|
12
|
+
constructor(private readonly context: Context) {
|
13
|
+
super()
|
14
|
+
}
|
15
|
+
|
16
|
+
public initFrom(file: FileDto): File {
|
17
|
+
this._content = file
|
18
|
+
|
19
|
+
return this
|
20
|
+
}
|
21
|
+
|
22
|
+
get isDisposed(): boolean {
|
23
|
+
return this._isDisposed
|
24
|
+
}
|
25
|
+
|
26
|
+
dispose(): void {
|
27
|
+
this._isDisposed = true
|
28
|
+
}
|
29
|
+
|
30
|
+
get id(): string {
|
31
|
+
return <string>this._content?.id
|
32
|
+
}
|
33
|
+
|
34
|
+
get name(): string {
|
35
|
+
return <string>this._content?.id
|
36
|
+
}
|
37
|
+
|
38
|
+
async url(): Promise<string> {
|
39
|
+
const response = await this.context
|
40
|
+
.resolve(RpcService)
|
41
|
+
?.requestBuilder("api/v1/Files/url")
|
42
|
+
.searchParam("id", this.id)
|
43
|
+
.sendGet()
|
44
|
+
|
45
|
+
if (ResponseUtils.isFail(response)) {
|
46
|
+
await ResponseUtils.throwError(
|
47
|
+
`Failed to get file ${this.id} url`,
|
48
|
+
response
|
49
|
+
)
|
50
|
+
}
|
51
|
+
|
52
|
+
return (await response!.json()).url
|
53
|
+
}
|
54
|
+
|
55
|
+
async status(): Promise<FileProgressDto> {
|
56
|
+
const response = await this.context
|
57
|
+
.resolve(RpcService)
|
58
|
+
?.requestBuilder("api/v1/Files/url")
|
59
|
+
.searchParam("id", this.id)
|
60
|
+
.sendGet()
|
61
|
+
|
62
|
+
if (ResponseUtils.isFail(response)) {
|
63
|
+
await ResponseUtils.throwError(`Failed to get file ${this.id}`, response)
|
64
|
+
}
|
65
|
+
|
66
|
+
return (await response!.json()).progress as FileProgressDto
|
67
|
+
}
|
68
|
+
}
|
@@ -0,0 +1,192 @@
|
|
1
|
+
import { Context } from "../context"
|
2
|
+
import { Disposable } from "../disposable"
|
3
|
+
import { FileDto, FileListResponse } from "../dto/workspacesResponse"
|
4
|
+
import { OrganizationService } from "../services/organizationService"
|
5
|
+
import { RpcService } from "../services/rpcService"
|
6
|
+
import { FileImpl } from "./file.impl"
|
7
|
+
import { File, Files, FilesEvent, FilesList as FilesPage } from "./files"
|
8
|
+
import { WorkspaceImpl } from "./workspace.impl"
|
9
|
+
import { ResponseUtils } from "../services/responseUtils"
|
10
|
+
|
11
|
+
export class FilesPageImpl extends FilesPage implements Disposable {
|
12
|
+
private _isDisposed: boolean = false
|
13
|
+
|
14
|
+
public files: File[] = []
|
15
|
+
public total: number = 0
|
16
|
+
public filesPerPage: number = 0
|
17
|
+
public page: number = 0
|
18
|
+
|
19
|
+
get pages(): number {
|
20
|
+
return Math.ceil(Math.max(this.total / this.filesPerPage, 1.0))
|
21
|
+
}
|
22
|
+
|
23
|
+
get isDisposed(): boolean {
|
24
|
+
return this._isDisposed
|
25
|
+
}
|
26
|
+
|
27
|
+
dispose(): void {
|
28
|
+
this._isDisposed = true
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
export class FilesImpl extends Files {
|
33
|
+
constructor(
|
34
|
+
private readonly workspace: WorkspaceImpl,
|
35
|
+
private readonly context: Context
|
36
|
+
) {
|
37
|
+
super()
|
38
|
+
}
|
39
|
+
|
40
|
+
// Object used as files page data, returned by "query"
|
41
|
+
public filesList?: FilesPage
|
42
|
+
|
43
|
+
async upload(file: any): Promise<File> {
|
44
|
+
return await this.internalUpload(file)
|
45
|
+
}
|
46
|
+
|
47
|
+
async delete(id: string): Promise<void> {
|
48
|
+
return await this.internalDeleteFile(id)
|
49
|
+
}
|
50
|
+
|
51
|
+
async query(query: string, page: number, limit: number): Promise<FilesPage> {
|
52
|
+
return await this.internalQuery(query, page, limit)
|
53
|
+
}
|
54
|
+
|
55
|
+
//----------------------------------------------------------------------------
|
56
|
+
// INTERNALS
|
57
|
+
//----------------------------------------------------------------------------
|
58
|
+
|
59
|
+
/**
|
60
|
+
* Delete organization.
|
61
|
+
* @param id
|
62
|
+
*/
|
63
|
+
async internalDeleteFile(id: string): Promise<void> {
|
64
|
+
if (id === undefined || id === null) {
|
65
|
+
throw new Error("File delete, id is undefined or null")
|
66
|
+
}
|
67
|
+
if (id.length === 0 || id.trim().length === 0) {
|
68
|
+
throw new Error("File delete, id is empty")
|
69
|
+
}
|
70
|
+
|
71
|
+
const response = await this.context
|
72
|
+
.resolve(RpcService)
|
73
|
+
?.requestBuilder("/api/v1/Files")
|
74
|
+
.searchParam("id", id)
|
75
|
+
.sendDelete()
|
76
|
+
if (ResponseUtils.isFail(response)) {
|
77
|
+
await ResponseUtils.throwError(`File ${id} delete, failed`, response)
|
78
|
+
}
|
79
|
+
const file = <FileImpl>this.filesList!.files.find(f => f.id === id)
|
80
|
+
const index = this.filesList!.files.indexOf(file)
|
81
|
+
if (index < 0) {
|
82
|
+
throw new Error("Organization delete, index is not found")
|
83
|
+
}
|
84
|
+
|
85
|
+
// remove file from collection
|
86
|
+
this.filesList!.files.splice(index, 1)
|
87
|
+
|
88
|
+
// dispatch event, file removed
|
89
|
+
this.dispatch({
|
90
|
+
type: FilesEvent.REMOVED,
|
91
|
+
data: file
|
92
|
+
})
|
93
|
+
|
94
|
+
// dispose file
|
95
|
+
file.dispose()
|
96
|
+
}
|
97
|
+
|
98
|
+
async internalQuery(
|
99
|
+
query: string,
|
100
|
+
page: number,
|
101
|
+
limit: number
|
102
|
+
): Promise<FilesPage> {
|
103
|
+
if (page === undefined || page === null) {
|
104
|
+
throw new Error("File fetch, page is undefined or null")
|
105
|
+
}
|
106
|
+
if (limit === undefined || limit === null) {
|
107
|
+
throw new Error("File fetch, limit is undefined or null")
|
108
|
+
}
|
109
|
+
if (limit === 0) {
|
110
|
+
throw new Error("File fetch, limit is 0")
|
111
|
+
}
|
112
|
+
|
113
|
+
const orgService = this.context.resolve(OrganizationService)
|
114
|
+
|
115
|
+
if (orgService === undefined) {
|
116
|
+
throw new Error("File fetch, organization service undefined")
|
117
|
+
}
|
118
|
+
|
119
|
+
const response = await this.context
|
120
|
+
.resolve(RpcService)
|
121
|
+
?.requestBuilder("api/v1/Files/list")
|
122
|
+
|
123
|
+
.searchParam("workspaceId", this.workspace.id)
|
124
|
+
.searchParam("organizationId", orgService.organizations.current)
|
125
|
+
.searchParam("query", query)
|
126
|
+
.searchParam("page", page.toString())
|
127
|
+
.searchParam("limit", limit.toString())
|
128
|
+
.sendGet()
|
129
|
+
|
130
|
+
if (ResponseUtils.isFail(response)) {
|
131
|
+
await ResponseUtils.throwError(
|
132
|
+
`Files fetch query:${query}, page:${page}, limit:${limit}, failed`,
|
133
|
+
response
|
134
|
+
)
|
135
|
+
}
|
136
|
+
|
137
|
+
const files = (await response!.json()) as FileListResponse
|
138
|
+
|
139
|
+
const filesList = new FilesPageImpl()
|
140
|
+
filesList.total = files.totalFilesCount
|
141
|
+
filesList.filesPerPage = files.filesPerPage
|
142
|
+
filesList.page = page
|
143
|
+
for (const fl of files.files) {
|
144
|
+
const file = new FileImpl(this.context).initFrom(fl)
|
145
|
+
|
146
|
+
filesList.files.push(file)
|
147
|
+
|
148
|
+
this.dispatch({
|
149
|
+
type: FilesEvent.ADDED,
|
150
|
+
data: file
|
151
|
+
})
|
152
|
+
}
|
153
|
+
|
154
|
+
this.filesList = filesList
|
155
|
+
|
156
|
+
return filesList
|
157
|
+
}
|
158
|
+
|
159
|
+
async internalUpload(file: any): Promise<File> {
|
160
|
+
const orgService = this.context.resolve(OrganizationService)
|
161
|
+
|
162
|
+
if (orgService === undefined) {
|
163
|
+
throw new Error("File load, organization service undefined")
|
164
|
+
}
|
165
|
+
|
166
|
+
const form = new FormData()
|
167
|
+
form.append("organizationId", orgService.organizations.current)
|
168
|
+
form.append("workspaceId", this.workspace.id)
|
169
|
+
form.append("name", file.name)
|
170
|
+
form.append("file", file, file.name)
|
171
|
+
|
172
|
+
const response = await this.context
|
173
|
+
.resolve(RpcService)
|
174
|
+
?.requestBuilder("api/v1/Files")
|
175
|
+
.sendPost(form)
|
176
|
+
if (ResponseUtils.isFail(response)) {
|
177
|
+
await ResponseUtils.throwError(`File upload ${file}`, response)
|
178
|
+
}
|
179
|
+
const result = (await response!.json()).file as FileDto
|
180
|
+
|
181
|
+
const fileImpl = new FileImpl(this.context).initFrom(result)
|
182
|
+
|
183
|
+
this.filesList!.files.push(file)
|
184
|
+
|
185
|
+
this.dispatch({
|
186
|
+
type: FilesEvent.ADDED,
|
187
|
+
data: file
|
188
|
+
})
|
189
|
+
|
190
|
+
return fileImpl
|
191
|
+
}
|
192
|
+
}
|