2020-10-20 21:50:53 +02:00
|
|
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
|
|
// See LICENSE.txt for license information.
|
2020-10-22 18:46:06 +02:00
|
|
|
import {IBlock, IMutableBlock} from './blocks/block'
|
2020-10-20 21:52:56 +02:00
|
|
|
import {Utils} from './utils'
|
2020-10-08 18:21:27 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// OctoClient is the client interface to the server APIs
|
|
|
|
//
|
|
|
|
class OctoClient {
|
2020-10-20 21:50:53 +02:00
|
|
|
serverUrl: string
|
|
|
|
|
|
|
|
constructor(serverUrl?: string) {
|
2020-10-22 00:03:12 +02:00
|
|
|
this.serverUrl = serverUrl || window.location.origin
|
2020-10-22 18:46:06 +02:00
|
|
|
Utils.log(`OctoClient serverUrl: ${this.serverUrl}`)
|
2020-10-20 21:50:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async getSubtree(rootId?: string): Promise<IBlock[]> {
|
2020-10-22 00:03:12 +02:00
|
|
|
const path = `/api/v1/blocks/${rootId}/subtree`
|
|
|
|
const response = await fetch(this.serverUrl + path)
|
|
|
|
const blocks = (await response.json() || []) as IMutableBlock[]
|
|
|
|
this.fixBlocks(blocks)
|
|
|
|
return blocks
|
2020-10-20 21:50:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async exportFullArchive(): Promise<IBlock[]> {
|
2020-10-20 21:52:56 +02:00
|
|
|
const path = '/api/v1/blocks/export'
|
2020-10-22 00:03:12 +02:00
|
|
|
const response = await fetch(this.serverUrl + path)
|
|
|
|
const blocks = (await response.json() || []) as IMutableBlock[]
|
|
|
|
this.fixBlocks(blocks)
|
|
|
|
return blocks
|
2020-10-20 21:50:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async importFullArchive(blocks: IBlock[]): Promise<Response> {
|
|
|
|
Utils.log(`importFullArchive: ${blocks.length} blocks(s)`)
|
|
|
|
blocks.forEach((block) => {
|
|
|
|
Utils.log(`\t ${block.type}, ${block.id}`)
|
2020-10-22 00:03:12 +02:00
|
|
|
})
|
2020-10-20 21:50:53 +02:00
|
|
|
const body = JSON.stringify(blocks)
|
|
|
|
return await fetch(this.serverUrl + '/api/v1/blocks/import', {
|
2020-10-22 00:03:12 +02:00
|
|
|
method: 'POST',
|
2020-10-20 21:50:53 +02:00
|
|
|
headers: {
|
|
|
|
Accept: 'application/json',
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
},
|
|
|
|
body,
|
2020-10-22 00:03:12 +02:00
|
|
|
})
|
2020-10-20 21:50:53 +02:00
|
|
|
}
|
|
|
|
|
2020-10-21 22:20:00 +02:00
|
|
|
async getBlocksWithParent(parentId: string, type?: string): Promise<IBlock[]> {
|
2020-10-20 21:50:53 +02:00
|
|
|
let path: string
|
2020-10-21 22:20:00 +02:00
|
|
|
if (type) {
|
2020-10-22 00:03:12 +02:00
|
|
|
path = `/api/v1/blocks?parent_id=${encodeURIComponent(parentId)}&type=${encodeURIComponent(type)}`
|
2020-10-20 21:50:53 +02:00
|
|
|
} else {
|
2020-10-22 00:03:12 +02:00
|
|
|
path = `/api/v1/blocks?parent_id=${encodeURIComponent(parentId)}`
|
2020-10-20 21:50:53 +02:00
|
|
|
}
|
2020-10-21 22:20:00 +02:00
|
|
|
return this.getBlocksWithPath(path)
|
|
|
|
}
|
|
|
|
|
|
|
|
async getBlocksWithType(type: string): Promise<IBlock[]> {
|
|
|
|
const path = `/api/v1/blocks?type=${encodeURIComponent(type)}`
|
|
|
|
return this.getBlocksWithPath(path)
|
|
|
|
}
|
2020-10-20 21:50:53 +02:00
|
|
|
|
2020-10-21 22:20:00 +02:00
|
|
|
private async getBlocksWithPath(path: string): Promise<IBlock[]> {
|
2020-10-22 00:03:12 +02:00
|
|
|
const response = await fetch(this.serverUrl + path)
|
2020-10-21 03:28:55 +02:00
|
|
|
const blocks = (await response.json() || []) as IMutableBlock[]
|
2020-10-20 21:50:53 +02:00
|
|
|
this.fixBlocks(blocks)
|
2020-10-22 00:03:12 +02:00
|
|
|
return blocks
|
2020-10-20 21:50:53 +02:00
|
|
|
}
|
|
|
|
|
2020-10-21 03:28:55 +02:00
|
|
|
fixBlocks(blocks: IMutableBlock[]): void {
|
2020-10-22 00:03:12 +02:00
|
|
|
if (!blocks) {
|
2020-10-20 21:50:53 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-10-22 00:03:12 +02:00
|
|
|
// TODO
|
2020-10-20 21:50:53 +02:00
|
|
|
for (const block of blocks) {
|
2020-10-22 00:03:12 +02:00
|
|
|
if (!block.fields) {
|
2020-10-20 21:50:53 +02:00
|
|
|
block.fields = {}
|
|
|
|
}
|
|
|
|
const o = block as any
|
|
|
|
if (o.cardProperties) {
|
|
|
|
block.fields.cardProperties = o.cardProperties; delete o.cardProperties
|
|
|
|
}
|
|
|
|
if (o.properties) {
|
|
|
|
block.fields.properties = o.properties; delete o.properties
|
|
|
|
}
|
|
|
|
if (o.icon) {
|
|
|
|
block.fields.icon = o.icon; delete o.icon
|
|
|
|
}
|
|
|
|
if (o.url) {
|
|
|
|
block.fields.url = o.url; delete o.url
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-21 03:28:55 +02:00
|
|
|
async updateBlock(block: IMutableBlock): Promise<Response> {
|
2020-10-20 21:50:53 +02:00
|
|
|
block.updateAt = Date.now()
|
|
|
|
return await this.insertBlocks([block])
|
|
|
|
}
|
|
|
|
|
2020-10-21 03:28:55 +02:00
|
|
|
async updateBlocks(blocks: IMutableBlock[]): Promise<Response> {
|
2020-10-20 21:50:53 +02:00
|
|
|
const now = Date.now()
|
|
|
|
blocks.forEach((block) => {
|
|
|
|
block.updateAt = now
|
2020-10-20 21:52:56 +02:00
|
|
|
})
|
2020-10-22 00:03:12 +02:00
|
|
|
return await this.insertBlocks(blocks)
|
2020-10-20 21:50:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async deleteBlock(blockId: string): Promise<Response> {
|
2020-10-22 18:46:06 +02:00
|
|
|
Utils.log(`deleteBlock: ${blockId}`)
|
2020-10-22 00:03:12 +02:00
|
|
|
return await fetch(this.serverUrl + `/api/v1/blocks/${encodeURIComponent(blockId)}`, {
|
2020-10-20 21:50:53 +02:00
|
|
|
method: 'DELETE',
|
|
|
|
headers: {
|
|
|
|
Accept: 'application/json',
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
async insertBlock(block: IBlock): Promise<Response> {
|
2020-10-22 00:03:12 +02:00
|
|
|
return this.insertBlocks([block])
|
2020-10-20 21:50:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async insertBlocks(blocks: IBlock[]): Promise<Response> {
|
2020-10-22 00:03:12 +02:00
|
|
|
Utils.log(`insertBlocks: ${blocks.length} blocks(s)`)
|
|
|
|
blocks.forEach((block) => {
|
|
|
|
Utils.log(`\t ${block.type}, ${block.id}`)
|
|
|
|
})
|
|
|
|
const body = JSON.stringify(blocks)
|
|
|
|
return await fetch(this.serverUrl + '/api/v1/blocks', {
|
2020-10-20 21:50:53 +02:00
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
2020-10-22 00:03:12 +02:00
|
|
|
Accept: 'application/json',
|
2020-10-20 21:50:53 +02:00
|
|
|
'Content-Type': 'application/json',
|
|
|
|
},
|
|
|
|
body,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns URL of uploaded file, or undefined on failure
|
|
|
|
async uploadFile(file: File): Promise<string | undefined> {
|
|
|
|
// IMPORTANT: We need to post the image as a form. The browser will convert this to a application/x-www-form-urlencoded POST
|
2020-10-22 00:03:12 +02:00
|
|
|
const formData = new FormData()
|
|
|
|
formData.append('file', file)
|
2020-10-20 21:50:53 +02:00
|
|
|
|
2020-10-22 00:03:12 +02:00
|
|
|
try {
|
2020-10-20 21:50:53 +02:00
|
|
|
const response = await fetch(this.serverUrl + '/api/v1/files', {
|
|
|
|
method: 'POST',
|
|
|
|
|
|
|
|
// TIPTIP: Leave out Content-Type here, it will be automatically set by the browser
|
|
|
|
headers: {
|
2020-10-22 00:03:12 +02:00
|
|
|
Accept: 'application/json',
|
2020-10-20 21:50:53 +02:00
|
|
|
},
|
|
|
|
body: formData,
|
2020-10-22 00:03:12 +02:00
|
|
|
})
|
2020-10-20 21:50:53 +02:00
|
|
|
if (response.status === 200) {
|
|
|
|
try {
|
2020-10-22 00:03:12 +02:00
|
|
|
const text = await response.text()
|
2020-10-20 21:50:53 +02:00
|
|
|
Utils.log(`uploadFile response: ${text}`)
|
2020-10-22 00:03:12 +02:00
|
|
|
const json = JSON.parse(text)
|
2020-10-20 21:50:53 +02:00
|
|
|
|
|
|
|
// const json = await response.json()
|
2020-10-22 00:03:12 +02:00
|
|
|
return json.url
|
|
|
|
} catch (e) {
|
|
|
|
Utils.logError(`uploadFile json ERROR: ${e}`)
|
2020-10-20 21:50:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (e) {
|
2020-10-22 00:03:12 +02:00
|
|
|
Utils.logError(`uploadFile ERROR: ${e}`)
|
2020-10-20 21:50:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return undefined
|
|
|
|
}
|
2020-10-08 18:21:27 +02:00
|
|
|
}
|
|
|
|
|
2020-10-15 16:57:43 +02:00
|
|
|
const client = new OctoClient()
|
|
|
|
|
|
|
|
export default client
|