Skip to content

Commit

Permalink
feat(:angola:): start with utility function to format cvd codes
Browse files Browse the repository at this point in the history
AFFECTS PACKAGES:
@esri/arcgis-rest-feature-service
  • Loading branch information
jgravois committed Nov 13, 2018
1 parent 9b58c63 commit 717404f
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 112 deletions.
146 changes: 146 additions & 0 deletions packages/arcgis-rest-feature-service/src/formatCodedValues.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/* Copyright (c) 2018 Environmental Systems Research Institute, Inc.
* Apache-2.0 */

import { IRequestOptions } from "@esri/arcgis-rest-request";
import {
IField,
ILayerDefinition,
IFeature
} from "@esri/arcgis-rest-common-types";
import { IQueryFeaturesResponse } from "./query";
import { getFeatureService } from "./getFeatureService";

/**
* Request options to fetch a feature by id.
*/
export interface IFormatCodedValuesRequestOptions extends IRequestOptions {
/**
* Layer service url.
*/
url: string;
/**
* Unique identifier of the feature.
*/
queryResponse: IQueryFeaturesResponse;
/**
* * If a fieldset is provided, no internal metadata check will be issued to gather info about coded value domains.
*
* getFeatureService(url)
* .then(metadata => {
* queryFeatures({ url })
* .then(response => {
* formatCodedValues({
* url,
* queryResponse,
* fields: metadata.fields
* })
* .then(formattedResponse)
* })
* })
*/
fields?: IField[];
}

/**
* Replaces the raw coded domain values in a query response with descriptions (for legibility).
*
* ```js
* import { queryFeatures, formatCodedValues } from '@esri/arcgis-rest-feature-service';
*
* const url = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/ServiceRequest/FeatureServer/0";
*
* queryFeatures({ url })
* .then(queryResponse => {
* formatCodedValues({
* url,
* queryResponse
* })
* .then(formattedResponse)
* })
* ```
*
* @param requestOptions - Options for the request.
* @returns A Promise that will resolve with the addFeatures response.
*/
export function formatCodedValues(
requestOptions: IFormatCodedValuesRequestOptions
): Promise<IQueryFeaturesResponse> {
return new Promise(resolve => {
if (!requestOptions.fields) {
return getFeatureService(requestOptions.url, requestOptions).then(
(metadata: ILayerDefinition) => {
resolve((requestOptions.fields = metadata.fields));
}
);
} else {
resolve(requestOptions.fields);
}
}).then(fields => {
// turn the fields array into a POJO to avoid multiple calls to Array.find()
const fieldsObject: any = {};
const fieldsArray = fields as IField[];
fieldsArray.forEach((field: IField) => {
fieldsObject[field.name] = field;
});

// dont mutate original response
const clonedResponse = JSON.parse(
JSON.stringify(requestOptions.queryResponse)
);

clonedResponse.features.forEach((feature: IFeature) => {
for (const key in feature.attributes) {
/* istanbul ignore next */
if (!feature.attributes.hasOwnProperty(key)) continue;
feature.attributes[key] = convertAttribute(
feature.attributes,
fieldsObject[key]
);
}
});
return clonedResponse;
});
}

/**
* ripped off from https://github.com/GeoXForm/esri-to-geojson/blob/55d32955d8ef0acb26de70025539e7c7a37d838e/src/index.js#L193-L220
*
* Decodes an attributes CVD and standardizes any date fields
*
* @params {object} attribute - a single esri feature attribute
* @params {object} field - the field metadata describing that attribute
* @returns {object} outAttribute - the converted attribute
* @private
*/

function convertAttribute(attribute: any, field: IField) {
const inValue = attribute[field.name];
let value;

if (inValue === null) return inValue;

if (field.domain && field.domain.type === "codedValue") {
value = cvd(inValue, field);
} else {
value = inValue;
}
return value;
}

/**
* also ripped off from https://github.com/GeoXForm/esri-to-geojson/blob/55d32955d8ef0acb26de70025539e7c7a37d838e/src/index.js#L222-L235
*
* Looks up a value from a coded domain
*
* @params {integer} value - The original field value
* @params {object} field - metadata describing the attribute field
* @returns {string/integerfloat} - The decoded field value
* @private
*/

function cvd(value: any, field: IField) {
const domain = field.domain.codedValues.find((d: any) => {
return value === d.code;
});
return domain ? domain.name : value;
}
7 changes: 2 additions & 5 deletions packages/arcgis-rest-feature-service/src/getFeatureService.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
/* Copyright (c) 2018 Environmental Systems Research Institute, Inc.
* Apache-2.0 */

import {
request,
IRequestOptions
} from "@esri/arcgis-rest-request";
import { request, IRequestOptions } from "@esri/arcgis-rest-request";

import { ILayerDefinition } from "@esri/arcgis-rest-common-types";

Expand All @@ -25,7 +22,7 @@ import { ILayerDefinition } from "@esri/arcgis-rest-common-types";
*/
export function getFeatureService(
url: string,
requestOptions: IRequestOptions
requestOptions?: IRequestOptions
): Promise<ILayerDefinition> {
return request(url, requestOptions);
}
1 change: 1 addition & 0 deletions packages/arcgis-rest-feature-service/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export * from "./updateAttachment";
export * from "./deleteAttachments";
export * from "./queryRelated";
export * from "./getFeatureService";
export * from "./formatCodedValues";
116 changes: 9 additions & 107 deletions packages/arcgis-rest-feature-service/src/query.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2017 Environmental Systems Research Institute, Inc.
/* Copyright (c) 2017-2018 Environmental Systems Research Institute, Inc.
* Apache-2.0 */

import {
Expand All @@ -11,12 +11,9 @@ import {
IFeatureSet,
IFeature,
esriUnits,
IExtent,
IField,
ILayerDefinition
IExtent
} from "@esri/arcgis-rest-common-types";

import { getFeatureService } from "./getFeatureService";
import { ISharedQueryParams } from "./helpers";

/**
Expand Down Expand Up @@ -92,11 +89,12 @@ export interface IQueryFeaturesRequestOptions
returnTrueCurves?: false;
sqlFormat?: "none" | "standard" | "native";
returnExceededLimitFeatures?: boolean;
// if fields false, skip metadata check, dont massage query response
// if fields populated, skip metadata check, make cvds and dates readable in response
// if fields true, fetch metadata and make cvds and dates readable
// if fields missing, fetch metadata and make cvds and dates readable
fields?: any;
/**
* someday...
*
* If 'true' the query will be preceded by a metadata check to gather info about coded value domains and result values will be decoded. If a fieldset is provided it will be used to decode values and no internal metadata request will be issued.
*/
// formatCodedValues?: boolean | IField[];
}

export interface IQueryFeaturesResponse extends IFeatureSet {
Expand Down Expand Up @@ -163,37 +161,11 @@ export function getFeature(
*/
export function queryFeatures(
requestOptions: IQueryFeaturesRequestOptions
): Promise<IQueryFeaturesResponse | IQueryResponse> {
if (
typeof requestOptions.fields === "undefined" ||
(typeof requestOptions.fields === "boolean" && requestOptions.fields)
) {
// ensure custom fetch and authentication are passed through
const metadataOptions: IRequestOptions = {
httpMethod: "GET",
authentication: requestOptions.authentication || null,
fetch: requestOptions.fetch || null
};
// fetch metadata to retrieve information about coded value domains
return getFeatureService(requestOptions.url, metadataOptions).then(
(metadata: ILayerDefinition) => {
requestOptions.fields = metadata.fields;
return _queryFeatures(requestOptions);
}
);
} else {
return _queryFeatures(requestOptions);
}
}

function _queryFeatures(
requestOptions: IQueryFeaturesRequestOptions
): Promise<IQueryFeaturesResponse | IQueryResponse> {
const queryOptions: IQueryFeaturesRequestOptions = {
params: {},
httpMethod: "GET",
url: requestOptions.url,
fields: false,
...requestOptions
};

Expand All @@ -207,75 +179,5 @@ function _queryFeatures(
queryOptions.params.outFields = "*";
}

if (!requestOptions.fields) {
return request(`${queryOptions.url}/query`, queryOptions);
} else {
// turn the fields array into a POJO to avoid multiple calls to Array.find()
const fieldsObject: any = {};
queryOptions.fields.forEach((field: IField) => {
fieldsObject[field.name] = field;
});

return request(`${queryOptions.url}/query`, queryOptions).then(response => {
response.features.forEach((feature: IFeature) => {
for (const key in feature.attributes) {
if (!feature.attributes.hasOwnProperty(key)) continue;
feature.attributes[key] = convertAttribute(
feature.attributes,
fieldsObject[key]
);
}
});
return response;
});
}
}

/**
* ripped off from https://github.com/GeoXForm/esri-to-geojson/blob/55d32955d8ef0acb26de70025539e7c7a37d838e/src/index.js#L193-L220
*
* Decodes an attributes CVD and standardizes any date fields
*
* @params {object} attribute - a single esri feature attribute
* @params {object} field - the field metadata describing that attribute
* @returns {object} outAttribute - the converted attribute
* @private
*/

function convertAttribute(attribute: any, field: IField) {
const inValue = attribute[field.name];
let value;

if (inValue === null) return inValue;

if (field.domain && field.domain.type === "codedValue") {
value = cvd(inValue, field);
} else if (field.type === "esriFieldTypeDate") {
try {
value = new Date(inValue).toISOString();
} catch (e) {
value = inValue;
}
} else {
value = inValue;
}
return value;
}

/**
* also ripped off from https://github.com/GeoXForm/esri-to-geojson/blob/55d32955d8ef0acb26de70025539e7c7a37d838e/src/index.js#L222-L235
*
* Looks up a value from a coded domain
*
* @params {integer} value - The original field value
* @params {object} field - metadata describing the attribute field
* @returns {string/integerfloat} - The decoded field value
* @private
*/

function cvd(value: any, field: IField) {
const domain = field.domain.codedValues.find((d: any) => {
return value === d.code;
});
return domain ? domain.name : value;
return request(`${queryOptions.url}/query`, queryOptions);
}

0 comments on commit 717404f

Please sign in to comment.