Implemented some more functions for the Core RESTful API
parent
445db26f33
commit
79af35336c
|
|
@ -1,3 +1,25 @@
|
||||||
|
/**
|
||||||
|
* A list view contains an array of objects and some data about the list.
|
||||||
|
*/
|
||||||
|
export interface ListView<T> {
|
||||||
|
/**
|
||||||
|
* The list of objects
|
||||||
|
*/
|
||||||
|
list: T[],
|
||||||
|
/**
|
||||||
|
* The number of elements for the query.
|
||||||
|
*/
|
||||||
|
count: number,
|
||||||
|
/**
|
||||||
|
* Items per page
|
||||||
|
*/
|
||||||
|
limit: number,
|
||||||
|
/**
|
||||||
|
* The first item shown
|
||||||
|
*/
|
||||||
|
offset: number,
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Properties of the type `LocalizedString` are used in several entities
|
* Properties of the type `LocalizedString` are used in several entities
|
||||||
* returned by various of the endpoints the RESTful API of LibreCCM.
|
* returned by various of the endpoints the RESTful API of LibreCCM.
|
||||||
|
|
@ -7,3 +29,4 @@
|
||||||
export interface LocalizedString {
|
export interface LocalizedString {
|
||||||
values: Record<string, string>
|
values: Record<string, string>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,15 @@
|
||||||
import {
|
import {
|
||||||
ApiResponse,
|
ApiResponse,
|
||||||
LibreCcmApiClient,
|
LibreCcmApiClient,
|
||||||
|
ListView,
|
||||||
} from "@libreccm/ccm-apiclient-commons";
|
} from "@libreccm/ccm-apiclient-commons";
|
||||||
|
|
||||||
import { Category, buildCategoryFromRecord } from "../entities/categorization";
|
import {
|
||||||
|
Category,
|
||||||
|
Categorization,
|
||||||
|
buildCategoryFromRecord,
|
||||||
|
buildCategorizationFromRecord,
|
||||||
|
} from "../entities/categorization";
|
||||||
import * as Constants from "../constants";
|
import * as Constants from "../constants";
|
||||||
|
|
||||||
export class CategorizationApiClient {
|
export class CategorizationApiClient {
|
||||||
|
|
@ -69,7 +75,7 @@ export class CategorizationApiClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateCategoryByDomainAndPath(
|
async updateCategoryOfDomain(
|
||||||
domain: string,
|
domain: string,
|
||||||
path: string,
|
path: string,
|
||||||
category: Category
|
category: Category
|
||||||
|
|
@ -91,7 +97,7 @@ export class CategorizationApiClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateCategoryById(
|
async updateCategoryWithId(
|
||||||
categoryId: number,
|
categoryId: number,
|
||||||
category: Category
|
category: Category
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
|
@ -112,7 +118,7 @@ export class CategorizationApiClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateCategoryByUuid(
|
async updateCategoryWithUuid(
|
||||||
uuid: string,
|
uuid: string,
|
||||||
category: Category
|
category: Category
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
|
@ -133,10 +139,7 @@ export class CategorizationApiClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteCategoryByDomainAndPath(
|
async deleteCategoryOfDomain(domain: string, path: string): Promise<void> {
|
||||||
domain: string,
|
|
||||||
path: string
|
|
||||||
): Promise<void> {
|
|
||||||
try {
|
try {
|
||||||
const response: ApiResponse = await this.#apiClient.delete(
|
const response: ApiResponse = await this.#apiClient.delete(
|
||||||
`${this.#CATEGORIES_API_PREFIX}/${domain}/${path}`
|
`${this.#CATEGORIES_API_PREFIX}/${domain}/${path}`
|
||||||
|
|
@ -153,7 +156,7 @@ export class CategorizationApiClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteCategoryById(categoryId: number): Promise<void> {
|
async deleteCategoryWithId(categoryId: number): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const response: ApiResponse = await this.#apiClient.delete(
|
const response: ApiResponse = await this.#apiClient.delete(
|
||||||
`${this.#CATEGORIES_API_PREFIX}/ID-${categoryId}`
|
`${this.#CATEGORIES_API_PREFIX}/ID-${categoryId}`
|
||||||
|
|
@ -170,12 +173,10 @@ export class CategorizationApiClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteCategoryByUuid(
|
async deleteCategoryWithUuid(uuid: string): Promise<void> {
|
||||||
uuid: string,
|
|
||||||
): Promise<void> {
|
|
||||||
try {
|
try {
|
||||||
const response: ApiResponse = await this.#apiClient.delete(
|
const response: ApiResponse = await this.#apiClient.delete(
|
||||||
`${this.#CATEGORIES_API_PREFIX}/UUID-${uuid}`,
|
`${this.#CATEGORIES_API_PREFIX}/UUID-${uuid}`
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
|
|
@ -188,4 +189,238 @@ export class CategorizationApiClient {
|
||||||
throw `Failed to delete category with UUID ${uuid}: ${err}`;
|
throw `Failed to delete category with UUID ${uuid}: ${err}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getSubCategoriesByDomainAndPath(
|
||||||
|
domain: string,
|
||||||
|
path: string,
|
||||||
|
limit = 20,
|
||||||
|
offset = 0
|
||||||
|
): Promise<ListView<Category>> {
|
||||||
|
try {
|
||||||
|
const response: ApiResponse = await this.#apiClient.get(
|
||||||
|
`${
|
||||||
|
this.#CATEGORIES_API_PREFIX
|
||||||
|
}/${domain}/${path}?limit=${limit}&offset=${offset}`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const result: Record<string, unknown> = await response.json();
|
||||||
|
const list: Record<string, unknown>[] = result.list as Record<
|
||||||
|
string,
|
||||||
|
unknown
|
||||||
|
>[];
|
||||||
|
const categories: Category[] = list.map((record) =>
|
||||||
|
buildCategoryFromRecord(record)
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
list: categories,
|
||||||
|
count: result.count as number,
|
||||||
|
limit: result.limit as number,
|
||||||
|
offset: result.offset as number,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
throw `Failed to get subcategories of category ${path} of
|
||||||
|
domain ${domain}: ${response.status} ${response.statusText}`;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
throw `Failed to get subcategories of category ${path} of
|
||||||
|
domain ${domain}: ${err}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getSubCategoriesById(
|
||||||
|
categoryId: number,
|
||||||
|
limit = 20,
|
||||||
|
offset = 0
|
||||||
|
): Promise<ListView<Category>> {
|
||||||
|
try {
|
||||||
|
const response: ApiResponse = await this.#apiClient.get(
|
||||||
|
`${
|
||||||
|
this.#CATEGORIES_API_PREFIX
|
||||||
|
}/ID-${categoryId}?limit=${limit}&offset=${offset}`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const result: Record<string, unknown> = await response.json();
|
||||||
|
const list: Record<string, unknown>[] = result.list as Record<
|
||||||
|
string,
|
||||||
|
unknown
|
||||||
|
>[];
|
||||||
|
const categories: Category[] = list.map((record) =>
|
||||||
|
buildCategoryFromRecord(record)
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
list: categories,
|
||||||
|
count: result.count as number,
|
||||||
|
limit: result.limit as number,
|
||||||
|
offset: result.offset as number,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
throw `Failed to get subcategories of category with ID
|
||||||
|
${categoryId}: ${response.status} ${response.statusText}`;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
throw `Failed to get subcategories of category with
|
||||||
|
ID ${categoryId}: ${err}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getSubCategoriesByUuid(
|
||||||
|
uuid: string,
|
||||||
|
limit = 20,
|
||||||
|
offset = 0
|
||||||
|
): Promise<ListView<Category>> {
|
||||||
|
try {
|
||||||
|
const response: ApiResponse = await this.#apiClient.get(
|
||||||
|
`${
|
||||||
|
this.#CATEGORIES_API_PREFIX
|
||||||
|
}/UUID-${uuid}?limit=${limit}&offset=${offset}`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const result: Record<string, unknown> = await response.json();
|
||||||
|
const list: Record<string, unknown>[] = result.list as Record<
|
||||||
|
string,
|
||||||
|
unknown
|
||||||
|
>[];
|
||||||
|
const categories: Category[] = list.map((record) =>
|
||||||
|
buildCategoryFromRecord(record)
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
list: categories,
|
||||||
|
count: result.count as number,
|
||||||
|
limit: result.limit as number,
|
||||||
|
offset: result.offset as number,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
throw `Failed to get subcategories of category with UUID
|
||||||
|
${uuid}: ${response.status} ${response.statusText}`;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
throw `Failed to get subcategories of category with
|
||||||
|
UUID ${uuid}: ${err}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new subcategory to category
|
||||||
|
*
|
||||||
|
* @param domain
|
||||||
|
* @param path
|
||||||
|
* @param category
|
||||||
|
*
|
||||||
|
* @returns A Promise which resolves to the full path (including domain)
|
||||||
|
* of the new subcategory.
|
||||||
|
*/
|
||||||
|
async addSubCategoryToCategoryOfDomain(
|
||||||
|
domain: string,
|
||||||
|
path: string,
|
||||||
|
category: Category
|
||||||
|
): Promise<string> {
|
||||||
|
try {
|
||||||
|
const response: ApiResponse = await this.#apiClient.post(
|
||||||
|
`${this.#CATEGORIES_API_PREFIX}/${domain}/${path}`,
|
||||||
|
JSON.stringify(category)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const result: string = await response.text();
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
throw `Failed to add new subcategory to category ${path} of
|
||||||
|
domain ${domain}: ${response.status} ${response.statusText}`;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
throw `Failed to add new subcategory to category ${path} of
|
||||||
|
domain ${domain}: ${err}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async addSubCategoryToWithId(
|
||||||
|
categoryId: number,
|
||||||
|
category: Category
|
||||||
|
): Promise<string> {
|
||||||
|
try {
|
||||||
|
const response: ApiResponse = await this.#apiClient.post(
|
||||||
|
`${this.#CATEGORIES_API_PREFIX}/ID-${categoryId}`,
|
||||||
|
JSON.stringify(category)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const result: string = await response.text();
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
throw `Failed to add new subcategory to category with
|
||||||
|
ID ${categoryId}: ${response.status} ${response.statusText}`;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
throw `Failed to add new subcategory to category with
|
||||||
|
ID ${categoryId}: ${err}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async addSubCategoryToWithUuid(
|
||||||
|
uuid: string,
|
||||||
|
category: Category
|
||||||
|
): Promise<string> {
|
||||||
|
try {
|
||||||
|
const response: ApiResponse = await this.#apiClient.post(
|
||||||
|
`${this.#CATEGORIES_API_PREFIX}/UUID-${uuid}`,
|
||||||
|
JSON.stringify(category)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const result: string = await response.text();
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
throw `Failed to add new subcategory to category with
|
||||||
|
UUID ${uuid}: ${response.status} ${response.statusText}`;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
throw `Failed to add new subcategory to category with
|
||||||
|
UUID ${uuid}: ${err}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getObjectsInCategoryOfDomain(
|
||||||
|
domain: string,
|
||||||
|
path: string,
|
||||||
|
limit = 20,
|
||||||
|
offset = 0
|
||||||
|
): Promise<ListView<Categorization>> {
|
||||||
|
try {
|
||||||
|
const response: ApiResponse = await this.#apiClient.get(
|
||||||
|
`${
|
||||||
|
this.#CATEGORIES_API_PREFIX
|
||||||
|
}/$domain/${path}/objects?limit=${limit}&offset=${offset}`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const result: Record<string, unknown> = await response.json();
|
||||||
|
const list: Record<string, unknown>[] = result.list as Record<
|
||||||
|
string,
|
||||||
|
unknown
|
||||||
|
>[];
|
||||||
|
const objects: Categorization[] = list.map((record) =>
|
||||||
|
buildCategorizationFromRecord(record)
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
list: objects,
|
||||||
|
count: result.count as number,
|
||||||
|
limit: result.limit as number,
|
||||||
|
offset: result.offset as number
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw `Failed to get objects in category ${path} of
|
||||||
|
domain ${domain}: ${response.status} ${response.statusText}`;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
throw `Failed to get objects in category ${path} of
|
||||||
|
domain ${domain}: ${err}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import {
|
||||||
LocalizedString,
|
LocalizedString,
|
||||||
assertProperties,
|
assertProperties,
|
||||||
} from "@libreccm/ccm-apiclient-commons";
|
} from "@libreccm/ccm-apiclient-commons";
|
||||||
|
import { CcmObjectId } from "./core";
|
||||||
|
|
||||||
export interface AssociatedCategory {
|
export interface AssociatedCategory {
|
||||||
name: string;
|
name: string;
|
||||||
|
|
@ -22,6 +23,16 @@ export interface Category {
|
||||||
categoryOrder: number;
|
categoryOrder: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Categorization {
|
||||||
|
categorizationId: number;
|
||||||
|
uuid: string;
|
||||||
|
categorizedObject: CcmObjectId;
|
||||||
|
indexObject: boolean;
|
||||||
|
categoryOrder: number;
|
||||||
|
objectOrder: number;
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
|
|
||||||
export function buildCategoryFromRecord(
|
export function buildCategoryFromRecord(
|
||||||
record: Record<string, unknown>
|
record: Record<string, unknown>
|
||||||
): Category {
|
): Category {
|
||||||
|
|
@ -55,3 +66,27 @@ export function buildCategoryFromRecord(
|
||||||
categoryOrder: record.categoryOrder as number,
|
categoryOrder: record.categoryOrder as number,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function buildCategorizationFromRecord(
|
||||||
|
record: Record<string, unknown>
|
||||||
|
): Categorization {
|
||||||
|
assertProperties(record, [
|
||||||
|
"categorizationId",
|
||||||
|
"uuid",
|
||||||
|
"categorizedObject",
|
||||||
|
"indexObject",
|
||||||
|
"categoryOrder",
|
||||||
|
"objectOrder",
|
||||||
|
"type"
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
categorizationId: record.categorizationId as number,
|
||||||
|
uuid: record.uuid as string,
|
||||||
|
categorizedObject: record.categorizedObject as CcmObjectId,
|
||||||
|
indexObject: record.indexObject as boolean,
|
||||||
|
categoryOrder: record.categoryOrder as number,
|
||||||
|
objectOrder: record.objectOrder as number,
|
||||||
|
type: record.type as string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
/**
|
||||||
|
* Basic data about an `CcmObject`.
|
||||||
|
*/
|
||||||
|
export interface CcmObjectId {
|
||||||
|
objectId: number,
|
||||||
|
uuid: string,
|
||||||
|
displayName: string
|
||||||
|
}
|
||||||
|
|
@ -266,7 +266,7 @@
|
||||||
"schema" : {
|
"schema" : {
|
||||||
"type" : "integer",
|
"type" : "integer",
|
||||||
"format" : "int32",
|
"format" : "int32",
|
||||||
"default" : 20
|
"default" : 0
|
||||||
}
|
}
|
||||||
} ],
|
} ],
|
||||||
"responses" : {
|
"responses" : {
|
||||||
|
|
@ -333,14 +333,16 @@
|
||||||
"in" : "query",
|
"in" : "query",
|
||||||
"schema" : {
|
"schema" : {
|
||||||
"type" : "integer",
|
"type" : "integer",
|
||||||
"format" : "int32"
|
"format" : "int32",
|
||||||
|
"default" : 20
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
"name" : "offset",
|
"name" : "offset",
|
||||||
"in" : "query",
|
"in" : "query",
|
||||||
"schema" : {
|
"schema" : {
|
||||||
"type" : "integer",
|
"type" : "integer",
|
||||||
"format" : "int32"
|
"format" : "int32",
|
||||||
|
"default" : 0
|
||||||
}
|
}
|
||||||
} ],
|
} ],
|
||||||
"responses" : {
|
"responses" : {
|
||||||
|
|
@ -379,14 +381,16 @@
|
||||||
"in" : "query",
|
"in" : "query",
|
||||||
"schema" : {
|
"schema" : {
|
||||||
"type" : "integer",
|
"type" : "integer",
|
||||||
"format" : "int32"
|
"format" : "int32",
|
||||||
|
"default" : 20
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
"name" : "offset",
|
"name" : "offset",
|
||||||
"in" : "query",
|
"in" : "query",
|
||||||
"schema" : {
|
"schema" : {
|
||||||
"type" : "integer",
|
"type" : "integer",
|
||||||
"format" : "int32"
|
"format" : "int32",
|
||||||
|
"default" : 0
|
||||||
}
|
}
|
||||||
} ],
|
} ],
|
||||||
"responses" : {
|
"responses" : {
|
||||||
|
|
@ -454,14 +458,16 @@
|
||||||
"in" : "query",
|
"in" : "query",
|
||||||
"schema" : {
|
"schema" : {
|
||||||
"type" : "integer",
|
"type" : "integer",
|
||||||
"format" : "int32"
|
"format" : "int32",
|
||||||
|
"default" : 20
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
"name" : "offset",
|
"name" : "offset",
|
||||||
"in" : "query",
|
"in" : "query",
|
||||||
"schema" : {
|
"schema" : {
|
||||||
"type" : "integer",
|
"type" : "integer",
|
||||||
"format" : "int32"
|
"format" : "int32",
|
||||||
|
"default" : 0
|
||||||
}
|
}
|
||||||
} ],
|
} ],
|
||||||
"responses" : {
|
"responses" : {
|
||||||
|
|
@ -601,9 +607,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/api/admin/categories/UUID-{categoryId}/objects/objectIdentifier" : {
|
"/api/admin/categories/UUID-{categoryId}/objects/{objectIdentifier}" : {
|
||||||
"delete" : {
|
"delete" : {
|
||||||
"operationId" : "removeObjectsFromCategory",
|
"operationId" : "removeObjectFromCategory_2",
|
||||||
"parameters" : [ {
|
"parameters" : [ {
|
||||||
"name" : "categoryId",
|
"name" : "categoryId",
|
||||||
"in" : "path",
|
"in" : "path",
|
||||||
|
|
@ -678,7 +684,7 @@
|
||||||
"schema" : {
|
"schema" : {
|
||||||
"type" : "integer",
|
"type" : "integer",
|
||||||
"format" : "int32",
|
"format" : "int32",
|
||||||
"default" : 20
|
"default" : 0
|
||||||
}
|
}
|
||||||
} ],
|
} ],
|
||||||
"responses" : {
|
"responses" : {
|
||||||
|
|
@ -720,7 +726,7 @@
|
||||||
"schema" : {
|
"schema" : {
|
||||||
"type" : "integer",
|
"type" : "integer",
|
||||||
"format" : "int32",
|
"format" : "int32",
|
||||||
"default" : 20
|
"default" : 0
|
||||||
}
|
}
|
||||||
} ],
|
} ],
|
||||||
"responses" : {
|
"responses" : {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue