// (C) 2007-2019 GoodData Corporation import * as errors from "../errors/errors"; import { Application } from "express"; import * as HttpStatusCodes from "http-status-codes"; import { has, includes, omit } from "lodash"; import { ILinkResponse } from "../../model/Link"; import { IMockProject, getWidgets, getAttributes, getVisualizationObjects, getFilterContexts, getVisualizationWidgets, } from "../../model/MockProject"; import { ValidationError } from "../ValidationError"; import { IObjectMeta } from "../../model/ObjectMeta"; import { getWidgetUri, getWidgetCategory } from "../../model/Widget"; import { IVisualizationWidget } from "../../model/VisualizationWidget"; export interface IUsing2InUseRequest { inUse: { nearest: boolean; types?: string[]; uri: string; }; } export interface IUsing2InUseManyRequest { inUseMany: { nearest: boolean; types?: string[]; uris: string[]; }; } export interface IUsing2InUseResponse { entries: ILinkResponse[]; } export interface IUsing2InUseManyResponse { useMany: IUseMany[]; } export interface IUseMany { entries: ILinkResponse[]; uri: string; } function validate(request: IUsing2InUseRequest | IUsing2InUseManyRequest): void { if (!has(request, "inUse") && !has(request, "inUseMany")) { // inUseMix isn't implemented because it's not used in gdc-dashboards throw new ValidationError(errors.undefinedUsing2Structure(Object.keys(request)[0])); } } function getVisualizationUriFromVisualizationWidget(visualizationWidget: IVisualizationWidget): string { return visualizationWidget.content.visualization; } function getInUseBody(request: IUsing2InUseRequest, project: IMockProject): IUsing2InUseResponse { const dashboardUri = request.inUse.uri; const dashboard = project.analyticalDashboards.find(d => d.meta.uri === dashboardUri); const widgets = [ ...getFilterContexts(project), ...getVisualizationObjects(project), ...getWidgets(project), ]; const visualizationWidgets = getVisualizationWidgets(project); const filterContextUri = dashboard.content.filterContext; const visualizationsUris = visualizationWidgets.map(visualizationWidget => getVisualizationUriFromVisualizationWidget(visualizationWidget), ); const visualizationWidgetsUris = dashboard.content.widgets; const widgetUris = [filterContextUri, ...visualizationsUris, ...visualizationWidgetsUris]; const entries: ILinkResponse[] = widgets .filter(widget => { const widgetUri = getWidgetUri(widget); return includes(widgetUris, widgetUri); }) .filter(widget => request.inUse.types.some(type => type === getWidgetCategory(widget))) .map(widget => objectMetaToLinkResponse(widget.meta)); return { entries }; } function objectMetaToLinkResponse(objectMeta: IObjectMeta): ILinkResponse { return Object.keys(omit(objectMeta, ["uri"])).reduce( (linkResponse: ILinkResponse, key: string): ILinkResponse => { if (key === "deprecated") { linkResponse.deprecated = objectMeta.deprecated ? "1" : "0"; } else if (includes(["isProduction", "sharedWithSomeone", "unlisted", "locked"], key)) { linkResponse[key] = objectMeta[key] ? 1 : 0; } else if (key !== "locked") { linkResponse[key] = objectMeta[key]; } return linkResponse; }, { link: objectMeta.uri }, ); } function getInUseManyBody(request: IUsing2InUseManyRequest, project: IMockProject): IUsing2InUseManyResponse { const requestedDisplayFormUris = request.inUseMany.uris; if (!includes(request.inUseMany.types, "attribute")) { return { useMany: [] }; } const useManyResponse = getAttributes(project).reduce((result, attribute) => { const displayForm = attribute.content.displayForms.find(df => { const displayFormUri = df.meta.uri; return includes(requestedDisplayFormUris, displayFormUri); }); if (displayForm) { const attributeObjectMeta: IObjectMeta = attribute.meta; const entryResponse: ILinkResponse = objectMetaToLinkResponse(attributeObjectMeta); return [...result, { entries: [entryResponse], uri: displayForm.meta.uri }]; } return result; }, []); return { useMany: useManyResponse }; } export const using2 = { register(app: Application, project: IMockProject) { app.post(`/gdc/md/${project.project.meta.identifier}/using2`, (req, res) => { try { validate(req.body); if (has(req.body, "inUse")) { res.status(HttpStatusCodes.OK).json(getInUseBody(req.body, project)); } else { res.status(HttpStatusCodes.OK).json(getInUseManyBody(req.body, project)); } } catch (error) { if (error instanceof ValidationError) { res.status(HttpStatusCodes.BAD_REQUEST).json(error.getValidationError()); } else { res.status(HttpStatusCodes.INTERNAL_SERVER_ERROR).json(error); } } }); return app; }, };