Implemented some more functions for the Core RESTful API

Jens Pelzetter 2020-07-24 20:42:49 +02:00
parent 445db26f33
commit 79af35336c
5 changed files with 332 additions and 25 deletions

View File

@ -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>
} }

View File

@ -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}`;
}
}
} }

View File

@ -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
}
}

View File

@ -0,0 +1,8 @@
/**
* Basic data about an `CcmObject`.
*/
export interface CcmObjectId {
objectId: number,
uuid: string,
displayName: string
}

View File

@ -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" : {