diff --git a/jsapp/js/api/models/assetUsageListParams.ts b/jsapp/js/api/models/assetUsageListParams.ts index 0b7221901b..0d5f98f174 100644 --- a/jsapp/js/api/models/assetUsageListParams.ts +++ b/jsapp/js/api/models/assetUsageListParams.ts @@ -12,11 +12,11 @@ The endpoints are grouped by area of intended use. Each category contains relate export type AssetUsageListParams = { /** - * A page number within the paginated result set. + * Number of results to return per page. */ - page?: number + limit?: number /** - * Number of results to return per page. + * The initial index from which to return the results. */ - page_size?: number + offset?: number } diff --git a/jsapp/js/api/models/organizationAssetUsageResponse.ts b/jsapp/js/api/models/customAssetUsage.ts similarity index 57% rename from jsapp/js/api/models/organizationAssetUsageResponse.ts rename to jsapp/js/api/models/customAssetUsage.ts index eaa6d15471..5ef8bf5246 100644 --- a/jsapp/js/api/models/organizationAssetUsageResponse.ts +++ b/jsapp/js/api/models/customAssetUsage.ts @@ -1,4 +1,4 @@ -import type { OrganizationAssetUsageResponseNlpUsageAllTime } from './organizationAssetUsageResponseNlpUsageAllTime' +import type { DeploymentStatusEnum } from './deploymentStatusEnum' /** * Generated by orval v7.10.0 🍺 * Do not edit manually. @@ -10,15 +10,15 @@ The endpoints are grouped by area of intended use. Each category contains relate **General note**: All projects (whether deployed or draft), as well as all library content (questions, blocks, templates, and collections) in the user-facing application are represented in the API as "assets". * OpenAPI spec version: 2.0.0 (api_v2) */ -import type { OrganizationAssetUsageResponseNlpUsageCurrentPeriod } from './organizationAssetUsageResponseNlpUsageCurrentPeriod' +import type { NlpUsage } from './nlpUsage' -export interface OrganizationAssetUsageResponse { - asset: string - asset__name: string - nlp_usage_current_period: OrganizationAssetUsageResponseNlpUsageCurrentPeriod - nlp_usage_all_time: OrganizationAssetUsageResponseNlpUsageAllTime - storage_bytes: number - submission_count_current_period: number - submission_count_all_time: number - deployment_status: string +export interface CustomAssetUsage { + readonly asset: string + readonly asset__name: string + readonly nlp_usage_current_period: NlpUsage + readonly nlp_usage_all_time: NlpUsage + readonly storage_bytes: number + readonly submission_count_current_period: number + readonly submission_count_all_time: number + readonly deployment_status: DeploymentStatusEnum } diff --git a/jsapp/js/api/models/deploymentStatusEnum.ts b/jsapp/js/api/models/deploymentStatusEnum.ts new file mode 100644 index 0000000000..f89c8990ce --- /dev/null +++ b/jsapp/js/api/models/deploymentStatusEnum.ts @@ -0,0 +1,25 @@ +/** + * Generated by orval v7.10.0 🍺 + * Do not edit manually. + * KoboToolbox Primary API + * This page documents all KoboToolbox API endpoints, except for those implementing the OpenRosa protocol, which are [documented separately](/api/openrosa/docs/). + +The endpoints are grouped by area of intended use. Each category contains related endpoints, with detailed documentation on usage and configuration. Use this as a reference to quickly find the right endpoint for managing projects, forms, data, permissions, integrations, logs, and organizational resources. + +**General note**: All projects (whether deployed or draft), as well as all library content (questions, blocks, templates, and collections) in the user-facing application are represented in the API as "assets". + * OpenAPI spec version: 2.0.0 (api_v2) + */ + +/** + * * `archived` - archived + * `deployed` - deployed + * `draft` - draft + */ +export type DeploymentStatusEnum = (typeof DeploymentStatusEnum)[keyof typeof DeploymentStatusEnum] + +// eslint-disable-next-line @typescript-eslint/no-redeclare +export const DeploymentStatusEnum = { + archived: 'archived', + deployed: 'deployed', + draft: 'draft', +} as const diff --git a/jsapp/js/api/models/organizationAssetUsageResponseNlpUsageAllTime.ts b/jsapp/js/api/models/nlpUsage.ts similarity index 93% rename from jsapp/js/api/models/organizationAssetUsageResponseNlpUsageAllTime.ts rename to jsapp/js/api/models/nlpUsage.ts index 1ffa8c6ab3..ebc1378a79 100644 --- a/jsapp/js/api/models/organizationAssetUsageResponseNlpUsageAllTime.ts +++ b/jsapp/js/api/models/nlpUsage.ts @@ -10,7 +10,7 @@ The endpoints are grouped by area of intended use. Each category contains relate * OpenAPI spec version: 2.0.0 (api_v2) */ -export type OrganizationAssetUsageResponseNlpUsageAllTime = { +export interface NlpUsage { total_nlp_asr_seconds: number total_nlp_mt_characters: number } diff --git a/jsapp/js/api/models/organizationAssetUsageResponseNlpUsageCurrentPeriod.ts b/jsapp/js/api/models/organizationsAssetUsageListParams.ts similarity index 80% rename from jsapp/js/api/models/organizationAssetUsageResponseNlpUsageCurrentPeriod.ts rename to jsapp/js/api/models/organizationsAssetUsageListParams.ts index 44edc42942..080b661028 100644 --- a/jsapp/js/api/models/organizationAssetUsageResponseNlpUsageCurrentPeriod.ts +++ b/jsapp/js/api/models/organizationsAssetUsageListParams.ts @@ -10,7 +10,13 @@ The endpoints are grouped by area of intended use. Each category contains relate * OpenAPI spec version: 2.0.0 (api_v2) */ -export type OrganizationAssetUsageResponseNlpUsageCurrentPeriod = { - total_nlp_asr_seconds: number - total_nlp_mt_characters: number +export type OrganizationsAssetUsageListParams = { + /** + * Paginate results with limit parameter + */ + limit?: number + /** + * Paginate results with offset parameter + */ + offset?: number } diff --git a/jsapp/js/api/models/paginatedOrganizationAssetUsageResponseList.ts b/jsapp/js/api/models/paginatedCustomAssetUsageList.ts similarity index 82% rename from jsapp/js/api/models/paginatedOrganizationAssetUsageResponseList.ts rename to jsapp/js/api/models/paginatedCustomAssetUsageList.ts index 216cd05b87..84a0b91f0b 100644 --- a/jsapp/js/api/models/paginatedOrganizationAssetUsageResponseList.ts +++ b/jsapp/js/api/models/paginatedCustomAssetUsageList.ts @@ -9,13 +9,13 @@ The endpoints are grouped by area of intended use. Each category contains relate **General note**: All projects (whether deployed or draft), as well as all library content (questions, blocks, templates, and collections) in the user-facing application are represented in the API as "assets". * OpenAPI spec version: 2.0.0 (api_v2) */ -import type { OrganizationAssetUsageResponse } from './organizationAssetUsageResponse' +import type { CustomAssetUsage } from './customAssetUsage' -export interface PaginatedOrganizationAssetUsageResponseList { +export interface PaginatedCustomAssetUsageList { count: number /** @nullable */ next?: string | null /** @nullable */ previous?: string | null - results: OrganizationAssetUsageResponse[] + results: CustomAssetUsage[] } diff --git a/jsapp/js/api/react-query/user-team-organization-usage.ts b/jsapp/js/api/react-query/user-team-organization-usage.ts index 9fd9a5538e..82b35c9c54 100644 --- a/jsapp/js/api/react-query/user-team-organization-usage.ts +++ b/jsapp/js/api/react-query/user-team-organization-usage.ts @@ -47,6 +47,8 @@ import type { OrganizationResponse } from '../models/organizationResponse' import type { OrganizationServiceUsageResponse } from '../models/organizationServiceUsageResponse' +import type { OrganizationsAssetUsageListParams } from '../models/organizationsAssetUsageListParams' + import type { OrganizationsInvitesListParams } from '../models/organizationsInvitesListParams' import type { OrganizationsListParams } from '../models/organizationsListParams' @@ -57,14 +59,14 @@ import type { PaginatedAssetList } from '../models/paginatedAssetList' import type { PaginatedAssetUsageResponseList } from '../models/paginatedAssetUsageResponseList' +import type { PaginatedCustomAssetUsageList } from '../models/paginatedCustomAssetUsageList' + import type { PaginatedEmailAddressList } from '../models/paginatedEmailAddressList' import type { PaginatedInviteResponseList } from '../models/paginatedInviteResponseList' import type { PaginatedMemberListResponseList } from '../models/paginatedMemberListResponseList' -import type { PaginatedOrganizationAssetUsageResponseList } from '../models/paginatedOrganizationAssetUsageResponseList' - import type { PaginatedOrganizationResponseList } from '../models/paginatedOrganizationResponseList' import type { PaginatedProjectViewAssetResponseList } from '../models/paginatedProjectViewAssetResponseList' @@ -495,34 +497,50 @@ export const useOrganizationsPartialUpdate = { - return `/api/v2/organizations/${uidOrganization}/asset_usage/` +export const getOrganizationsAssetUsageListUrl = ( + uidOrganization: string, + params?: OrganizationsAssetUsageListParams, +) => { + const normalizedParams = new URLSearchParams() + + Object.entries(params || {}).forEach(([key, value]) => { + if (value !== undefined) { + normalizedParams.append(key, value === null ? 'null' : value.toString()) + } + }) + + const stringifiedParams = normalizedParams.toString() + + return stringifiedParams.length > 0 + ? `/api/v2/organizations/${uidOrganization}/asset_usage/?${stringifiedParams}` + : `/api/v2/organizations/${uidOrganization}/asset_usage/` } -export const organizationsAssetUsageRetrieve = async ( +export const organizationsAssetUsageList = async ( uidOrganization: string, + params?: OrganizationsAssetUsageListParams, options?: RequestInit, -): Promise => { - return fetchWithAuth( - getOrganizationsAssetUsageRetrieveUrl(uidOrganization), +): Promise => { + return fetchWithAuth( + getOrganizationsAssetUsageListUrl(uidOrganization, params), { ...options, method: 'GET', @@ -530,50 +548,55 @@ export const organizationsAssetUsageRetrieve = async ( ) } -export const getOrganizationsAssetUsageRetrieveQueryKey = (uidOrganization: string) => { - return ['api', 'v2', 'organizations', uidOrganization, 'asset_usage'] as const +export const getOrganizationsAssetUsageListQueryKey = ( + uidOrganization: string, + params?: OrganizationsAssetUsageListParams, +) => { + return ['api', 'v2', 'organizations', uidOrganization, 'asset_usage', ...(params ? [params] : [])] as const } -export const getOrganizationsAssetUsageRetrieveQueryOptions = < - TData = Awaited>, +export const getOrganizationsAssetUsageListQueryOptions = < + TData = Awaited>, TError = ErrorDetail, >( uidOrganization: string, + params?: OrganizationsAssetUsageListParams, options?: { - query?: UseQueryOptions>, TError, TData> + query?: UseQueryOptions>, TError, TData> request?: SecondParameter }, ) => { const { query: queryOptions, request: requestOptions } = options ?? {} - const queryKey = queryOptions?.queryKey ?? getOrganizationsAssetUsageRetrieveQueryKey(uidOrganization) + const queryKey = queryOptions?.queryKey ?? getOrganizationsAssetUsageListQueryKey(uidOrganization, params) - const queryFn: QueryFunction>> = ({ signal }) => - organizationsAssetUsageRetrieve(uidOrganization, { signal, ...requestOptions }) + const queryFn: QueryFunction>> = ({ signal }) => + organizationsAssetUsageList(uidOrganization, params, { signal, ...requestOptions }) return { queryKey, queryFn, enabled: !!uidOrganization, ...queryOptions } as UseQueryOptions< - Awaited>, + Awaited>, TError, TData > & { queryKey: QueryKey } } -export type OrganizationsAssetUsageRetrieveQueryResult = NonNullable< - Awaited> +export type OrganizationsAssetUsageListQueryResult = NonNullable< + Awaited> > -export type OrganizationsAssetUsageRetrieveQueryError = ErrorDetail +export type OrganizationsAssetUsageListQueryError = ErrorDetail -export function useOrganizationsAssetUsageRetrieve< - TData = Awaited>, +export function useOrganizationsAssetUsageList< + TData = Awaited>, TError = ErrorDetail, >( uidOrganization: string, + params?: OrganizationsAssetUsageListParams, options?: { - query?: UseQueryOptions>, TError, TData> + query?: UseQueryOptions>, TError, TData> request?: SecondParameter }, ): UseQueryResult & { queryKey: QueryKey } { - const queryOptions = getOrganizationsAssetUsageRetrieveQueryOptions(uidOrganization, options) + const queryOptions = getOrganizationsAssetUsageListQueryOptions(uidOrganization, params, options) const query = useQuery(queryOptions) as UseQueryResult & { queryKey: QueryKey } diff --git a/kobo/apps/organizations/views.py b/kobo/apps/organizations/views.py index e47e125a81..c20fc0d56d 100644 --- a/kobo/apps/organizations/views.py +++ b/kobo/apps/organizations/views.py @@ -32,7 +32,6 @@ MemberPatchRequest, ) from kpi.schema_extensions.v2.organizations.serializers import ( - OrganizationAssetUsageResponse, OrganizationPatchPayload, OrganizationServiceUsageResponse, ) @@ -144,11 +143,28 @@ def get_queryset(self, *args, **kwargs): asset_usage=extend_schema( description=read_md('kpi', 'organizations/org_asset_usage.md'), responses=open_api_200_ok_response( - OrganizationAssetUsageResponse(many=True), + CustomAssetUsageSerializer(many=True), require_auth=False, raise_access_forbidden=False, validate_payload=False, ), + parameters=[ + OpenApiParameter( + name='offset', + type=int, + location=OpenApiParameter.QUERY, + required=False, + description='Paginate results with offset parameter', + ), + OpenApiParameter( + name='limit', + type=int, + location=OpenApiParameter.QUERY, + required=False, + description='Paginate results with limit parameter', + ), + ], + operation_id='api_v2_organizations_asset_usage_list', ), assets=extend_schema( description=read_md('kpi', 'organizations/org_assets.md'), diff --git a/kpi/paginators.py b/kpi/paginators.py index 451ef48627..b6596c65f4 100644 --- a/kpi/paginators.py +++ b/kpi/paginators.py @@ -119,14 +119,6 @@ def get_paginated_response_schema(self, schema): } -class AssetUsagePagination(PageNumberPagination): - """ - Pagination class for usage project breakdown table. - """ - page_size = 8 - page_size_query_param = 'page_size' - - class DataPagination(LimitOffsetPagination): """ Pagination class for submissions. diff --git a/kpi/schema_extensions/v2/organizations/serializers.py b/kpi/schema_extensions/v2/organizations/serializers.py index 874415aca5..be9848ac62 100644 --- a/kpi/schema_extensions/v2/organizations/serializers.py +++ b/kpi/schema_extensions/v2/organizations/serializers.py @@ -2,29 +2,8 @@ from kobo.apps.organizations.models import OrganizationType from kpi.utils.schema_extensions.serializers import inline_serializer_class -from .fields import ( - AssetField, - NlpUsageAllTime, - NlpUsageCurrentPeriod, - TotalNlpUsageField, - TotalSubmissionCountField, -) from ..service_usage.fields import BalancesField - -OrganizationAssetUsageResponse = inline_serializer_class( - name='OrganizationAssetUsageResponse', - fields={ - 'asset': AssetField(), - 'asset__name': serializers.CharField(), - 'nlp_usage_current_period': NlpUsageCurrentPeriod(), - 'nlp_usage_all_time': NlpUsageAllTime(), - 'storage_bytes': serializers.IntegerField(), - 'submission_count_current_period': serializers.IntegerField(), - 'submission_count_all_time': serializers.IntegerField(), - 'deployment_status': serializers.CharField(), - }, -) - +from .fields import TotalNlpUsageField, TotalSubmissionCountField OrganizationServiceUsageResponse = inline_serializer_class( name='OrganizationServiceUsageResponse', diff --git a/kpi/serializers/v2/service_usage.py b/kpi/serializers/v2/service_usage.py index a7fce7821a..ce9e351adb 100644 --- a/kpi/serializers/v2/service_usage.py +++ b/kpi/serializers/v2/service_usage.py @@ -1,19 +1,29 @@ +from drf_spectacular.types import OpenApiTypes +from drf_spectacular.utils import extend_schema_field from rest_framework import serializers from rest_framework.fields import empty from kobo.apps.organizations.utils import get_billing_dates from kpi.deployment_backends.openrosa_backend import OpenRosaDeploymentBackend -from kpi.models.asset import Asset +from kpi.models.asset import Asset, AssetDeploymentStatus +from kpi.schema_extensions.v2.organizations.fields import UrlField +from kpi.utils.schema_extensions.fields import HyperlinkedIdentityFieldWithSchemaField from kpi.utils.usage_calculator import ServiceUsageCalculator +class NlpUsageSerializer(serializers.Serializer): + total_nlp_asr_seconds = serializers.IntegerField() + total_nlp_mt_characters = serializers.IntegerField() + + class AssetUsageSerializer(serializers.HyperlinkedModelSerializer): - asset = serializers.HyperlinkedIdentityField( + asset = HyperlinkedIdentityFieldWithSchemaField( + schema_field=UrlField, lookup_field='uid', lookup_url_kwarg='uid_asset', view_name='asset-detail', ) - asset__name = serializers.ReadOnlyField(source='name') + asset__name = serializers.CharField(source='name', read_only=True) nlp_usage_current_period = serializers.SerializerMethodField() nlp_usage_all_time = serializers.SerializerMethodField() storage_bytes = serializers.SerializerMethodField() @@ -38,23 +48,28 @@ def __init__(self, instance=None, data=empty, **kwargs): organization = self.context.get('organization') self._period_start, _ = get_billing_dates(organization) + @extend_schema_field(NlpUsageSerializer) def get_nlp_usage_current_period(self, asset): return self._get_nlp_tracking_data(asset, self._period_start) + @extend_schema_field(NlpUsageSerializer) def get_nlp_usage_all_time(self, asset): return self._get_nlp_tracking_data(asset) + @extend_schema_field(OpenApiTypes.INT) def get_submission_count_current_period(self, asset): if not asset.has_deployment: return 0 return asset.deployment.submission_count_since_date(self._period_start) + @extend_schema_field(OpenApiTypes.INT) def get_submission_count_all_time(self, asset): if not asset.has_deployment: return 0 return asset.deployment.submission_count_since_date() + @extend_schema_field(OpenApiTypes.INT) def get_storage_bytes(self, asset): # Get value from asset deployment (if it has deployment) if not asset.has_deployment: @@ -79,6 +94,7 @@ class CustomAssetUsageSerializer(AssetUsageSerializer): class Meta(AssetUsageSerializer.Meta): fields = AssetUsageSerializer.Meta.fields + ('deployment_status',) + @extend_schema_field(serializers.ChoiceField(choices=AssetDeploymentStatus)) def get_deployment_status(self, asset): return asset.deployment_status diff --git a/kpi/views/v2/asset_usage.py b/kpi/views/v2/asset_usage.py index 27d8ea35a2..89bd64183e 100644 --- a/kpi/views/v2/asset_usage.py +++ b/kpi/views/v2/asset_usage.py @@ -3,7 +3,6 @@ from rest_framework.mixins import ListModelMixin from kpi.models.asset import Asset -from kpi.paginators import AssetUsagePagination from kpi.permissions import IsAuthenticated from kpi.schema_extensions.v2.asset_usage.serializers import AssetUsageResponse from kpi.serializers.v2.service_usage import AssetUsageSerializer @@ -35,7 +34,6 @@ class AssetUsageViewSet(ListModelMixin, viewsets.GenericViewSet): permission_classes = (IsAuthenticated,) serializer_class = AssetUsageSerializer - pagination_class = AssetUsagePagination def get_queryset(self): return Asset.objects.defer('content').filter(owner=self.request.user) diff --git a/static/openapi/schema_v2.json b/static/openapi/schema_v2.json index b3bb6d980d..28577144a6 100644 --- a/static/openapi/schema_v2.json +++ b/static/openapi/schema_v2.json @@ -1088,19 +1088,19 @@ "description": "## Get user's asset usage\n", "parameters": [ { - "name": "page", + "name": "limit", "required": false, "in": "query", - "description": "A page number within the paginated result set.", + "description": "Number of results to return per page.", "schema": { "type": "integer" } }, { - "name": "page_size", + "name": "offset", "required": false, "in": "query", - "description": "Number of results to return per page.", + "description": "The initial index from which to return the results.", "schema": { "type": "integer" } @@ -8267,9 +8267,25 @@ }, "/api/v2/organizations/{uid_organization}/asset_usage/": { "get": { - "operationId": "api_v2_organizations_asset_usage_retrieve", + "operationId": "api_v2_organizations_asset_usage_list", "description": "## Retrieve organization asset usage tracker\n\nTracks the total usage of each asset for the user in the given organization\n", "parameters": [ + { + "in": "query", + "name": "limit", + "schema": { + "type": "integer" + }, + "description": "Paginate results with limit parameter" + }, + { + "in": "query", + "name": "offset", + "schema": { + "type": "integer" + }, + "description": "Paginate results with offset parameter" + }, { "in": "path", "name": "uid_organization", @@ -8296,7 +8312,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PaginatedOrganizationAssetUsageResponseList" + "$ref": "#/components/schemas/PaginatedCustomAssetUsageList" } } }, @@ -14145,6 +14161,67 @@ } ] }, + "CustomAssetUsage": { + "type": "object", + "properties": { + "asset": { + "type": "string", + "format": "uri", + "example": "https://kf.kobotoolbox.org/api/v2/organizations/orgzeph7Ub8tVmJ82JBbH96n/", + "readOnly": true + }, + "asset__name": { + "type": "string", + "readOnly": true + }, + "nlp_usage_current_period": { + "allOf": [ + { + "$ref": "#/components/schemas/NlpUsage" + } + ], + "readOnly": true + }, + "nlp_usage_all_time": { + "allOf": [ + { + "$ref": "#/components/schemas/NlpUsage" + } + ], + "readOnly": true + }, + "storage_bytes": { + "type": "integer", + "readOnly": true + }, + "submission_count_current_period": { + "type": "integer", + "readOnly": true + }, + "submission_count_all_time": { + "type": "integer", + "readOnly": true + }, + "deployment_status": { + "allOf": [ + { + "$ref": "#/components/schemas/DeploymentStatusEnum" + } + ], + "readOnly": true + } + }, + "required": [ + "asset", + "asset__name", + "deployment_status", + "nlp_usage_all_time", + "nlp_usage_current_period", + "storage_bytes", + "submission_count_all_time", + "submission_count_current_period" + ] + }, "CustomerPortal": { "type": "object", "properties": { @@ -14428,6 +14505,15 @@ "version_id" ] }, + "DeploymentStatusEnum": { + "enum": [ + "archived", + "deployed", + "draft" + ], + "type": "string", + "description": "* `archived` - archived\n* `deployed` - deployed\n* `draft` - draft" + }, "EmailAddress": { "type": "object", "properties": { @@ -16172,6 +16258,21 @@ "type": "string", "description": "* `admin` - admin\n* `member` - member\n* `owner` - owner" }, + "NlpUsage": { + "type": "object", + "properties": { + "total_nlp_asr_seconds": { + "type": "integer" + }, + "total_nlp_mt_characters": { + "type": "integer" + } + }, + "required": [ + "total_nlp_asr_seconds", + "total_nlp_mt_characters" + ] + }, "NullableServiceUsageBalanceData": { "oneOf": [ { @@ -16289,71 +16390,6 @@ "html" ] }, - "OrganizationAssetUsageResponse": { - "type": "object", - "properties": { - "asset": { - "type": "string", - "format": "uri", - "example": "https://kf.kobotoolbox.org/api/v2/organizations/orgzeph7Ub8tVmJ82JBbH96n/assets/" - }, - "asset__name": { - "type": "string" - }, - "nlp_usage_current_period": { - "type": "object", - "properties": { - "total_nlp_asr_seconds": { - "type": "integer" - }, - "total_nlp_mt_characters": { - "type": "integer" - } - }, - "required": [ - "total_nlp_asr_seconds", - "total_nlp_mt_characters" - ] - }, - "nlp_usage_all_time": { - "type": "object", - "properties": { - "total_nlp_asr_seconds": { - "type": "integer" - }, - "total_nlp_mt_characters": { - "type": "integer" - } - }, - "required": [ - "total_nlp_asr_seconds", - "total_nlp_mt_characters" - ] - }, - "storage_bytes": { - "type": "integer" - }, - "submission_count_current_period": { - "type": "integer" - }, - "submission_count_all_time": { - "type": "integer" - }, - "deployment_status": { - "type": "string" - } - }, - "required": [ - "asset", - "asset__name", - "deployment_status", - "nlp_usage_all_time", - "nlp_usage_current_period", - "storage_bytes", - "submission_count_all_time", - "submission_count_current_period" - ] - }, "OrganizationResponse": { "type": "object", "properties": { @@ -16749,13 +16785,13 @@ "type": "string", "nullable": true, "format": "uri", - "example": "http://api.example.org/accounts/?page=4" + "example": "http://api.example.org/accounts/?offset=400&limit=100" }, "previous": { "type": "string", "nullable": true, "format": "uri", - "example": "http://api.example.org/accounts/?page=2" + "example": "http://api.example.org/accounts/?offset=200&limit=100" }, "results": { "type": "array", @@ -16796,6 +16832,37 @@ } } }, + "PaginatedCustomAssetUsageList": { + "type": "object", + "required": [ + "count", + "results" + ], + "properties": { + "count": { + "type": "integer", + "example": 123 + }, + "next": { + "type": "string", + "nullable": true, + "format": "uri", + "example": "http://api.example.org/accounts/?offset=400&limit=100" + }, + "previous": { + "type": "string", + "nullable": true, + "format": "uri", + "example": "http://api.example.org/accounts/?offset=200&limit=100" + }, + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CustomAssetUsage" + } + } + } + }, "PaginatedDataResponseList": { "type": "object", "required": [ @@ -17199,37 +17266,6 @@ } } }, - "PaginatedOrganizationAssetUsageResponseList": { - "type": "object", - "required": [ - "count", - "results" - ], - "properties": { - "count": { - "type": "integer", - "example": 123 - }, - "next": { - "type": "string", - "nullable": true, - "format": "uri", - "example": "http://api.example.org/accounts/?offset=400&limit=100" - }, - "previous": { - "type": "string", - "nullable": true, - "format": "uri", - "example": "http://api.example.org/accounts/?offset=200&limit=100" - }, - "results": { - "type": "array", - "items": { - "$ref": "#/components/schemas/OrganizationAssetUsageResponse" - } - } - } - }, "PaginatedOrganizationResponseList": { "type": "object", "required": [ diff --git a/static/openapi/schema_v2.yaml b/static/openapi/schema_v2.yaml index 9c181e1c02..aac328a0ef 100644 --- a/static/openapi/schema_v2.yaml +++ b/static/openapi/schema_v2.yaml @@ -738,16 +738,16 @@ paths: description: | ## Get user's asset usage parameters: - - name: page + - name: limit required: false in: query - description: A page number within the paginated result set. + description: Number of results to return per page. schema: type: integer - - name: page_size + - name: offset required: false in: query - description: Number of results to return per page. + description: The initial index from which to return the results. schema: type: integer tags: @@ -6016,12 +6016,22 @@ paths: description: '' /api/v2/organizations/{uid_organization}/asset_usage/: get: - operationId: api_v2_organizations_asset_usage_retrieve + operationId: api_v2_organizations_asset_usage_list description: | ## Retrieve organization asset usage tracker Tracks the total usage of each asset for the user in the given organization parameters: + - in: query + name: limit + schema: + type: integer + description: Paginate results with limit parameter + - in: query + name: offset + schema: + type: integer + description: Paginate results with offset parameter - in: path name: uid_organization schema: @@ -6038,7 +6048,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/PaginatedOrganizationAssetUsageResponseList' + $ref: '#/components/schemas/PaginatedCustomAssetUsageList' description: null '404': content: @@ -10207,6 +10217,47 @@ components: - file_type - metadata - user + CustomAssetUsage: + type: object + properties: + asset: + type: string + format: uri + example: https://kf.kobotoolbox.org/api/v2/organizations/orgzeph7Ub8tVmJ82JBbH96n/ + readOnly: true + asset__name: + type: string + readOnly: true + nlp_usage_current_period: + allOf: + - $ref: '#/components/schemas/NlpUsage' + readOnly: true + nlp_usage_all_time: + allOf: + - $ref: '#/components/schemas/NlpUsage' + readOnly: true + storage_bytes: + type: integer + readOnly: true + submission_count_current_period: + type: integer + readOnly: true + submission_count_all_time: + type: integer + readOnly: true + deployment_status: + allOf: + - $ref: '#/components/schemas/DeploymentStatusEnum' + readOnly: true + required: + - asset + - asset__name + - deployment_status + - nlp_usage_all_time + - nlp_usage_current_period + - storage_bytes + - submission_count_all_time + - submission_count_current_period CustomerPortal: type: object properties: @@ -10410,6 +10461,16 @@ components: - asset - backend - version_id + DeploymentStatusEnum: + enum: + - archived + - deployed + - draft + type: string + description: |- + * `archived` - archived + * `deployed` - deployed + * `draft` - draft EmailAddress: type: object properties: @@ -11651,6 +11712,16 @@ components: * `admin` - admin * `member` - member * `owner` - owner + NlpUsage: + type: object + properties: + total_nlp_asr_seconds: + type: integer + total_nlp_mt_characters: + type: integer + required: + - total_nlp_asr_seconds + - total_nlp_mt_characters NullableServiceUsageBalanceData: oneOf: - $ref: '#/components/schemas/ServiceUsageBalanceData' @@ -11733,52 +11804,6 @@ components: type: string required: - html - OrganizationAssetUsageResponse: - type: object - properties: - asset: - type: string - format: uri - example: https://kf.kobotoolbox.org/api/v2/organizations/orgzeph7Ub8tVmJ82JBbH96n/assets/ - asset__name: - type: string - nlp_usage_current_period: - type: object - properties: - total_nlp_asr_seconds: - type: integer - total_nlp_mt_characters: - type: integer - required: - - total_nlp_asr_seconds - - total_nlp_mt_characters - nlp_usage_all_time: - type: object - properties: - total_nlp_asr_seconds: - type: integer - total_nlp_mt_characters: - type: integer - required: - - total_nlp_asr_seconds - - total_nlp_mt_characters - storage_bytes: - type: integer - submission_count_current_period: - type: integer - submission_count_all_time: - type: integer - deployment_status: - type: string - required: - - asset - - asset__name - - deployment_status - - nlp_usage_all_time - - nlp_usage_current_period - - storage_bytes - - submission_count_all_time - - submission_count_current_period OrganizationResponse: type: object properties: @@ -12073,12 +12098,12 @@ components: type: string nullable: true format: uri - example: http://api.example.org/accounts/?page=4 + example: http://api.example.org/accounts/?offset=400&limit=100 previous: type: string nullable: true format: uri - example: http://api.example.org/accounts/?page=2 + example: http://api.example.org/accounts/?offset=200&limit=100 results: type: array items: @@ -12106,6 +12131,29 @@ components: type: array items: $ref: '#/components/schemas/AuditLogResponse' + PaginatedCustomAssetUsageList: + type: object + required: + - count + - results + properties: + count: + type: integer + example: 123 + next: + type: string + nullable: true + format: uri + example: http://api.example.org/accounts/?offset=400&limit=100 + previous: + type: string + nullable: true + format: uri + example: http://api.example.org/accounts/?offset=200&limit=100 + results: + type: array + items: + $ref: '#/components/schemas/CustomAssetUsage' PaginatedDataResponseList: type: object required: @@ -12405,29 +12453,6 @@ components: type: array items: $ref: '#/components/schemas/OneTimeAddOn' - PaginatedOrganizationAssetUsageResponseList: - type: object - required: - - count - - results - properties: - count: - type: integer - example: 123 - next: - type: string - nullable: true - format: uri - example: http://api.example.org/accounts/?offset=400&limit=100 - previous: - type: string - nullable: true - format: uri - example: http://api.example.org/accounts/?offset=200&limit=100 - results: - type: array - items: - $ref: '#/components/schemas/OrganizationAssetUsageResponse' PaginatedOrganizationResponseList: type: object required: