Finishing specs to explain how to configure a calculation view.

This commit is contained in:
mike12345567 2024-10-31 17:42:46 +00:00
parent cf84191995
commit 9d85661893
7 changed files with 661 additions and 151 deletions

View File

@ -2099,6 +2099,13 @@
"description": "The name of the view.", "description": "The name of the view.",
"type": "string" "type": "string"
}, },
"type": {
"description": "The type of view - standard (empty value) or calculation.",
"type": "string",
"enum": [
"calculation"
]
},
"primaryDisplay": { "primaryDisplay": {
"type": "string", "type": "string",
"description": "A column used to display rows from this view - usually used when rendered in tables." "description": "A column used to display rows from this view - usually used when rendered in tables."
@ -2106,6 +2113,8 @@
"schema": { "schema": {
"type": "object", "type": "object",
"additionalProperties": { "additionalProperties": {
"oneOf": [
{
"type": "object", "type": "object",
"properties": { "properties": {
"visible": { "visible": {
@ -2123,12 +2132,50 @@
"width": { "width": {
"type": "integer", "type": "integer",
"description": "A width for the column, defined in pixels - this affects rendering in tables." "description": "A width for the column, defined in pixels - this affects rendering in tables."
},
"column": {
"type": "array",
"description": "If this is a relationship column, we can set the columns we wish to include",
"items": {
"type": "object",
"properties": {
"readonly": {
"type": "boolean"
} }
} }
} }
} }
} }
}, },
{
"type": "object",
"properties": {
"calculationType": {
"type": "string",
"description": "This column should be built from a calculation, specifying a type and field. It is important to note when a calculation is configured all non-calculation columns will be used for grouping.",
"enum": [
"sum",
"avg",
"count",
"min",
"max"
]
},
"field": {
"type": "string",
"description": "The field from the table to perform the calculation on."
},
"distinct": {
"type": "boolean",
"description": "Can be used in tandem with the count calculation type, to count unique entries."
}
}
}
]
}
}
}
},
"viewOutput": { "viewOutput": {
"type": "object", "type": "object",
"properties": { "properties": {
@ -2145,6 +2192,13 @@
"description": "The name of the view.", "description": "The name of the view.",
"type": "string" "type": "string"
}, },
"type": {
"description": "The type of view - standard (empty value) or calculation.",
"type": "string",
"enum": [
"calculation"
]
},
"primaryDisplay": { "primaryDisplay": {
"type": "string", "type": "string",
"description": "A column used to display rows from this view - usually used when rendered in tables." "description": "A column used to display rows from this view - usually used when rendered in tables."
@ -2152,6 +2206,8 @@
"schema": { "schema": {
"type": "object", "type": "object",
"additionalProperties": { "additionalProperties": {
"oneOf": [
{
"type": "object", "type": "object",
"properties": { "properties": {
"visible": { "visible": {
@ -2169,9 +2225,47 @@
"width": { "width": {
"type": "integer", "type": "integer",
"description": "A width for the column, defined in pixels - this affects rendering in tables." "description": "A width for the column, defined in pixels - this affects rendering in tables."
},
"column": {
"type": "array",
"description": "If this is a relationship column, we can set the columns we wish to include",
"items": {
"type": "object",
"properties": {
"readonly": {
"type": "boolean"
} }
} }
} }
}
}
},
{
"type": "object",
"properties": {
"calculationType": {
"type": "string",
"description": "This column should be built from a calculation, specifying a type and field. It is important to note when a calculation is configured all non-calculation columns will be used for grouping.",
"enum": [
"sum",
"avg",
"count",
"min",
"max"
]
},
"field": {
"type": "string",
"description": "The field from the table to perform the calculation on."
},
"distinct": {
"type": "boolean",
"description": "Can be used in tandem with the count calculation type, to count unique entries."
}
}
}
]
}
}, },
"id": { "id": {
"description": "The ID of the view.", "description": "The ID of the view.",
@ -2202,6 +2296,13 @@
"description": "The name of the view.", "description": "The name of the view.",
"type": "string" "type": "string"
}, },
"type": {
"description": "The type of view - standard (empty value) or calculation.",
"type": "string",
"enum": [
"calculation"
]
},
"primaryDisplay": { "primaryDisplay": {
"type": "string", "type": "string",
"description": "A column used to display rows from this view - usually used when rendered in tables." "description": "A column used to display rows from this view - usually used when rendered in tables."
@ -2209,6 +2310,8 @@
"schema": { "schema": {
"type": "object", "type": "object",
"additionalProperties": { "additionalProperties": {
"oneOf": [
{
"type": "object", "type": "object",
"properties": { "properties": {
"visible": { "visible": {
@ -2226,9 +2329,47 @@
"width": { "width": {
"type": "integer", "type": "integer",
"description": "A width for the column, defined in pixels - this affects rendering in tables." "description": "A width for the column, defined in pixels - this affects rendering in tables."
},
"column": {
"type": "array",
"description": "If this is a relationship column, we can set the columns we wish to include",
"items": {
"type": "object",
"properties": {
"readonly": {
"type": "boolean"
} }
} }
} }
}
}
},
{
"type": "object",
"properties": {
"calculationType": {
"type": "string",
"description": "This column should be built from a calculation, specifying a type and field. It is important to note when a calculation is configured all non-calculation columns will be used for grouping.",
"enum": [
"sum",
"avg",
"count",
"min",
"max"
]
},
"field": {
"type": "string",
"description": "The field from the table to perform the calculation on."
},
"distinct": {
"type": "boolean",
"description": "Can be used in tandem with the count calculation type, to count unique entries."
}
}
}
]
}
}, },
"id": { "id": {
"description": "The ID of the view.", "description": "The ID of the view.",
@ -2958,6 +3099,50 @@
} }
} }
}, },
"/views/{viewId}/rows/search": {
"post": {
"operationId": "rowViewSearch",
"summary": "Search for rows in a view",
"tags": [
"rows"
],
"parameters": [
{
"$ref": "#/components/parameters/viewId"
},
{
"$ref": "#/components/parameters/appId"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/rowSearch"
}
}
}
},
"responses": {
"200": {
"description": "The response will contain an array of rows that match the search parameters.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/searchOutput"
},
"examples": {
"search": {
"$ref": "#/components/examples/rows"
}
}
}
}
}
}
}
},
"/tables": { "/tables": {
"post": { "post": {
"operationId": "tableCreate", "operationId": "tableCreate",

View File

@ -1758,6 +1758,11 @@ components:
name: name:
description: The name of the view. description: The name of the view.
type: string type: string
type:
description: The type of view - standard (empty value) or calculation.
type: string
enum:
- calculation
primaryDisplay: primaryDisplay:
type: string type: string
description: A column used to display rows from this view - usually used when description: A column used to display rows from this view - usually used when
@ -1765,47 +1770,8 @@ components:
schema: schema:
type: object type: object
additionalProperties: additionalProperties:
type: object oneOf:
properties: - type: object
visible:
type: boolean
description: Defines whether the column is visible or not - rows
retrieved/updated through this view will not be able to access
it.
readonly:
type: boolean
description: "When used in combination with 'visible: true' the column will be
visible in row responses but cannot be updated."
order:
type: integer
description: A number defining where the column shows up in tables, lowest being
first.
width:
type: integer
description: A width for the column, defined in pixels - this affects rendering
in tables.
viewOutput:
type: object
properties:
data:
description: The view to be created/updated.
type: object
required:
- name
- schema
- id
properties:
name:
description: The name of the view.
type: string
primaryDisplay:
type: string
description: A column used to display rows from this view - usually used when
rendered in tables.
schema:
type: object
additionalProperties:
type: object
properties: properties:
visible: visible:
type: boolean type: boolean
@ -1824,6 +1790,112 @@ components:
type: integer type: integer
description: A width for the column, defined in pixels - this affects rendering description: A width for the column, defined in pixels - this affects rendering
in tables. in tables.
column:
type: array
description: If this is a relationship column, we can set the columns we wish to
include
items:
type: object
properties:
readonly:
type: boolean
- type: object
properties:
calculationType:
type: string
description: This column should be built from a calculation, specifying a type
and field. It is important to note when a calculation is
configured all non-calculation columns will be used for
grouping.
enum:
- sum
- avg
- count
- min
- max
field:
type: string
description: The field from the table to perform the calculation on.
distinct:
type: boolean
description: Can be used in tandem with the count calculation type, to count
unique entries.
viewOutput:
type: object
properties:
data:
description: The view to be created/updated.
type: object
required:
- name
- schema
- id
properties:
name:
description: The name of the view.
type: string
type:
description: The type of view - standard (empty value) or calculation.
type: string
enum:
- calculation
primaryDisplay:
type: string
description: A column used to display rows from this view - usually used when
rendered in tables.
schema:
type: object
additionalProperties:
oneOf:
- type: object
properties:
visible:
type: boolean
description: Defines whether the column is visible or not - rows
retrieved/updated through this view will not be able
to access it.
readonly:
type: boolean
description: "When used in combination with 'visible: true' the column will be
visible in row responses but cannot be updated."
order:
type: integer
description: A number defining where the column shows up in tables, lowest being
first.
width:
type: integer
description: A width for the column, defined in pixels - this affects rendering
in tables.
column:
type: array
description: If this is a relationship column, we can set the columns we wish to
include
items:
type: object
properties:
readonly:
type: boolean
- type: object
properties:
calculationType:
type: string
description: This column should be built from a calculation, specifying a type
and field. It is important to note when a calculation
is configured all non-calculation columns will be used
for grouping.
enum:
- sum
- avg
- count
- min
- max
field:
type: string
description: The field from the table to perform the calculation on.
distinct:
type: boolean
description: Can be used in tandem with the count calculation type, to count
unique entries.
id: id:
description: The ID of the view. description: The ID of the view.
type: string type: string
@ -1845,6 +1917,11 @@ components:
name: name:
description: The name of the view. description: The name of the view.
type: string type: string
type:
description: The type of view - standard (empty value) or calculation.
type: string
enum:
- calculation
primaryDisplay: primaryDisplay:
type: string type: string
description: A column used to display rows from this view - usually used when description: A column used to display rows from this view - usually used when
@ -1852,13 +1929,14 @@ components:
schema: schema:
type: object type: object
additionalProperties: additionalProperties:
type: object oneOf:
- type: object
properties: properties:
visible: visible:
type: boolean type: boolean
description: Defines whether the column is visible or not - rows description: Defines whether the column is visible or not - rows
retrieved/updated through this view will not be able to retrieved/updated through this view will not be able
access it. to access it.
readonly: readonly:
type: boolean type: boolean
description: "When used in combination with 'visible: true' the column will be description: "When used in combination with 'visible: true' the column will be
@ -1871,6 +1949,36 @@ components:
type: integer type: integer
description: A width for the column, defined in pixels - this affects rendering description: A width for the column, defined in pixels - this affects rendering
in tables. in tables.
column:
type: array
description: If this is a relationship column, we can set the columns we wish to
include
items:
type: object
properties:
readonly:
type: boolean
- type: object
properties:
calculationType:
type: string
description: This column should be built from a calculation, specifying a type
and field. It is important to note when a
calculation is configured all non-calculation
columns will be used for grouping.
enum:
- sum
- avg
- count
- min
- max
field:
type: string
description: The field from the table to perform the calculation on.
distinct:
type: boolean
description: Can be used in tandem with the count calculation type, to count
unique entries.
id: id:
description: The ID of the view. description: The ID of the view.
type: string type: string
@ -2308,6 +2416,32 @@ paths:
examples: examples:
search: search:
$ref: "#/components/examples/rows" $ref: "#/components/examples/rows"
"/views/{viewId}/rows/search":
post:
operationId: rowViewSearch
summary: Search for rows in a view
tags:
- rows
parameters:
- $ref: "#/components/parameters/viewId"
- $ref: "#/components/parameters/appId"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/rowSearch"
responses:
"200":
description: The response will contain an array of rows that match the search
parameters.
content:
application/json:
schema:
$ref: "#/components/schemas/searchOutput"
examples:
search:
$ref: "#/components/examples/rows"
/tables: /tables:
post: post:
operationId: tableCreate operationId: tableCreate

View File

@ -1,5 +1,6 @@
import { object } from "./utils" import { object } from "./utils"
import Resource from "./utils/Resource" import Resource from "./utils/Resource"
import { CalculationType } from "@budibase/types"
const view = { const view = {
name: "peopleView", name: "peopleView",
@ -46,6 +47,19 @@ const baseColumnDef = {
description: description:
"A width for the column, defined in pixels - this affects rendering in tables.", "A width for the column, defined in pixels - this affects rendering in tables.",
}, },
column: {
type: "array",
description:
"If this is a relationship column, we can set the columns we wish to include",
items: {
type: "object",
properties: {
readonly: {
type: "boolean",
},
},
},
},
} }
const viewSchema = { const viewSchema = {
@ -57,6 +71,11 @@ const viewSchema = {
description: "The name of the view.", description: "The name of the view.",
type: "string", type: "string",
}, },
type: {
description: "The type of view - standard (empty value) or calculation.",
type: "string",
enum: ["calculation"],
},
primaryDisplay: { primaryDisplay: {
type: "string", type: "string",
description: description:
@ -65,9 +84,34 @@ const viewSchema = {
schema: { schema: {
type: "object", type: "object",
additionalProperties: { additionalProperties: {
oneOf: [
{
type: "object", type: "object",
properties: baseColumnDef, properties: baseColumnDef,
}, },
{
type: "object",
properties: {
calculationType: {
type: "string",
description:
"This column should be built from a calculation, specifying a type and field. It is important to note when a calculation is configured all non-calculation columns will be used for grouping.",
enum: Object.values(CalculationType),
},
field: {
type: "string",
description:
"The field from the table to perform the calculation on.",
},
distinct: {
type: "boolean",
description:
"Can be used in tandem with the count calculation type, to count unique entries.",
},
},
},
],
},
}, },
}, },
} }

View File

@ -22,13 +22,13 @@ export function fixRow(row: Row, params: any) {
return row return row
} }
export async function search(ctx: UserCtx, next: Next) { function getSearchParameters(ctx: UserCtx) {
let { sort, paginate, bookmark, limit, query } = ctx.request.body let { sort, paginate, bookmark, limit, query } = ctx.request.body
// update the body to the correct format of the internal search // update the body to the correct format of the internal search
if (!sort) { if (!sort) {
sort = {} sort = {}
} }
ctx.request.body = { return {
sort: sort.column, sort: sort.column,
sortType: sort.type, sortType: sort.type,
sortOrder: sort.order, sortOrder: sort.order,
@ -37,10 +37,25 @@ export async function search(ctx: UserCtx, next: Next) {
limit, limit,
query, query,
} }
}
export async function search(ctx: UserCtx, next: Next) {
ctx.request.body = getSearchParameters(ctx)
await rowController.search(ctx) await rowController.search(ctx)
await next() await next()
} }
export async function viewSearch(ctx: UserCtx, next: Next) {
ctx.request.body = getSearchParameters(ctx)
await rowController.views.searchView({
...ctx,
params: {
viewId: ctx.params.viewId,
},
})
await next()
}
export async function create(ctx: UserCtx, next: Next) { export async function create(ctx: UserCtx, next: Next) {
ctx.request.body = fixRow(ctx.request.body, ctx.params) ctx.request.body = fixRow(ctx.request.body, ctx.params)
await rowController.save(ctx) await rowController.save(ctx)
@ -79,4 +94,5 @@ export default {
update, update,
destroy, destroy,
search, search,
viewSearch,
} }

View File

@ -40,12 +40,16 @@ export async function read(ctx: UserCtx, next: Next) {
} }
export async function update(ctx: UserCtx, next: Next) { export async function update(ctx: UserCtx, next: Next) {
// TODO: this is more complex - no rev on views const viewId = ctx.params.viewId
// ctx.request.body = await addRev( await controller.v2.update({
// fixView(ctx.request.body, ctx.params), ...ctx,
// ctx.params.tableId body: {
// ) data: fixView(ctx.body, { viewId }),
await controller.v2.update(ctx) },
params: {
viewId,
},
})
await next() await next()
} }

View File

@ -168,4 +168,40 @@ read.push(
).addMiddleware(externalSearchValidator()) ).addMiddleware(externalSearchValidator())
) )
/**
* @openapi
* /views/{viewId}/rows/search:
* post:
* operationId: rowViewSearch
* summary: Search for rows in a view
* tags:
* - rows
* parameters:
* - $ref: '#/components/parameters/viewId'
* - $ref: '#/components/parameters/appId'
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/rowSearch'
* responses:
* 200:
* description: The response will contain an array of rows that match the search parameters.
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/searchOutput'
* examples:
* search:
* $ref: '#/components/examples/rows'
*/
read.push(
new Endpoint(
"post",
"/views/:viewId/rows/search",
controller.search
).addMiddleware(externalSearchValidator())
)
export default { read, write } export default { read, write }

View File

@ -65,6 +65,9 @@ export interface paths {
"/tables/{tableId}/rows/search": { "/tables/{tableId}/rows/search": {
post: operations["rowSearch"]; post: operations["rowSearch"];
}; };
"/views/{viewId}/rows/search": {
post: operations["rowViewSearch"];
};
"/tables": { "/tables": {
/** Create a table, this could be internal or external. */ /** Create a table, this could be internal or external. */
post: operations["tableCreate"]; post: operations["tableCreate"];
@ -833,10 +836,16 @@ export interface components {
view: { view: {
/** @description The name of the view. */ /** @description The name of the view. */
name: string; name: string;
/**
* @description The type of view - standard (empty value) or calculation.
* @enum {string}
*/
type?: "calculation";
/** @description A column used to display rows from this view - usually used when rendered in tables. */ /** @description A column used to display rows from this view - usually used when rendered in tables. */
primaryDisplay?: string; primaryDisplay?: string;
schema: { schema: {
[key: string]: { [key: string]:
| {
/** @description Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it. */ /** @description Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it. */
visible?: boolean; visible?: boolean;
/** @description When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated. */ /** @description When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated. */
@ -845,6 +854,21 @@ export interface components {
order?: number; order?: number;
/** @description A width for the column, defined in pixels - this affects rendering in tables. */ /** @description A width for the column, defined in pixels - this affects rendering in tables. */
width?: number; width?: number;
/** @description If this is a relationship column, we can set the columns we wish to include */
column?: {
readonly?: boolean;
}[];
}
| {
/**
* @description This column should be built from a calculation, specifying a type and field. It is important to note when a calculation is configured all non-calculation columns will be used for grouping.
* @enum {string}
*/
calculationType?: "sum" | "avg" | "count" | "min" | "max";
/** @description The field from the table to perform the calculation on. */
field?: string;
/** @description Can be used in tandem with the count calculation type, to count unique entries. */
distinct?: boolean;
}; };
}; };
}; };
@ -853,10 +877,16 @@ export interface components {
data: { data: {
/** @description The name of the view. */ /** @description The name of the view. */
name: string; name: string;
/**
* @description The type of view - standard (empty value) or calculation.
* @enum {string}
*/
type?: "calculation";
/** @description A column used to display rows from this view - usually used when rendered in tables. */ /** @description A column used to display rows from this view - usually used when rendered in tables. */
primaryDisplay?: string; primaryDisplay?: string;
schema: { schema: {
[key: string]: { [key: string]:
| {
/** @description Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it. */ /** @description Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it. */
visible?: boolean; visible?: boolean;
/** @description When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated. */ /** @description When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated. */
@ -865,6 +895,21 @@ export interface components {
order?: number; order?: number;
/** @description A width for the column, defined in pixels - this affects rendering in tables. */ /** @description A width for the column, defined in pixels - this affects rendering in tables. */
width?: number; width?: number;
/** @description If this is a relationship column, we can set the columns we wish to include */
column?: {
readonly?: boolean;
}[];
}
| {
/**
* @description This column should be built from a calculation, specifying a type and field. It is important to note when a calculation is configured all non-calculation columns will be used for grouping.
* @enum {string}
*/
calculationType?: "sum" | "avg" | "count" | "min" | "max";
/** @description The field from the table to perform the calculation on. */
field?: string;
/** @description Can be used in tandem with the count calculation type, to count unique entries. */
distinct?: boolean;
}; };
}; };
/** @description The ID of the view. */ /** @description The ID of the view. */
@ -875,10 +920,16 @@ export interface components {
data: { data: {
/** @description The name of the view. */ /** @description The name of the view. */
name: string; name: string;
/**
* @description The type of view - standard (empty value) or calculation.
* @enum {string}
*/
type?: "calculation";
/** @description A column used to display rows from this view - usually used when rendered in tables. */ /** @description A column used to display rows from this view - usually used when rendered in tables. */
primaryDisplay?: string; primaryDisplay?: string;
schema: { schema: {
[key: string]: { [key: string]:
| {
/** @description Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it. */ /** @description Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it. */
visible?: boolean; visible?: boolean;
/** @description When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated. */ /** @description When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated. */
@ -887,6 +938,21 @@ export interface components {
order?: number; order?: number;
/** @description A width for the column, defined in pixels - this affects rendering in tables. */ /** @description A width for the column, defined in pixels - this affects rendering in tables. */
width?: number; width?: number;
/** @description If this is a relationship column, we can set the columns we wish to include */
column?: {
readonly?: boolean;
}[];
}
| {
/**
* @description This column should be built from a calculation, specifying a type and field. It is important to note when a calculation is configured all non-calculation columns will be used for grouping.
* @enum {string}
*/
calculationType?: "sum" | "avg" | "count" | "min" | "max";
/** @description The field from the table to perform the calculation on. */
field?: string;
/** @description Can be used in tandem with the count calculation type, to count unique entries. */
distinct?: boolean;
}; };
}; };
/** @description The ID of the view. */ /** @description The ID of the view. */
@ -1295,6 +1361,31 @@ export interface operations {
}; };
}; };
}; };
rowViewSearch: {
parameters: {
path: {
/** The ID of the view which this request is targeting. */
viewId: components["parameters"]["viewId"];
};
header: {
/** The ID of the app which this request is targeting. */
"x-budibase-app-id": components["parameters"]["appId"];
};
};
responses: {
/** The response will contain an array of rows that match the search parameters. */
200: {
content: {
"application/json": components["schemas"]["searchOutput"];
};
};
};
requestBody: {
content: {
"application/json": components["schemas"]["rowSearch"];
};
};
};
/** Create a table, this could be internal or external. */ /** Create a table, this could be internal or external. */
tableCreate: { tableCreate: {
parameters: { parameters: {