Newer
Older
import { useClient } from "@/context/ClientContext";
import { CWFile, DataService, ImportProcess, Project, Recipe } from "@/types";
import {
BinariesParam,
ResultSet,
Transaction,
TransactionQueryScalarRef,
} from "@cubicweb/client";
import { useRouter } from "next/navigation";
export function useApiLogin() {
const client = useClient();
return (login: string, password: string) => client.login(login, password);
export function useApiLogout() {
const client = useClient();
await client.logout();
router.push("/login");
export function useApiDeleteProject() {
const client = useClient();
const rql = "DELETE ImportProcedure X WHERE X eid %(eid)s";
return (eid: number) => client.execute(rql, { eid });
export function useApiDeleteDataService() {
const client = useClient();
const rql = "DELETE DataService X WHERE X eid %(eid)s";
return (eid: number) => client.execute(rql, { eid });
export function useApiDeleteRecipe() {
const client = useClient();
const rql = "DELETE ImportRecipe X WHERE X eid %(eid)s";
return (eid: number) => client.execute(rql, { eid });
}
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
function pushSetProjectFiles(
transaction: Transaction,
eid: number | TransactionQueryScalarRef,
data: Omit<Project, "import_recipes">,
) {
const insertFileRql =
"INSERT File X: X data %(data)s, X data_format %(data_format)s, X data_name %(data_name)s";
const setOntologyRql =
"Set X ontology_file %(ontology_file)s WHERE X eid %(eid)s";
const setShaclRql = "Set X shacl_files %(shacl_files)s WHERE X eid %(eid)s";
const binaries: BinariesParam = {};
if (data.ontology_file?.data) {
const file = data.ontology_file.data;
binaries["ontology_file"] = file;
const insertQuery = transaction.push(insertFileRql, {
data: {
type: "binary_reference",
ref: "ontology_file",
},
data_format: file.type,
data_name: "ontologie.owl",
});
transaction.push(setOntologyRql, {
eid,
ontology_file: insertQuery.ref().row(0).column(0),
});
}
if (data.shacl_files?.data) {
const file = data.shacl_files.data;
binaries["shacl_files"] = file;
const insertQuery = transaction.push(insertFileRql, {
data: {
type: "binary_reference",
ref: "shacl_files",
},
data_format: file.type,
data_name: "shacl.shacl",
});
transaction.push(setShaclRql, {
eid,
shacl_files: insertQuery.ref().row(0).column(0),
});
}
transaction.setBinaries(binaries);
}
export function useApiCreateProject() {
const client = useClient();
"INSERT ImportProcedure X: X name %(name)s, X virtuoso_url %(virtuoso_url)s, X virtuoso_user %(virtuoso_user)s, " +
"X virtuoso_password %(virtuoso_password)s, X activated %(activated)s";
return async (data: Omit<Project, "import_recipes">) => {
const transaction = new Transaction();
const query = transaction.push(rql, {
virtuoso_url: data.virtuoso_url,
virtuoso_password: data.virtuoso_password,
activated: data.activated,
});
const eidRef = query.ref().row(0).column(0);
pushSetProjectFiles(transaction, eidRef, data);
const result = await client.executeTransaction(transaction);
return result.resolveScalar(eidRef) as number;
};
export function useApiUpdateProject() {
const client = useClient();
"SET X name %(name)s, X virtuoso_url %(virtuoso_url)s, X virtuoso_user %(virtuoso_user)s, X virtuoso_password %(virtuoso_password)s, X activated %(activated)s" +
"WHERE X is ImportProcedure, X eid %(eid)s";
return (data: Omit<Project, "import_recipes">) => {
const transaction = new Transaction();
transaction.push(rql, {
eid: data.eid,
name: data.name,
virtuoso_url: data.virtuoso_url,
virtuoso_password: data.virtuoso_password,
activated: data.activated,
});
pushSetProjectFiles(transaction, data.eid, data);
return client.executeTransaction(transaction);
};
export function useApiUpdateProjectState() {
const client = useClient();
const rql =
"SET X activated %(activated)s" +
"WHERE X is ImportProcedure, X eid %(eid)s";
return (eid: number, activated: boolean) =>
client.execute(rql, { eid, activated });
export function useApiCreateDataService() {
const client = useClient();
const rql =
"INSERT DataService X: X name %(name)s, X data_url %(data_url)s, X refresh_period %(refresh_period)s, X description %(description)s";
return (data: Omit<DataService, "eid" | "projects">) =>
client.execute(rql, {
name: data.name,
data_url: data.data_url,
refresh_period: data.refresh_period,
description: data.description ?? "",
});
export function useApiUpdateDataService() {
const client = useClient();
const rql =
"SET X name %(name)s, X data_url %(data_url)s, X refresh_period %(refresh_period)s, X description %(description)s" +
"WHERE X is DataService, X eid %(eid)s";
return (data: DataService) =>
client.execute(rql, {
eid: data.eid,
name: data.name,
data_url: data.data_url,
refresh_period: data.refresh_period,
description: data.description ?? "",
});
export class UnknownEidError extends Error {
constructor(eid: number) {
super();
this.message = eid.toString();
}
}
export function useApiCreateRecipe() {
const client = useClient();
const insertRql =
"INSERT ImportRecipe X: X name %(name)s, X graph_uri %(graph_uri)s, X process_type %(process_type)s";
const setDataServiceRql =
"SET X dataservice %(dataservice)s WHERE X eid %(eid)s";
const setProjectRql =
"SET X import_recipes %(import_recipes)s WHERE X eid %(project_eid)s";
return (projectEid: number, data: Omit<Recipe, "eid">) => {
const transaction = new Transaction();
const insertQuery = transaction.push(insertRql, {
name: data.name,
process_type: data.process_type,
});
const eidRef = insertQuery.ref().row(0).column(0);
transaction.push(setDataServiceRql, {
dataservice: data.dataservice.eid,
eid: eidRef,
});
transaction.push(setProjectRql, {
import_recipes: eidRef,
project_eid: projectEid,
});
return client.executeTransaction(transaction);
};
}
export function useApiGetProject(): (eid: number) => Promise<Project> {
const client = useClient();
"Any X, ATTR_NAME, ATTR_VIRTUOSO_URL, ATTR_VIRTUOSO_USER, ATTR_VIRTUOSO_PASSWORD, ATTR_ACTIVATED, REL_ONTOLOGY.download_url(), REL_SHACL.download_url() " +
"WHERE X is ImportProcedure, X eid %(eid)s, X name ATTR_NAME, X virtuoso_url ATTR_VIRTUOSO_URL, X virtuoso_user ATTR_VIRTUOSO_USER, " +
"X virtuoso_password ATTR_VIRTUOSO_PASSWORD, X activated ATTR_ACTIVATED, X ontology_file REL_ONTOLOGY?, X shacl_files REL_SHACL?";
const recipeListRql =
"Any X, ATTR_NAME, ATTR_GRAPH_URI, ATTR_PROCESS_TYPE ,REL_DATASERVICE, REL_DATASERVICE_NAME " +
"WHERE X is ImportRecipe, X name ATTR_NAME, X graph_uri ATTR_GRAPH_URI, X process_type ATTR_PROCESS_TYPE, X dataservice REL_DATASERVICE, REL_DATASERVICE name REL_DATASERVICE_NAME, O import_recipes X, O eid %(eid)s";
return async (eid: number) => {
try {
const transaction = new Transaction();
const projectQuery = transaction.push(projectRql, { eid });
const recipeListQuery = transaction.push(recipeListRql, { eid });
const result = await client.executeTransaction(transaction);
const projectResult = result.resolveQuery(projectQuery.ref());
const recipeListResult = result.resolveQuery(recipeListQuery.ref());
if (projectResult.length === 0) {
throw new UnknownEidError(eid);
}
const recipeListJsonResult: Array<Recipe> = recipeListResult.map(
(r) =>
({
eid: r[0],
name: r[1],
Olivier Giorgis
committed
graph_uri: r[2],
process_type: r[3],
dataservice: { eid: r[4], name: r[5] },
}) as Recipe,
);
const r = projectResult[0];
return {
eid: r[0],
name: r[1],
virtuoso_url: r[2],
virtuoso_password: r[4],
activated: r[5],
import_recipes: recipeListJsonResult,
ontology_file: { downloadUrl: r[6] } as CWFile,
shacl_files: { downloadUrl: r[7] } as CWFile,
} as Project;
} catch (e) {
if (e && typeof e === "object" && "title" in e) {
const errorData = e as { title: string };
if (errorData.title === "TypeResolverException") {
throw new UnknownEidError(eid);
}
}
throw e;
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
export function useApiGetImportProcesses(): (data: {
dataServiceEid?: number;
recipeEid?: number;
projectEid?: number;
}) => Promise<ImportProcess[]> {
const client = useClient();
function getImportRecipePart(hasDataService: boolean, hasRecipe: boolean) {
if (hasRecipe)
return "X import_recipe R, R name VAL_RECIPE, R eid %(recipe_eid)s, ";
if (hasDataService)
return "X import_recipe R, R name VAL_RECIPE, R dataservice D, D eid %(dataservice_eid)s, ";
return "X import_recipe R, R name VAL_RECIPE, ";
}
function getImportProcedurePart(hasProject: boolean) {
if (hasProject)
return "X import_procedure P, P name VAL_PROJECT, P eid %(project_eid)s, ";
return "X import_procedure P, P name VAL_PROJECT, ";
}
function getRql(
hasDataService: boolean,
hasRecipe: boolean,
hasProject: boolean,
) {
// if your entity type is "workflowable" then you can use the relation in_state to find out
// in which state the entity is (whatever the workflow you use). then you can use the wf_info_for on
// the state to fetch the TrInfo which leads to this state, and with the TrInfo entity you do have the
// creation_date, the comment and so on
return (
"Any X, MAX(VAL_DATE), VAL_RECIPE, VAL_PROJECT, VAL_STATE " +
"GROUPBY X, VAL_RECIPE, VAL_PROJECT, VAL_STATE " +
"ORDERBY MAX(VAL_DATE) DESC " +
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
"WHERE X is ImportProcess, " +
getImportRecipePart(hasDataService, hasRecipe) +
getImportProcedurePart(hasProject) +
"X in_state S, S name VAL_STATE, " +
"TR wf_info_for X, TR creation_date VAL_DATE"
);
}
return async ({ dataServiceEid, recipeEid, projectEid }) => {
try {
const transaction = new Transaction();
const params: RQLParams = {};
if (dataServiceEid) {
params["dataservice_eid"] = dataServiceEid;
}
if (recipeEid) {
params["recipe_eid"] = recipeEid;
}
if (projectEid) {
params["project_eid"] = projectEid;
}
const importProcessListQuery = transaction.push(
getRql(
dataServiceEid !== undefined,
recipeEid !== undefined,
projectEid !== undefined,
),
params,
);

Fabien Amarger
committed
// TODO fetch files for all import processes
// See https://forge.extranet.logilab.fr/cubicweb/RQL/-/merge_requests/99
const dataLogQuery = transaction.push(
"Any X, DATA.download_url(), LOG.download_url() WHERE X eid %(eid)s, " +
"X has_output_dataset DATA?, X import_report LOG?",
{ eid: importProcessListQuery.ref().row(0).column(0) },
);
const result = await client.executeTransaction(transaction);
const importProcessListResult = result.resolveQuery(
importProcessListQuery.ref(),
);

Fabien Amarger
committed
const dataLogListResult = result.resolveQuery(dataLogQuery.ref());
for (const result of importProcessListResult) {
const dataLog = dataLogListResult.find((e) => e[0] === result[0]);
if (dataLog != undefined) {
result[5] = dataLog[1];
result[6] = dataLog[2];
}
}
return importProcessListResultSetToObject(importProcessListResult);
} catch (e) {
if (e && typeof e === "object" && "title" in e) {
const errorData = e as { title: string };
throw new Error(errorData.title);
}
throw e;
}
};
}
function importProcessListResultSetToObject(
resultSet: ResultSet,
): ImportProcess[] {

Fabien Amarger
committed
return resultSet.map((r) => {
return {
eid: r[0],
date: r[1],
recipe: r[2],
project: r[3],
state: r[4],
dataset_url: r[5],
log_url: r[6],
} as ImportProcess;
});
function projectListResultSetToObject(resultSet: ResultSet) {
return resultSet.map(
(r) =>
({
eid: r[0],
name: r[1],
virtuoso_url: r[2],
virtuoso_password: r[4],
activated: r[5],
}) as Project,
);
}
export function useApiGetDataService(): (eid: number) => Promise<DataService> {
const client = useClient();
const dataServiceRql =
"Any X, ATTR_NAME, ATTR_DATA_URL, ATTR_REFRESH_PERIOD, ATTR_DESCRIPTION " +
"WHERE X is DataService, X eid %(eid)s, X name ATTR_NAME, X data_url ATTR_DATA_URL, X refresh_period ATTR_REFRESH_PERIOD, X description ATTR_DESCRIPTION";
const projectListRql =
"Any X, ATTR_NAME, ATTR_VIRTUOSO_URL, ATTR_VIRTUOSO_USER, ATTR_VIRTUOSO_PASSWORD, ATTR_ACTIVATED " +
"WHERE X is ImportProcedure, X name ATTR_NAME, X virtuoso_url ATTR_VIRTUOSO_URL, X virtuoso_user ATTR_VIRTUOSO_USER, X virtuoso_password ATTR_VIRTUOSO_PASSWORD, X activated ATTR_ACTIVATED, " +
"X import_recipes R, R dataservice %(eid)s";
return async (eid: number) => {
try {
const transaction = new Transaction();
const dataServiceQuery = transaction.push(dataServiceRql, { eid });
const projectListQuery = transaction.push(projectListRql, { eid });
const result = await client.executeTransaction(transaction);
const dataServiceResult = result.resolveQuery(dataServiceQuery.ref());
const projectListResult = result.resolveQuery(projectListQuery.ref());
if (dataServiceResult.length === 0) {
throw new UnknownEidError(eid);
}
const r = dataServiceResult[0];
eid: r[0],
name: r[1],
data_url: r[2],
refresh_period: r[3],
description: r[4],
projects: projectListResultSetToObject(projectListResult),
} as DataService;
} catch (e) {
if (e && typeof e === "object" && "title" in e) {
const errorData = e as { title: string };
if (errorData.title === "TypeResolverException") {
throw new UnknownEidError(eid);
}
}
throw e;
}
};
}
export function useApiGetProjectList(): () => Promise<Array<Project>> {
const client = useClient();
const rql =
"Any X, ATTR_NAME, ATTR_VIRTUOSO_URL, ATTR_VIRTUOSO_USER, ATTR_VIRTUOSO_PASSWORD, ATTR_ACTIVATED " +
"WHERE X is ImportProcedure, X name ATTR_NAME, X virtuoso_url ATTR_VIRTUOSO_URL, X virtuoso_user ATTR_VIRTUOSO_USER, X virtuoso_password ATTR_VIRTUOSO_PASSWORD, X activated ATTR_ACTIVATED";
return async () => {
const result = await client.execute(rql, {});
return projectListResultSetToObject(result);
export function useApiGetDataServiceList(): () => Promise<Array<DataService>> {
const client = useClient();
const rql =
"Any X, ATTR_NAME, ATTR_DATA_URL, ATTR_REFRESH_PERIOD, ATTR_DESCRIPTION " +
"WHERE X is DataService, X name ATTR_NAME, X data_url ATTR_DATA_URL, X refresh_period ATTR_REFRESH_PERIOD, X description ATTR_DESCRIPTION";
return async () => {
const result = await client.execute(rql, {});
const jsonResult: Array<DataService> = result.map(
(r) =>
({
eid: r[0],
name: r[1],
data_url: r[2],
refresh_period: r[3],
description: r[4],
}) as DataService,
);
return jsonResult;
};
}