diff --git a/TYPESCRIPT.md b/TYPESCRIPT.md index 7be9a5e4f3b17..ae23768558f9d 100644 --- a/TYPESCRIPT.md +++ b/TYPESCRIPT.md @@ -62,7 +62,7 @@ declare module '@elastic/eui' { 1. Open up the file and see how easy it would be to convert to TypeScript. 2. If it's very straightforward, go for it. 3. If it's not and you wish to stay focused on your own PR, get around the error by adding a type definition file in the same folder as the dependency, with the same name. -4. Minimally you will need to type what you are using in your PR. No need to go crazy to fully type the thing or you might be there for awhile depending on what's available. +4. Minimally you will need to type what you are using in your PR. No need to go crazy to fully type the thing or you might be there for a while depending on what's available. For example: diff --git a/docs/developer/architecture/code-exploration.asciidoc b/docs/developer/architecture/code-exploration.asciidoc index bb7222020180c..d9502e4cb47ee 100644 --- a/docs/developer/architecture/code-exploration.asciidoc +++ b/docs/developer/architecture/code-exploration.asciidoc @@ -86,9 +86,9 @@ Contains the Discover application and the saved search embeddable. Embeddables are re-usable widgets that can be rendered in any environment or plugin. Developers can embed them directly in their plugin. End users can dynamically add them to any embeddable containers. -- {kib-repo}blob/{branch}/src/plugins/es_ui_shared[esUiShared] +- {kib-repo}blob/{branch}/src/plugins/es_ui_shared/README.md[esUiShared] -WARNING: Missing README. +This plugin contains reusable code in the form of self-contained modules (or libraries). Each of these modules exports a set of functionality relevant to the domain of the module. - {kib-repo}blob/{branch}/src/plugins/expressions/README.md[expressions] diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist._constructor_.md new file mode 100644 index 0000000000000..3b60ac0f48edd --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist._constructor_.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [FieldList](./kibana-plugin-plugins-data-public.fieldlist.md) > [(constructor)](./kibana-plugin-plugins-data-public.fieldlist._constructor_.md) + +## FieldList.(constructor) + +Constructs a new instance of the `FieldList` class + +Signature: + +```typescript +constructor(indexPattern: IndexPattern, specs?: FieldSpec[], shortDotsEnable?: boolean, onNotification?: () => void); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| indexPattern | IndexPattern | | +| specs | FieldSpec[] | | +| shortDotsEnable | boolean | | +| onNotification | () => void | | + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.add.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.add.md new file mode 100644 index 0000000000000..ae3d82f0cc3ea --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.add.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [FieldList](./kibana-plugin-plugins-data-public.fieldlist.md) > [add](./kibana-plugin-plugins-data-public.fieldlist.add.md) + +## FieldList.add property + +Signature: + +```typescript +readonly add: (field: FieldSpec) => void; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.getall.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.getall.md new file mode 100644 index 0000000000000..da29a4de9acc8 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.getall.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [FieldList](./kibana-plugin-plugins-data-public.fieldlist.md) > [getAll](./kibana-plugin-plugins-data-public.fieldlist.getall.md) + +## FieldList.getAll property + +Signature: + +```typescript +readonly getAll: () => IndexPatternField[]; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.getbyname.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.getbyname.md new file mode 100644 index 0000000000000..af368d003423a --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.getbyname.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [FieldList](./kibana-plugin-plugins-data-public.fieldlist.md) > [getByName](./kibana-plugin-plugins-data-public.fieldlist.getbyname.md) + +## FieldList.getByName property + +Signature: + +```typescript +readonly getByName: (name: IndexPatternField['name']) => IndexPatternField | undefined; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.getbytype.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.getbytype.md new file mode 100644 index 0000000000000..16bae3ee7c555 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.getbytype.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [FieldList](./kibana-plugin-plugins-data-public.fieldlist.md) > [getByType](./kibana-plugin-plugins-data-public.fieldlist.getbytype.md) + +## FieldList.getByType property + +Signature: + +```typescript +readonly getByType: (type: IndexPatternField['type']) => any[]; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.md new file mode 100644 index 0000000000000..012b069430290 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.md @@ -0,0 +1,32 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [FieldList](./kibana-plugin-plugins-data-public.fieldlist.md) + +## FieldList class + +Signature: + +```typescript +export declare class FieldList extends Array implements IIndexPatternFieldList +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(indexPattern, specs, shortDotsEnable, onNotification)](./kibana-plugin-plugins-data-public.fieldlist._constructor_.md) | | Constructs a new instance of the FieldList class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [add](./kibana-plugin-plugins-data-public.fieldlist.add.md) | | (field: FieldSpec) => void | | +| [getAll](./kibana-plugin-plugins-data-public.fieldlist.getall.md) | | () => IndexPatternField[] | | +| [getByName](./kibana-plugin-plugins-data-public.fieldlist.getbyname.md) | | (name: IndexPatternField['name']) => IndexPatternField | undefined | | +| [getByType](./kibana-plugin-plugins-data-public.fieldlist.getbytype.md) | | (type: IndexPatternField['type']) => any[] | | +| [remove](./kibana-plugin-plugins-data-public.fieldlist.remove.md) | | (field: IFieldType) => void | | +| [removeAll](./kibana-plugin-plugins-data-public.fieldlist.removeall.md) | | () => void | | +| [replaceAll](./kibana-plugin-plugins-data-public.fieldlist.replaceall.md) | | (specs: FieldSpec[]) => void | | +| [toSpec](./kibana-plugin-plugins-data-public.fieldlist.tospec.md) | | () => {
count: number;
script: string | undefined;
lang: string | undefined;
conflictDescriptions: Record<string, string[]> | undefined;
name: string;
type: string;
esTypes: string[] | undefined;
scripted: boolean;
searchable: boolean;
aggregatable: boolean;
readFromDocValues: boolean;
subType: import("../types").IFieldSubType | undefined;
format: any;
}[] | | +| [update](./kibana-plugin-plugins-data-public.fieldlist.update.md) | | (field: FieldSpec) => void | | + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.remove.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.remove.md new file mode 100644 index 0000000000000..149410adb3550 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.remove.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [FieldList](./kibana-plugin-plugins-data-public.fieldlist.md) > [remove](./kibana-plugin-plugins-data-public.fieldlist.remove.md) + +## FieldList.remove property + +Signature: + +```typescript +readonly remove: (field: IFieldType) => void; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.removeall.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.removeall.md new file mode 100644 index 0000000000000..92a45349ad005 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.removeall.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [FieldList](./kibana-plugin-plugins-data-public.fieldlist.md) > [removeAll](./kibana-plugin-plugins-data-public.fieldlist.removeall.md) + +## FieldList.removeAll property + +Signature: + +```typescript +readonly removeAll: () => void; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.replaceall.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.replaceall.md new file mode 100644 index 0000000000000..5330440e6b96a --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.replaceall.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [FieldList](./kibana-plugin-plugins-data-public.fieldlist.md) > [replaceAll](./kibana-plugin-plugins-data-public.fieldlist.replaceall.md) + +## FieldList.replaceAll property + +Signature: + +```typescript +readonly replaceAll: (specs: FieldSpec[]) => void; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.tospec.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.tospec.md new file mode 100644 index 0000000000000..e646339feb495 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.tospec.md @@ -0,0 +1,25 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [FieldList](./kibana-plugin-plugins-data-public.fieldlist.md) > [toSpec](./kibana-plugin-plugins-data-public.fieldlist.tospec.md) + +## FieldList.toSpec property + +Signature: + +```typescript +readonly toSpec: () => { + count: number; + script: string | undefined; + lang: string | undefined; + conflictDescriptions: Record | undefined; + name: string; + type: string; + esTypes: string[] | undefined; + scripted: boolean; + searchable: boolean; + aggregatable: boolean; + readFromDocValues: boolean; + subType: import("../types").IFieldSubType | undefined; + format: any; + }[]; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.update.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.update.md new file mode 100644 index 0000000000000..c718e47b31b50 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldlist.update.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [FieldList](./kibana-plugin-plugins-data-public.fieldlist.md) > [update](./kibana-plugin-plugins-data-public.fieldlist.update.md) + +## FieldList.update property + +Signature: + +```typescript +readonly update: (field: FieldSpec) => void; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getindexpatternfieldlistcreator.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getindexpatternfieldlistcreator.md deleted file mode 100644 index 880acdc8956d4..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getindexpatternfieldlistcreator.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [getIndexPatternFieldListCreator](./kibana-plugin-plugins-data-public.getindexpatternfieldlistcreator.md) - -## getIndexPatternFieldListCreator variable - -Signature: - -```typescript -getIndexPatternFieldListCreator: ({ fieldFormats, onNotification, }: FieldListDependencies) => CreateIndexPatternFieldList -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.getall.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.getall.md new file mode 100644 index 0000000000000..070e36e303a80 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.getall.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IIndexPatternFieldList](./kibana-plugin-plugins-data-public.iindexpatternfieldlist.md) > [getAll](./kibana-plugin-plugins-data-public.iindexpatternfieldlist.getall.md) + +## IIndexPatternFieldList.getAll() method + +Signature: + +```typescript +getAll(): IndexPatternField[]; +``` +Returns: + +`IndexPatternField[]` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.getbyname.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.getbyname.md index 14b5aa7137dc2..e277df87fe908 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.getbyname.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.getbyname.md @@ -7,16 +7,16 @@ Signature: ```typescript -getByName(name: Field['name']): Field | undefined; +getByName(name: IndexPatternField['name']): IndexPatternField | undefined; ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| name | Field['name'] | | +| name | IndexPatternField['name'] | | Returns: -`Field | undefined` +`IndexPatternField | undefined` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.getbytype.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.getbytype.md index 3c65b78e5291d..9a7b3ab36b0c1 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.getbytype.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.getbytype.md @@ -7,16 +7,16 @@ Signature: ```typescript -getByType(type: Field['type']): Field[]; +getByType(type: IndexPatternField['type']): IndexPatternField[]; ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| type | Field['type'] | | +| type | IndexPatternField['type'] | | Returns: -`Field[]` +`IndexPatternField[]` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.md index 47d7c7491aa86..b068c4804c0dd 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.md @@ -7,7 +7,7 @@ Signature: ```typescript -export interface IIndexPatternFieldList extends Array +export interface IIndexPatternFieldList extends Array ``` ## Methods @@ -15,8 +15,11 @@ export interface IIndexPatternFieldList extends Array | Method | Description | | --- | --- | | [add(field)](./kibana-plugin-plugins-data-public.iindexpatternfieldlist.add.md) | | +| [getAll()](./kibana-plugin-plugins-data-public.iindexpatternfieldlist.getall.md) | | | [getByName(name)](./kibana-plugin-plugins-data-public.iindexpatternfieldlist.getbyname.md) | | | [getByType(type)](./kibana-plugin-plugins-data-public.iindexpatternfieldlist.getbytype.md) | | | [remove(field)](./kibana-plugin-plugins-data-public.iindexpatternfieldlist.remove.md) | | +| [removeAll()](./kibana-plugin-plugins-data-public.iindexpatternfieldlist.removeall.md) | | +| [replaceAll(specs)](./kibana-plugin-plugins-data-public.iindexpatternfieldlist.replaceall.md) | | | [update(field)](./kibana-plugin-plugins-data-public.iindexpatternfieldlist.update.md) | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.removeall.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.removeall.md new file mode 100644 index 0000000000000..55e7ca98e2637 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.removeall.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IIndexPatternFieldList](./kibana-plugin-plugins-data-public.iindexpatternfieldlist.md) > [removeAll](./kibana-plugin-plugins-data-public.iindexpatternfieldlist.removeall.md) + +## IIndexPatternFieldList.removeAll() method + +Signature: + +```typescript +removeAll(): void; +``` +Returns: + +`void` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.replaceall.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.replaceall.md new file mode 100644 index 0000000000000..c7e8cdd578bfe --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.replaceall.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IIndexPatternFieldList](./kibana-plugin-plugins-data-public.iindexpatternfieldlist.md) > [replaceAll](./kibana-plugin-plugins-data-public.iindexpatternfieldlist.replaceall.md) + +## IIndexPatternFieldList.replaceAll() method + +Signature: + +```typescript +replaceAll(specs: FieldSpec[]): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| specs | FieldSpec[] | | + +Returns: + +`void` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getfieldbyname.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getfieldbyname.md index e6a23c5c70aab..75cdfd0a2e22e 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getfieldbyname.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getfieldbyname.md @@ -7,7 +7,7 @@ Signature: ```typescript -getFieldByName(name: string): Field | void; +getFieldByName(name: string): IndexPatternField | undefined; ``` ## Parameters @@ -18,5 +18,5 @@ getFieldByName(name: string): Field | void; Returns: -`Field | void` +`IndexPatternField | undefined` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getformatterforfield.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getformatterforfield.md new file mode 100644 index 0000000000000..7984f7aff1d2d --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getformatterforfield.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) > [getFormatterForField](./kibana-plugin-plugins-data-public.indexpattern.getformatterforfield.md) + +## IndexPattern.getFormatterForField() method + +Signature: + +```typescript +getFormatterForField(field: IndexPatternField | IndexPatternField['spec']): FieldFormat; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| field | IndexPatternField | IndexPatternField['spec'] | | + +Returns: + +`FieldFormat` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getnonscriptedfields.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getnonscriptedfields.md index 4e49304484815..77ce6f6f23a67 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getnonscriptedfields.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getnonscriptedfields.md @@ -7,9 +7,9 @@ Signature: ```typescript -getNonScriptedFields(): Field[]; +getNonScriptedFields(): IndexPatternField[]; ``` Returns: -`Field[]` +`IndexPatternField[]` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getscriptedfields.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getscriptedfields.md index 9ab4f9a9aaed5..055f07367c96e 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getscriptedfields.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getscriptedfields.md @@ -7,9 +7,9 @@ Signature: ```typescript -getScriptedFields(): Field[]; +getScriptedFields(): IndexPatternField[]; ``` Returns: -`Field[]` +`IndexPatternField[]` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.gettimefield.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.gettimefield.md index 8e68e8c35aff7..24de0be3794bb 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.gettimefield.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.gettimefield.md @@ -7,9 +7,9 @@ Signature: ```typescript -getTimeField(): Field | undefined; +getTimeField(): IndexPatternField | undefined; ``` Returns: -`Field | undefined` +`IndexPatternField | undefined` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.md index a37f115358922..d340aaeeef25e 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.md @@ -42,6 +42,7 @@ export declare class IndexPattern implements IIndexPattern | [getAggregationRestrictions()](./kibana-plugin-plugins-data-public.indexpattern.getaggregationrestrictions.md) | | | | [getComputedFields()](./kibana-plugin-plugins-data-public.indexpattern.getcomputedfields.md) | | | | [getFieldByName(name)](./kibana-plugin-plugins-data-public.indexpattern.getfieldbyname.md) | | | +| [getFormatterForField(field)](./kibana-plugin-plugins-data-public.indexpattern.getformatterforfield.md) | | | | [getNonScriptedFields()](./kibana-plugin-plugins-data-public.indexpattern.getnonscriptedfields.md) | | | | [getScriptedFields()](./kibana-plugin-plugins-data-public.indexpattern.getscriptedfields.md) | | | | [getSourceFiltering()](./kibana-plugin-plugins-data-public.indexpattern.getsourcefiltering.md) | | | @@ -55,7 +56,7 @@ export declare class IndexPattern implements IIndexPattern | [popularizeField(fieldName, unit)](./kibana-plugin-plugins-data-public.indexpattern.popularizefield.md) | | | | [prepBody()](./kibana-plugin-plugins-data-public.indexpattern.prepbody.md) | | | | [refreshFields()](./kibana-plugin-plugins-data-public.indexpattern.refreshfields.md) | | | -| [removeScriptedField(field)](./kibana-plugin-plugins-data-public.indexpattern.removescriptedfield.md) | | | +| [removeScriptedField(fieldName)](./kibana-plugin-plugins-data-public.indexpattern.removescriptedfield.md) | | | | [save(saveAttempts)](./kibana-plugin-plugins-data-public.indexpattern.save.md) | | | | [toJSON()](./kibana-plugin-plugins-data-public.indexpattern.tojson.md) | | | | [toSpec()](./kibana-plugin-plugins-data-public.indexpattern.tospec.md) | | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.removescriptedfield.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.removescriptedfield.md index 2a6811f501152..42c6dd72b8c4e 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.removescriptedfield.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.removescriptedfield.md @@ -7,14 +7,14 @@ Signature: ```typescript -removeScriptedField(field: IFieldType): Promise; +removeScriptedField(fieldName: string): Promise; ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| field | IFieldType | | +| fieldName | string | | Returns: diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield._constructor_.md index 7a195702b6f13..10b65bdccdf87 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield._constructor_.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield._constructor_.md @@ -4,20 +4,20 @@ ## IndexPatternField.(constructor) -Constructs a new instance of the `Field` class +Constructs a new instance of the `IndexPatternField` class Signature: ```typescript -constructor(indexPattern: IIndexPattern, spec: FieldSpecExportFmt | FieldSpec | Field, shortDotsEnable: boolean, { fieldFormats, onNotification }: FieldDependencies); +constructor(indexPattern: IndexPattern, spec: FieldSpec, displayName: string, onNotification: OnNotification); ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| indexPattern | IIndexPattern | | -| spec | FieldSpecExportFmt | FieldSpec | Field | | -| shortDotsEnable | boolean | | -| { fieldFormats, onNotification } | FieldDependencies | | +| indexPattern | IndexPattern | | +| spec | FieldSpec | | +| displayName | string | | +| onNotification | OnNotification | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.aggregatable.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.aggregatable.md index 267c8f786b5dd..6ef87d08600a3 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.aggregatable.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.aggregatable.md @@ -7,5 +7,5 @@ Signature: ```typescript -aggregatable?: boolean; +get aggregatable(): boolean; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.conflictdescriptions.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.conflictdescriptions.md index ec19a4854bf0e..6d62053726197 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.conflictdescriptions.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.conflictdescriptions.md @@ -7,5 +7,7 @@ Signature: ```typescript -conflictDescriptions?: FieldSpecConflictDescriptions; +get conflictDescriptions(): Record | undefined; + +set conflictDescriptions(conflictDescriptions: Record | undefined); ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.count.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.count.md index 8e848276f21c4..84c0a75fd206d 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.count.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.count.md @@ -7,5 +7,7 @@ Signature: ```typescript -count?: number; +get count(): number; + +set count(count: number); ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.displayname.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.displayname.md index ed9630f92fc97..c0ce2fff419bf 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.displayname.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.displayname.md @@ -7,5 +7,5 @@ Signature: ```typescript -displayName?: string; +readonly displayName: string; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.estypes.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.estypes.md index dec74df099d43..ac088cb69a3d6 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.estypes.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.estypes.md @@ -7,5 +7,5 @@ Signature: ```typescript -esTypes?: string[]; +get esTypes(): string[] | undefined; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.filterable.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.filterable.md index 4290c4a2f86b3..1149047c0eccd 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.filterable.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.filterable.md @@ -7,5 +7,5 @@ Signature: ```typescript -filterable?: boolean; +get filterable(): boolean; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.format.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.format.md index d5df8ed628cb0..f28d5b1bca7e5 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.format.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.format.md @@ -7,5 +7,5 @@ Signature: ```typescript -format: any; +get format(): FieldFormat; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.indexpattern.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.indexpattern.md index 4acaaa8c0dc2c..3d145cce9d07d 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.indexpattern.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.indexpattern.md @@ -7,5 +7,5 @@ Signature: ```typescript -indexPattern?: IIndexPattern; +readonly indexPattern: IndexPattern; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.lang.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.lang.md index f731be8f613cf..0a8446d40e5ec 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.lang.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.lang.md @@ -7,5 +7,7 @@ Signature: ```typescript -lang?: string; +get lang(): string | undefined; + +set lang(lang: string | undefined); ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.md index d82999e7a96af..713b29ea3a3d3 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.md @@ -7,37 +7,43 @@ Signature: ```typescript -export declare class Field implements IFieldType +export declare class IndexPatternField implements IFieldType ``` ## Constructors | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(indexPattern, spec, shortDotsEnable, { fieldFormats, onNotification })](./kibana-plugin-plugins-data-public.indexpatternfield._constructor_.md) | | Constructs a new instance of the Field class | +| [(constructor)(indexPattern, spec, displayName, onNotification)](./kibana-plugin-plugins-data-public.indexpatternfield._constructor_.md) | | Constructs a new instance of the IndexPatternField class | ## Properties | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [$$spec](./kibana-plugin-plugins-data-public.indexpatternfield.__spec.md) | | FieldSpec | | | [aggregatable](./kibana-plugin-plugins-data-public.indexpatternfield.aggregatable.md) | | boolean | | -| [conflictDescriptions](./kibana-plugin-plugins-data-public.indexpatternfield.conflictdescriptions.md) | | FieldSpecConflictDescriptions | | +| [conflictDescriptions](./kibana-plugin-plugins-data-public.indexpatternfield.conflictdescriptions.md) | | Record<string, string[]> | undefined | | | [count](./kibana-plugin-plugins-data-public.indexpatternfield.count.md) | | number | | | [displayName](./kibana-plugin-plugins-data-public.indexpatternfield.displayname.md) | | string | | -| [esTypes](./kibana-plugin-plugins-data-public.indexpatternfield.estypes.md) | | string[] | | +| [esTypes](./kibana-plugin-plugins-data-public.indexpatternfield.estypes.md) | | string[] | undefined | | | [filterable](./kibana-plugin-plugins-data-public.indexpatternfield.filterable.md) | | boolean | | -| [format](./kibana-plugin-plugins-data-public.indexpatternfield.format.md) | | any | | -| [indexPattern](./kibana-plugin-plugins-data-public.indexpatternfield.indexpattern.md) | | IIndexPattern | | -| [lang](./kibana-plugin-plugins-data-public.indexpatternfield.lang.md) | | string | | +| [format](./kibana-plugin-plugins-data-public.indexpatternfield.format.md) | | FieldFormat | | +| [indexPattern](./kibana-plugin-plugins-data-public.indexpatternfield.indexpattern.md) | | IndexPattern | | +| [lang](./kibana-plugin-plugins-data-public.indexpatternfield.lang.md) | | string | undefined | | | [name](./kibana-plugin-plugins-data-public.indexpatternfield.name.md) | | string | | | [readFromDocValues](./kibana-plugin-plugins-data-public.indexpatternfield.readfromdocvalues.md) | | boolean | | -| [script](./kibana-plugin-plugins-data-public.indexpatternfield.script.md) | | string | | +| [script](./kibana-plugin-plugins-data-public.indexpatternfield.script.md) | | string | undefined | | | [scripted](./kibana-plugin-plugins-data-public.indexpatternfield.scripted.md) | | boolean | | | [searchable](./kibana-plugin-plugins-data-public.indexpatternfield.searchable.md) | | boolean | | | [sortable](./kibana-plugin-plugins-data-public.indexpatternfield.sortable.md) | | boolean | | -| [subType](./kibana-plugin-plugins-data-public.indexpatternfield.subtype.md) | | IFieldSubType | | -| [toSpec](./kibana-plugin-plugins-data-public.indexpatternfield.tospec.md) | | () => FieldSpecExportFmt | | +| [spec](./kibana-plugin-plugins-data-public.indexpatternfield.spec.md) | | FieldSpec | | +| [subType](./kibana-plugin-plugins-data-public.indexpatternfield.subtype.md) | | import("../types").IFieldSubType | undefined | | | [type](./kibana-plugin-plugins-data-public.indexpatternfield.type.md) | | string | | | [visualizable](./kibana-plugin-plugins-data-public.indexpatternfield.visualizable.md) | | boolean | | +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [toJSON()](./kibana-plugin-plugins-data-public.indexpatternfield.tojson.md) | | | +| [toSpec()](./kibana-plugin-plugins-data-public.indexpatternfield.tospec.md) | | | + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.name.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.name.md index cb24621e73209..c690edeafea6e 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.name.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.name.md @@ -7,5 +7,5 @@ Signature: ```typescript -name: string; +get name(): string; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.readfromdocvalues.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.readfromdocvalues.md index 4b012c26a8620..22f727e3c00e8 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.readfromdocvalues.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.readfromdocvalues.md @@ -7,5 +7,5 @@ Signature: ```typescript -readFromDocValues?: boolean; +get readFromDocValues(): boolean; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.script.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.script.md index 132ba25a47637..27f9c797c92f2 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.script.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.script.md @@ -7,5 +7,7 @@ Signature: ```typescript -script?: string; +get script(): string | undefined; + +set script(script: string | undefined); ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.scripted.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.scripted.md index 1dd6bc865a75d..f3810b9698a11 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.scripted.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.scripted.md @@ -7,5 +7,5 @@ Signature: ```typescript -scripted?: boolean; +get scripted(): boolean; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.searchable.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.searchable.md index 42f984d851435..431907b154dc0 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.searchable.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.searchable.md @@ -7,5 +7,5 @@ Signature: ```typescript -searchable?: boolean; +get searchable(): boolean; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.sortable.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.sortable.md index 72d225185140b..871320c9586d3 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.sortable.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.sortable.md @@ -7,5 +7,5 @@ Signature: ```typescript -sortable?: boolean; +get sortable(): boolean; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.__spec.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.spec.md similarity index 56% rename from docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.__spec.md rename to docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.spec.md index f52a3324af36f..9884faaa6c7bb 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.__spec.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.spec.md @@ -1,11 +1,11 @@ -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternField](./kibana-plugin-plugins-data-public.indexpatternfield.md) > [$$spec](./kibana-plugin-plugins-data-public.indexpatternfield.__spec.md) +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternField](./kibana-plugin-plugins-data-public.indexpatternfield.md) > [spec](./kibana-plugin-plugins-data-public.indexpatternfield.spec.md) -## IndexPatternField.$$spec property +## IndexPatternField.spec property Signature: ```typescript -$$spec: FieldSpec; +readonly spec: FieldSpec; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.subtype.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.subtype.md index 2d807f8a5739c..5c3c4d54ad099 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.subtype.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.subtype.md @@ -7,5 +7,5 @@ Signature: ```typescript -subType?: IFieldSubType; +get subType(): import("../types").IFieldSubType | undefined; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.tojson.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.tojson.md new file mode 100644 index 0000000000000..a6a3a5a093c8e --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.tojson.md @@ -0,0 +1,41 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternField](./kibana-plugin-plugins-data-public.indexpatternfield.md) > [toJSON](./kibana-plugin-plugins-data-public.indexpatternfield.tojson.md) + +## IndexPatternField.toJSON() method + +Signature: + +```typescript +toJSON(): { + count: number; + script: string | undefined; + lang: string | undefined; + conflictDescriptions: Record | undefined; + name: string; + type: string; + esTypes: string[] | undefined; + scripted: boolean; + searchable: boolean; + aggregatable: boolean; + readFromDocValues: boolean; + subType: import("../types").IFieldSubType | undefined; + }; +``` +Returns: + +`{ + count: number; + script: string | undefined; + lang: string | undefined; + conflictDescriptions: Record | undefined; + name: string; + type: string; + esTypes: string[] | undefined; + scripted: boolean; + searchable: boolean; + aggregatable: boolean; + readFromDocValues: boolean; + subType: import("../types").IFieldSubType | undefined; + }` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.tospec.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.tospec.md index 35714faa03bc9..5037cb0049e82 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.tospec.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.tospec.md @@ -2,10 +2,42 @@ [Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternField](./kibana-plugin-plugins-data-public.indexpatternfield.md) > [toSpec](./kibana-plugin-plugins-data-public.indexpatternfield.tospec.md) -## IndexPatternField.toSpec property +## IndexPatternField.toSpec() method Signature: ```typescript -toSpec: () => FieldSpecExportFmt; +toSpec(): { + count: number; + script: string | undefined; + lang: string | undefined; + conflictDescriptions: Record | undefined; + name: string; + type: string; + esTypes: string[] | undefined; + scripted: boolean; + searchable: boolean; + aggregatable: boolean; + readFromDocValues: boolean; + subType: import("../types").IFieldSubType | undefined; + format: any; + }; ``` +Returns: + +`{ + count: number; + script: string | undefined; + lang: string | undefined; + conflictDescriptions: Record | undefined; + name: string; + type: string; + esTypes: string[] | undefined; + scripted: boolean; + searchable: boolean; + aggregatable: boolean; + readFromDocValues: boolean; + subType: import("../types").IFieldSubType | undefined; + format: any; + }` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.type.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.type.md index c8483c9b83c9a..45085b9e74bcc 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.type.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.type.md @@ -7,5 +7,5 @@ Signature: ```typescript -type: string; +get type(): string; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.visualizable.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.visualizable.md index dd661ae779c11..9ed689752503a 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.visualizable.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.visualizable.md @@ -7,5 +7,5 @@ Signature: ```typescript -visualizable?: boolean; +get visualizable(): boolean; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md index db41936f35cca..c8d45804a3729 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md @@ -10,6 +10,7 @@ | --- | --- | | [AggParamType](./kibana-plugin-plugins-data-public.aggparamtype.md) | | | [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) | | +| [FieldList](./kibana-plugin-plugins-data-public.fieldlist.md) | | | [FilterManager](./kibana-plugin-plugins-data-public.filtermanager.md) | | | [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) | | | [IndexPatternField](./kibana-plugin-plugins-data-public.indexpatternfield.md) | | @@ -103,7 +104,6 @@ | [extractSearchSourceReferences](./kibana-plugin-plugins-data-public.extractsearchsourcereferences.md) | | | [fieldFormats](./kibana-plugin-plugins-data-public.fieldformats.md) | | | [FilterBar](./kibana-plugin-plugins-data-public.filterbar.md) | | -| [getIndexPatternFieldListCreator](./kibana-plugin-plugins-data-public.getindexpatternfieldlistcreator.md) | | | [getKbnTypeNames](./kibana-plugin-plugins-data-public.getkbntypenames.md) | Get the esTypes known by all kbnFieldTypes {Array} | | [indexPatterns](./kibana-plugin-plugins-data-public.indexpatterns.md) | | | [injectSearchSourceReferences](./kibana-plugin-plugins-data-public.injectsearchsourcereferences.md) | | diff --git a/docs/development/plugins/kibana_utils/public/state_sync/kibana-plugin-plugins-kibana_utils-public-state_sync.createkbnurlstatestorage.md b/docs/development/plugins/kibana_utils/public/state_sync/kibana-plugin-plugins-kibana_utils-public-state_sync.createkbnurlstatestorage.md index 22f70ce22b574..478ba2d409acd 100644 --- a/docs/development/plugins/kibana_utils/public/state_sync/kibana-plugin-plugins-kibana_utils-public-state_sync.createkbnurlstatestorage.md +++ b/docs/development/plugins/kibana_utils/public/state_sync/kibana-plugin-plugins-kibana_utils-public-state_sync.createkbnurlstatestorage.md @@ -9,8 +9,10 @@ Creates [IKbnUrlStateStorage](./kibana-plugin-plugins-kibana_utils-public-state_ Signature: ```typescript -createKbnUrlStateStorage: ({ useHash, history }?: { +createKbnUrlStateStorage: ({ useHash, history, onGetError, onSetError, }?: { useHash: boolean; history?: History | undefined; + onGetError?: ((error: Error) => void) | undefined; + onSetError?: ((error: Error) => void) | undefined; }) => IKbnUrlStateStorage ``` diff --git a/docs/drilldowns/explore-underlying-data.asciidoc b/docs/drilldowns/explore-underlying-data.asciidoc index e0f940f73e96e..c2bba599730d8 100644 --- a/docs/drilldowns/explore-underlying-data.asciidoc +++ b/docs/drilldowns/explore-underlying-data.asciidoc @@ -33,9 +33,9 @@ applies the filters and time range created by the events that triggered the acti [role="screenshot"] image::images/explore_data_in_chart.png[Explore underlying data from chart] -You can disable this action by adding the following line to your `kibana.yml` config. +To enable this action add the following line to your `kibana.yml` config. ["source","yml"] ----------- -xpack.discoverEnhanced.actions.exploreDataInChart.enabled: false +xpack.discoverEnhanced.actions.exploreDataInChart.enabled: true ----------- diff --git a/docs/glossary.asciidoc b/docs/glossary.asciidoc index 07c0bfcf35cb7..51470513198b9 100644 --- a/docs/glossary.asciidoc +++ b/docs/glossary.asciidoc @@ -214,6 +214,13 @@ syslog, Apache, and other webserver logs. See [[k_glos]] == K +[[glossary-kibana-privileges]] {kib} privileges :: +// tag::kibana-privileges-def[] +Enable administrators to grant users read-only, read-write, or no access to +individual features within <> in {kib}. See +{kibana-ref}/kibana-privileges.html[{kib} privileges]. +// end::kibana-privileges-def[] + [[glossary-kql]] {kib} Query Language (KQL) :: // tag::kql-def[] The default language for querying in {kib}. KQL provides diff --git a/package.json b/package.json index aaa7ae7ee4684..becd670e4ddcf 100644 --- a/package.json +++ b/package.json @@ -117,10 +117,10 @@ ] }, "dependencies": { - "@babel/core": "^7.10.2", - "@babel/plugin-transform-modules-commonjs": "^7.10.1", - "@babel/register": "^7.10.1", - "@elastic/apm-rum": "^5.2.0", + "@babel/core": "^7.11.1", + "@babel/plugin-transform-modules-commonjs": "^7.10.4", + "@babel/register": "^7.10.5", + "@elastic/apm-rum": "^5.4.0", "@elastic/charts": "19.8.1", "@elastic/datemath": "5.0.3", "@elastic/elasticsearch": "7.9.0-rc.2", @@ -147,19 +147,18 @@ "JSONStream": "1.3.5", "abortcontroller-polyfill": "^1.4.0", "accept": "3.0.2", - "angular": "^1.7.9", - "angular-aria": "^1.7.9", + "angular": "^1.8.0", + "angular-aria": "^1.8.0", "angular-elastic": "^2.5.1", "angular-recursion": "^1.0.5", - "angular-route": "^1.7.9", - "angular-sanitize": "^1.7.9", + "angular-route": "^1.8.0", + "angular-sanitize": "^1.8.0", "angular-sortable-view": "^0.0.17", "autoprefixer": "^9.7.4", "babel-loader": "^8.0.6", "bluebird": "3.5.5", "boom": "^7.2.0", "brace": "0.11.1", - "browserslist-useragent": "^3.0.2", "cache-loader": "^4.1.0", "chalk": "^2.4.2", "check-disk-space": "^2.1.0", @@ -174,7 +173,7 @@ "deep-freeze-strict": "^1.1.1", "deepmerge": "^4.2.2", "del": "^5.1.0", - "elastic-apm-node": "^3.6.0", + "elastic-apm-node": "^3.7.0", "elasticsearch": "^16.7.0", "elasticsearch-browser": "^16.7.0", "execa": "^4.0.2", @@ -290,8 +289,8 @@ "yauzl": "2.10.0" }, "devDependencies": { - "@babel/parser": "^7.10.2", - "@babel/types": "^7.10.2", + "@babel/parser": "^7.11.2", + "@babel/types": "^7.11.0", "@elastic/eslint-config-kibana": "0.15.0", "@elastic/eslint-plugin-eui": "0.0.2", "@elastic/github-checks-reporter": "0.0.20b3", @@ -319,7 +318,6 @@ "@types/babel__core": "^7.1.2", "@types/bluebird": "^3.1.1", "@types/boom": "^7.2.0", - "@types/browserslist-useragent": "^3.0.0", "@types/chance": "^1.0.0", "@types/cheerio": "^0.22.10", "@types/chromedriver": "^81.0.0", @@ -440,7 +438,7 @@ "exit-hook": "^2.2.0", "faker": "1.1.0", "fetch-mock": "^7.3.9", - "geckodriver": "^1.19.0", + "geckodriver": "^1.20.0", "getopts": "^2.2.4", "grunt": "1.0.4", "grunt-available-tasks": "^0.6.3", diff --git a/packages/elastic-datemath/package.json b/packages/elastic-datemath/package.json index 15040a6243ff2..ad4190f981439 100644 --- a/packages/elastic-datemath/package.json +++ b/packages/elastic-datemath/package.json @@ -11,8 +11,8 @@ "kbn:watch": "yarn build --watch" }, "devDependencies": { - "@babel/cli": "^7.10.1", - "@babel/preset-env": "^7.10.2", + "@babel/cli": "^7.10.5", + "@babel/preset-env": "^7.11.0", "babel-plugin-add-module-exports": "^1.0.2", "moment": "^2.24.0" }, diff --git a/packages/kbn-analytics/package.json b/packages/kbn-analytics/package.json index bd3f5832b7140..873252ceb0a1a 100644 --- a/packages/kbn-analytics/package.json +++ b/packages/kbn-analytics/package.json @@ -14,7 +14,7 @@ "kbn:watch": "node scripts/build --source-maps --watch" }, "devDependencies": { - "@babel/cli": "^7.10.1", + "@babel/cli": "^7.10.5", "@kbn/dev-utils": "1.0.0", "@kbn/babel-preset": "1.0.0", "typescript": "3.9.5" diff --git a/packages/kbn-babel-preset/package.json b/packages/kbn-babel-preset/package.json index 83530beffd2b2..db1f2161b6e38 100644 --- a/packages/kbn-babel-preset/package.json +++ b/packages/kbn-babel-preset/package.json @@ -4,14 +4,14 @@ "version": "1.0.0", "license": "Apache-2.0", "dependencies": { - "@babel/plugin-proposal-class-properties": "^7.10.1", - "@babel/plugin-proposal-export-namespace-from": "^7.10.1", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.1", - "@babel/plugin-proposal-optional-chaining": "^7.10.1", - "@babel/plugin-proposal-private-methods": "^7.10.1", - "@babel/preset-env": "^7.10.2", - "@babel/preset-react": "^7.10.1", - "@babel/preset-typescript": "^7.10.1", + "@babel/plugin-proposal-class-properties": "^7.10.4", + "@babel/plugin-proposal-export-namespace-from": "^7.10.4", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4", + "@babel/plugin-proposal-optional-chaining": "^7.11.0", + "@babel/plugin-proposal-private-methods": "^7.10.4", + "@babel/preset-env": "^7.11.0", + "@babel/preset-react": "^7.10.4", + "@babel/preset-typescript": "^7.10.4", "babel-plugin-add-module-exports": "^1.0.2", "babel-plugin-filter-imports": "^3.0.0", "babel-plugin-styled-components": "^1.10.7", diff --git a/packages/kbn-i18n/package.json b/packages/kbn-i18n/package.json index c5da144688c3c..0f830acb284a0 100644 --- a/packages/kbn-i18n/package.json +++ b/packages/kbn-i18n/package.json @@ -12,8 +12,8 @@ "kbn:watch": "node scripts/build --watch --source-maps" }, "devDependencies": { - "@babel/cli": "^7.10.1", - "@babel/core": "^7.10.2", + "@babel/cli": "^7.10.5", + "@babel/core": "^7.11.1", "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", "@types/intl-relativeformat": "^2.1.0", diff --git a/packages/kbn-interpreter/package.json b/packages/kbn-interpreter/package.json index c6bb06e68b9c0..aef63229ebe96 100644 --- a/packages/kbn-interpreter/package.json +++ b/packages/kbn-interpreter/package.json @@ -9,16 +9,16 @@ "kbn:watch": "node scripts/build --dev --watch" }, "dependencies": { - "@babel/runtime": "^7.10.2", + "@babel/runtime": "^7.11.2", "@kbn/i18n": "1.0.0", "lodash": "^4.17.15", "uuid": "3.3.2" }, "devDependencies": { - "@babel/cli": "^7.10.1", - "@babel/core": "^7.10.2", - "@babel/plugin-transform-modules-commonjs": "^7.10.1", - "@babel/plugin-transform-runtime": "^7.10.1", + "@babel/cli": "^7.10.5", + "@babel/core": "^7.11.1", + "@babel/plugin-transform-modules-commonjs": "^7.10.4", + "@babel/plugin-transform-runtime": "^7.11.0", "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", "babel-loader": "^8.0.6", diff --git a/packages/kbn-optimizer/README.md b/packages/kbn-optimizer/README.md index 5d5c5e3b6eb74..13be836f0ea88 100644 --- a/packages/kbn-optimizer/README.md +++ b/packages/kbn-optimizer/README.md @@ -10,9 +10,9 @@ The [Webpack config][WebpackConfig] is designed to provide the majority of what Source maps are enabled except when building the distributable. They show the code actually being executed by the browser to strike a balance between debuggability and performance. They are not configurable at this time but will be configurable once we have a developer configuration solution that doesn't rely on the server (see [#55656](https://github.com/elastic/kibana/issues/55656)). -### IE Support +### Browser Support -To make front-end code easier to debug the optimizer uses the `BROWSERSLIST_ENV=dev` environment variable (by default) to build JS and CSS that is compatible with modern browsers. In order to support older browsers like IE in development you will need to specify the `BROWSERSLIST_ENV=production` environment variable or build a distributable for testing. +To make front-end code easier to debug the optimizer uses the `BROWSERSLIST_ENV=dev` environment variable (by default) to build JS and CSS that is compatible with modern browsers. In order to support all browsers that we support with the distributable you will need to specify the `BROWSERSLIST_ENV=production` environment variable or build a distributable for testing. ## Running the optimizer diff --git a/packages/kbn-optimizer/package.json b/packages/kbn-optimizer/package.json index e6eb5de31abd8..84e5c79e2e358 100644 --- a/packages/kbn-optimizer/package.json +++ b/packages/kbn-optimizer/package.json @@ -10,7 +10,7 @@ "kbn:watch": "yarn build --watch" }, "dependencies": { - "@babel/cli": "^7.10.1", + "@babel/cli": "^7.10.5", "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", "@kbn/ui-shared-deps": "1.0.0", diff --git a/packages/kbn-plugin-helpers/package.json b/packages/kbn-plugin-helpers/package.json index f370265876df3..45582ad2af97a 100644 --- a/packages/kbn-plugin-helpers/package.json +++ b/packages/kbn-plugin-helpers/package.json @@ -12,7 +12,7 @@ "plugin-helpers": "bin/plugin-helpers.js" }, "dependencies": { - "@babel/core": "^7.10.2", + "@babel/core": "^7.11.1", "argv-split": "^2.0.1", "commander": "^3.0.0", "del": "^5.1.0", diff --git a/packages/kbn-pm/package.json b/packages/kbn-pm/package.json index 188db0a8321a2..3e40bf40222e6 100644 --- a/packages/kbn-pm/package.json +++ b/packages/kbn-pm/package.json @@ -10,11 +10,11 @@ "prettier": "prettier --write './src/**/*.ts'" }, "devDependencies": { - "@babel/core": "^7.10.2", - "@babel/plugin-proposal-class-properties": "^7.10.1", - "@babel/plugin-proposal-object-rest-spread": "^7.10.1", - "@babel/preset-env": "^7.10.2", - "@babel/preset-typescript": "^7.10.1", + "@babel/core": "^7.11.1", + "@babel/plugin-proposal-class-properties": "^7.10.4", + "@babel/plugin-proposal-object-rest-spread": "^7.11.0", + "@babel/preset-env": "^7.11.0", + "@babel/preset-typescript": "^7.10.4", "@types/cmd-shim": "^2.0.0", "@types/cpy": "^5.1.0", "@types/dedent": "^0.7.0", diff --git a/packages/kbn-test/package.json b/packages/kbn-test/package.json index 38e4668fc1e42..9482ea83cc257 100644 --- a/packages/kbn-test/package.json +++ b/packages/kbn-test/package.json @@ -10,7 +10,7 @@ "kbn:watch": "yarn build --watch" }, "devDependencies": { - "@babel/cli": "^7.10.1", + "@babel/cli": "^7.10.5", "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", "@types/joi": "^13.4.2", diff --git a/packages/kbn-ui-framework/package.json b/packages/kbn-ui-framework/package.json index 7933ce06d6847..a095d9ac2a77f 100644 --- a/packages/kbn-ui-framework/package.json +++ b/packages/kbn-ui-framework/package.json @@ -30,7 +30,7 @@ "enzyme-adapter-react-16": "^1.9.1" }, "devDependencies": { - "@babel/core": "^7.10.2", + "@babel/core": "^7.11.1", "@elastic/eui": "0.0.55", "@kbn/babel-preset": "1.0.0", "@kbn/optimizer": "1.0.0", diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json index 3c03a52383f77..ae14777e8b44a 100644 --- a/packages/kbn-ui-shared-deps/package.json +++ b/packages/kbn-ui-shared-deps/package.json @@ -15,7 +15,7 @@ "@kbn/i18n": "1.0.0", "@kbn/monaco": "1.0.0", "abortcontroller-polyfill": "^1.4.0", - "angular": "^1.7.9", + "angular": "^1.8.0", "compression-webpack-plugin": "^4.0.0", "core-js": "^3.6.4", "custom-event-polyfill": "^0.3.0", diff --git a/rfcs/text/0001_lifecycle_setup.md b/rfcs/text/0001_lifecycle_setup.md index 01343b42f9a2d..bff200ca76472 100644 --- a/rfcs/text/0001_lifecycle_setup.md +++ b/rfcs/text/0001_lifecycle_setup.md @@ -124,7 +124,7 @@ all services and plugins, and then adding an empty `start` where it is necessary. Functionality can then be moved from `setup`->`start` on a case-by-case. -If this change doesn't happen for awhile, then it might make sense to follow +If this change doesn't happen for a while, then it might make sense to follow the reverse process to ensure the least impact. The migration guide will be updated to reflect the `setup` and `start` diff --git a/rfcs/text/0012_encryption_key_rotation.md b/rfcs/text/0012_encryption_key_rotation.md new file mode 100644 index 0000000000000..d984d1157a0a1 --- /dev/null +++ b/rfcs/text/0012_encryption_key_rotation.md @@ -0,0 +1,119 @@ +- Start Date: 2020-07-22 +- RFC PR: [#72828](https://github.com/elastic/kibana/pull/72828) +- Kibana Issue: (leave this empty) + +# Summary + +This RFC proposes a way of the encryption key (`xpack.encryptedSavedObjects.encryptionKey`) rotation that would allow administrators to seamlessly change existing encryption key without any data loss and manual intervention. + +# Basic example + +When administrators decide to rotate encryption key they will have to generate a new one and move the old key(s) to the `keyRotation` section in the `kibana.yml`: + +```yaml +xpack.encryptedSavedObjects: + encryptionKey: "NEW-encryption-key" + keyRotation: + decryptionOnlyKeys: ["OLD-encryption-key-1", "OLD-encryption-key-2"] +``` + +Before old decryption-only key is disposed administrators may want to call a dedicated and _protected_ API endpoint that will go through all registered Saved Objects with encrypted attributes and try to re-encrypt them with the primary encryption key: + +```http request +POST https://localhost:5601/api/encrypted_saved_objects/rotate_key?conflicts=abort +Content-Type: application/json +Kbn-Xsrf: true +``` + +# Motivation + +Today when encryption key changes we can no longer decrypt Saved Objects attributes that were previously encrypted with the `EncryptedSavedObjects` plugin. We handle this case in two different ways depending on whether consumers explicitly requested decryption or not: + +* If consumers explicitly request decryption via `getDecryptedAsInternalUser()` we abort operation and throw exception. +* If consumers fetch Saved Objects with encrypted attributes that should be automatically decrypted (the ones with `dangerouslyExposeValue: true` marker) via standard Saved Objects APIs we don't abort operation, but rather strip all encrypted attributes from the response and record decryption error in the `error` Saved Object field. +* If Kibana tries to migrate encrypted Saved Objects at the start up time we abort operation and throw exception. + +In both of these cases we throw or record error with the specific type to allow consumers to gracefully handle this scenario and either drop Saved Objects with unrecoverable encrypted attributes or facilitate the process of re-entering and re-encryption of the new values. + +This approach works reasonably well in some scenarios, but it may become very troublesome if we have to deal with lots of Saved Objects. Moreover, we'd like to recommend our users to periodically rotate encryption keys even if they aren't compromised. Hence, we need to provide a way of seamless migration of the existing encrypted Saved Objects to a new encryption key. + +There are two main scenarios we'd like to cover in this RFC: + +## Encryption key is not available + +Administrators may lose existing encryption key or explicitly decide to not use it if it was compromised and users can no longer trust encrypted content that may have been tampered with. In this scenario encrypted portion of the existing Saved Objects is considered lost, and the only way to recover from this state is a manual intervention described previously. That means `EncryptedSavedObjects` plugin consumers __should__ continue supporting this scenario even after we implement a proper encryption key rotation mechanism described in this RFC. + +## Encryption key is available, but needs to be rotated + +In this scenario a new encryption key (primary encryption key) will be generated, and we will use it to encrypt new or updated Saved Objects. We will still need to know the old encryption key to decrypt existing attributes, but we will no longer use this key to encrypt any of the new or existing Saved Objects. It's also should be possible to have multiple old decryption-only keys. + +The old old decryption-only keys should be eventually disposed and users should have a way to make sure all existing Saved Objects are re-encrypted with the new primary encryption key. + +__NOTE:__ users can get into a state when different Saved Objects are encrypted with different encryption keys even if they didn't intend to rotate the encryption key. We anticipate that it can happen during initial Elastic Stack HA setup, when by mistake or intentionally different Kibana instances were using different encryption keys. Key rotation mechanism can help to fix this issue without a data loss. + +# Detailed design + +The core idea is that when the encryption key needs to be rotated then a new key is generated and becomes a primary one, and the old one moves to the `keyRotation` section: + +```yaml +xpack.encryptedSavedObjects: + encryptionKey: "NEW-encryption-key" + keyRotation: + decryptionOnlyKeys: ["OLD-encryption-key"] +``` + +As the name implies, the key from the `decryptionOnlyKeys` is only used to decrypt content that we cannot decrypt with the primary encryption key. It's allowed to have multiple decryption-only keys at the same time. When user creates a new Saved Object or updates the existing one then its content is always encrypted with the primary encryption key. Config schema won't allow having the same key in `encryptionKey` and `decryptionOnlyKeys`. + +Having multiple decryption keys at the same time brings one problem though: we need to figure out which key to use to decrypt specific Saved Object. If our encryption keys could have a unique ID that we would store together with the encrypted data (we cannot use encryption key hash for that for obvious reasons) we could know for sure which key to use, but we don't have such functionality right now and it may not be the easiest one to manage through `yml` configuration anyway. + +Instead, this RFC proposes to try available existing decryption keys one by one to decrypt Saved Object and always start from the primary one. This way we won't incur any penalty while decrypting Saved Objects that are already encrypted with the primary encryption key, but there will still be some cost when we have to perform multiple decryption attempts. See the [`Drawbacks`](#drawbacks) section for the details. + +Technically just having `decryptionOnlyKeys` would be enough to cover the majority of the use cases, but the old decryption-only keys should be eventually disposed. At this point administrators would like to make sure _all_ Saved Objects are encrypted with the new primary encryption key. Another reason to re-encrypt all existing Saved Objects with the new key at once is to preventively reduce the performance impact of the multiple decryption attempts. + +We'd like to make this process as simple as possible while meeting the following requirements: + +* It should not be required to restart Kibana to perform this type of migration since Saved Objects encrypted with the another encryption key can theoretically appear at any point in time. +* It should be possible to integrate this operation into other operational flows our users may have and any user-friendly key management UIs we may introduce in this future. +* Any possible failures that may happen during this operation shouldn't make Kibana nonfunctional. +* Ordinary users should not be able to trigger this migration since it may consume a considerable amount of computing resources. + +We think that the best option we have right now is a dedicated API endpoint that would trigger this migration: + +```http request +POST https://localhost:5601/api/encrypted_saved_objects/rotate_key?conflicts=abort +Content-Type: application/json +Kbn-Xsrf: true +``` + +This will be a protected endpoint and only user with enough privileges will be able to use it. + +Under the hood we'll scroll over all Saved Objects that are registered with `EncryptedSavedObjects` plugin and re-encrypt attributes only for those of them that can only be decrypted with any of the old decryption-only keys. Saved Objects that can be decrypted with the primary encryption key will be ignored. We'll also ignore the ones that cannot be decrypted with any of the available decryption keys at all, and presumably return their IDs in the response. + +As for any other encryption or decryption operation we'll record relevant bits in the audit logs. + +# Benefits + +* The concept of decryption-only keys is easy to grasp and allows Kibana to function even if it has a mix of Saved Objects encrypted with different encryption keys. +* Support of the key rotation out of the box decreases the chances of the data loss and makes `EncryptedSavedObjects` story more secure and approachable overall. + +# Drawbacks + +* Multiple decryption attempts affect performance. See [the performance test results](https://github.com/elastic/kibana/pull/72420#issue-453400211) for more details, but making two decryption attempts is basically twice as slow as with a single attempt. Although it's only relevant for the encrypted Saved Objects migration performed at the start up time and batch operations that trigger automatic decryption (only for the Saved Objects registered with `dangerouslyExposeValue: true` marker that nobody is using in Kibana right now), we may have more use cases in the future. +* Historically we supported Kibana features with either configuration or dedicated UI, but in this case we want to introduce an API endpoint that _should be_ used directly. We may have a key management UI in the future though. + +# Alternatives + +We cannot think of any better alternative for `decryptionOnlyKeys` at the moment, but instead of API endpoint for the batch re-encryption we could potentially use another `kibana.yml` config option. For example `keyRotation.mode: onWrite | onStart | both`, but it feels a bit hacky and cannot be really integrated with anything else. + +# Adoption strategy + +Adoption strategy is pretty straightforward since the feature is an enhancement and doesn't bring any BWC concerns. + +# How we teach this + +Key rotation is a well-known paradigm. We'll update `README.md` of the `EncryptedSavedObjects` plugin and create a dedicated section in the public Kibana documentation. + +# Unresolved questions + +* Is it reasonable to have this feature in Basic? +* Are there any other use-cases that are not covered by the proposal? diff --git a/src/core/server/http/base_path_proxy_server.ts b/src/core/server/http/base_path_proxy_server.ts index eccc9d013176c..acb83962bd457 100644 --- a/src/core/server/http/base_path_proxy_server.ts +++ b/src/core/server/http/base_path_proxy_server.ts @@ -22,10 +22,9 @@ import { Agent as HttpsAgent, ServerOptions as TlsOptions } from 'https'; import apm from 'elastic-apm-node'; import { ByteSizeValue } from '@kbn/config-schema'; -import { Server, Request, ResponseToolkit } from 'hapi'; +import { Server, Request } from 'hapi'; import HapiProxy from 'h2o2'; import { sampleSize } from 'lodash'; -import BrowserslistUserAgent from 'browserslist-useragent'; import * as Rx from 'rxjs'; import { take } from 'rxjs/operators'; @@ -41,34 +40,6 @@ export interface BasePathProxyServerOptions { delayUntil: () => Rx.Observable; } -// Before we proxy request to a target port we may want to wait until some -// condition is met (e.g. until target listener is ready). -const checkForBrowserCompat = (log: Logger) => async (request: Request, h: ResponseToolkit) => { - if (!request.headers['user-agent'] || process.env.BROWSERSLIST_ENV === 'production') { - return h.continue; - } - - const matches = BrowserslistUserAgent.matchesUA(request.headers['user-agent'], { - env: 'dev', - allowHigherVersions: true, - ignoreMinor: true, - ignorePath: true, - }); - - if (!matches) { - log.warn(` - Request with user-agent [${request.headers['user-agent']}] - seems like it is coming from a browser that is not supported by the dev browserlist. - - Please run Kibana with the environment variable BROWSERSLIST_ENV=production to enable - support for all production browsers (like IE). - - `); - } - - return h.continue; -}; - export class BasePathProxyServer { private server?: Server; private httpsAgent?: HttpsAgent; @@ -155,9 +126,6 @@ export class BasePathProxyServer { }, method: 'GET', path: '/', - options: { - pre: [checkForBrowserCompat(this.log)], - }, }); this.server.route({ @@ -175,7 +143,6 @@ export class BasePathProxyServer { method: '*', options: { pre: [ - checkForBrowserCompat(this.log), // Before we proxy request to a target port we may want to wait until some // condition is met (e.g. until target listener is ready). async (request, responseToolkit) => { @@ -210,7 +177,6 @@ export class BasePathProxyServer { method: '*', options: { pre: [ - checkForBrowserCompat(this.log), // Before we proxy request to a target port we may want to wait until some // condition is met (e.g. until target listener is ready). async (request, responseToolkit) => { diff --git a/src/dev/i18n/integrate_locale_files.test.ts b/src/dev/i18n/integrate_locale_files.test.ts index 7ff1d87f1bc55..3bd3dc61c044f 100644 --- a/src/dev/i18n/integrate_locale_files.test.ts +++ b/src/dev/i18n/integrate_locale_files.test.ts @@ -21,7 +21,7 @@ import { mockMakeDirAsync, mockWriteFileAsync } from './integrate_locale_files.t import path from 'path'; import { integrateLocaleFiles, verifyMessages } from './integrate_locale_files'; -// @ts-ignore +// @ts-expect-error import { normalizePath } from './utils'; const localePath = path.resolve(__dirname, '__fixtures__', 'integrate_locale_files', 'fr.json'); @@ -36,6 +36,7 @@ const defaultIntegrateOptions = { sourceFileName: localePath, dryRun: false, ignoreIncompatible: false, + ignoreMalformed: false, ignoreMissing: false, ignoreUnused: false, config: { diff --git a/src/dev/i18n/integrate_locale_files.ts b/src/dev/i18n/integrate_locale_files.ts index d8ccccca15559..f9cd6dd1971c7 100644 --- a/src/dev/i18n/integrate_locale_files.ts +++ b/src/dev/i18n/integrate_locale_files.ts @@ -31,7 +31,8 @@ import { normalizePath, readFileAsync, writeFileAsync, - // @ts-ignore + verifyICUMessage, + // @ts-expect-error } from './utils'; import { I18nConfig } from './config'; @@ -41,6 +42,7 @@ export interface IntegrateOptions { sourceFileName: string; targetFileName?: string; dryRun: boolean; + ignoreMalformed: boolean; ignoreIncompatible: boolean; ignoreUnused: boolean; ignoreMissing: boolean; @@ -105,6 +107,23 @@ export function verifyMessages( } } + for (const messageId of localizedMessagesIds) { + const defaultMessage = defaultMessagesMap.get(messageId); + if (defaultMessage) { + try { + const message = localizedMessagesMap.get(messageId)!; + verifyICUMessage(message); + } catch (err) { + if (options.ignoreMalformed) { + localizedMessagesMap.delete(messageId); + options.log.warning(`Malformed translation ignored (${messageId}): ${err}`); + } else { + errorMessage += `\nMalformed translation (${messageId}): ${err}\n`; + } + } + } + } + if (errorMessage) { throw createFailError(errorMessage); } diff --git a/src/dev/i18n/tasks/check_compatibility.ts b/src/dev/i18n/tasks/check_compatibility.ts index 5900bf5aff252..afaf3cd875a8a 100644 --- a/src/dev/i18n/tasks/check_compatibility.ts +++ b/src/dev/i18n/tasks/check_compatibility.ts @@ -22,13 +22,14 @@ import { integrateLocaleFiles, I18nConfig } from '..'; export interface I18nFlags { fix: boolean; + ignoreMalformed: boolean; ignoreIncompatible: boolean; ignoreUnused: boolean; ignoreMissing: boolean; } export function checkCompatibility(config: I18nConfig, flags: I18nFlags, log: ToolingLog) { - const { fix, ignoreIncompatible, ignoreUnused, ignoreMissing } = flags; + const { fix, ignoreIncompatible, ignoreUnused, ignoreMalformed, ignoreMissing } = flags; return config.translations.map((translationsPath) => ({ task: async ({ messages }: { messages: Map }) => { // If `fix` is set we should try apply all possible fixes and override translations file. @@ -37,6 +38,7 @@ export function checkCompatibility(config: I18nConfig, flags: I18nFlags, log: To ignoreIncompatible: fix || ignoreIncompatible, ignoreUnused: fix || ignoreUnused, ignoreMissing: fix || ignoreMissing, + ignoreMalformed: fix || ignoreMalformed, sourceFileName: translationsPath, targetFileName: fix ? translationsPath : undefined, config, diff --git a/src/dev/i18n/utils.js b/src/dev/i18n/utils.js index 1d1c3118e0852..11a002fdbf4a8 100644 --- a/src/dev/i18n/utils.js +++ b/src/dev/i18n/utils.js @@ -208,6 +208,28 @@ export function checkValuesProperty(prefixedValuesKeys, defaultMessage, messageI } } +/** + * Verifies valid ICU message. + * @param message ICU message. + * @param messageId ICU message id + * @returns {undefined} + */ +export function verifyICUMessage(message) { + try { + parser.parse(message); + } catch (error) { + if (error.name === 'SyntaxError') { + const errorWithContext = createParserErrorMessage(message, { + loc: { + line: error.location.start.line, + column: error.location.start.column - 1, + }, + message: error.message, + }); + throw errorWithContext; + } + } +} /** * Extracts value references from the ICU message. * @param message ICU message. diff --git a/src/dev/precommit_hook/casing_check_config.js b/src/dev/precommit_hook/casing_check_config.js index 36d0ff8f51d88..bdbd600e9aa74 100644 --- a/src/dev/precommit_hook/casing_check_config.js +++ b/src/dev/precommit_hook/casing_check_config.js @@ -71,6 +71,8 @@ export const IGNORE_FILE_GLOBS = [ 'x-pack/plugins/apm/e2e/**/*', 'x-pack/plugins/maps/server/fonts/**/*', + // packages for the ingest manager's api integration tests could be valid semver which has dashes + 'x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/**/*', ]; /** diff --git a/src/dev/run_i18n_check.ts b/src/dev/run_i18n_check.ts index 97ea988b1de3a..70eeedac2b8b6 100644 --- a/src/dev/run_i18n_check.ts +++ b/src/dev/run_i18n_check.ts @@ -36,6 +36,7 @@ run( async ({ flags: { 'ignore-incompatible': ignoreIncompatible, + 'ignore-malformed': ignoreMalformed, 'ignore-missing': ignoreMissing, 'ignore-unused': ignoreUnused, 'include-config': includeConfig, @@ -48,12 +49,13 @@ run( fix && (ignoreIncompatible !== undefined || ignoreUnused !== undefined || + ignoreMalformed !== undefined || ignoreMissing !== undefined) ) { throw createFailError( `${chalk.white.bgRed( ' I18N ERROR ' - )} none of the --ignore-incompatible, --ignore-unused or --ignore-missing is allowed when --fix is set.` + )} none of the --ignore-incompatible, --ignore-malformed, --ignore-unused or --ignore-missing is allowed when --fix is set.` ); } @@ -99,6 +101,7 @@ run( checkCompatibility( config, { + ignoreMalformed: !!ignoreMalformed, ignoreIncompatible: !!ignoreIncompatible, ignoreUnused: !!ignoreUnused, ignoreMissing: !!ignoreMissing, diff --git a/src/dev/run_i18n_integrate.ts b/src/dev/run_i18n_integrate.ts index ac1e957adfc99..25c3ea32783aa 100644 --- a/src/dev/run_i18n_integrate.ts +++ b/src/dev/run_i18n_integrate.ts @@ -31,6 +31,7 @@ run( 'ignore-incompatible': ignoreIncompatible = false, 'ignore-missing': ignoreMissing = false, 'ignore-unused': ignoreUnused = false, + 'ignore-malformed': ignoreMalformed = false, 'include-config': includeConfig, path, source, @@ -66,12 +67,13 @@ run( typeof ignoreIncompatible !== 'boolean' || typeof ignoreUnused !== 'boolean' || typeof ignoreMissing !== 'boolean' || + typeof ignoreMalformed !== 'boolean' || typeof dryRun !== 'boolean' ) { throw createFailError( `${chalk.white.bgRed( ' I18N ERROR ' - )} --ignore-incompatible, --ignore-unused, --ignore-missing, and --dry-run can't have values` + )} --ignore-incompatible, --ignore-unused, --ignore-malformed, --ignore-missing, and --dry-run can't have values` ); } @@ -97,6 +99,7 @@ run( ignoreIncompatible, ignoreUnused, ignoreMissing, + ignoreMalformed, config, log, }); @@ -108,7 +111,6 @@ run( const reporter = new ErrorReporter(); const messages: Map = new Map(); await list.run({ messages, reporter }); - process.exitCode = 0; } catch (error) { process.exitCode = 1; if (error instanceof ErrorReporter) { @@ -118,7 +120,6 @@ run( log.error(error); } } - process.exit(); }, { flags: { diff --git a/src/plugins/dashboard/public/application/legacy_app.js b/src/plugins/dashboard/public/application/legacy_app.js index 8b8fdcb7a76ac..abe04fb8bd7e3 100644 --- a/src/plugins/dashboard/public/application/legacy_app.js +++ b/src/plugins/dashboard/public/application/legacy_app.js @@ -30,6 +30,7 @@ import { createKbnUrlStateStorage, redirectWhenMissing, SavedObjectNotFound, + withNotifyOnErrors, } from '../../../kibana_utils/public'; import { DashboardListing, EMPTY_FILTER } from './listing/dashboard_listing'; import { addHelpMenuToAppChrome } from './help_menu/help_menu_util'; @@ -65,6 +66,7 @@ export function initDashboardApp(app, deps) { createKbnUrlStateStorage({ history, useHash: deps.uiSettings.get('state:storeInSessionStorage'), + ...withNotifyOnErrors(deps.core.notifications.toasts), }) ); diff --git a/src/plugins/data/common/es_query/filters/exists_filter.test.ts b/src/plugins/data/common/es_query/filters/exists_filter.test.ts index 065301986726d..298ea7f49da5e 100644 --- a/src/plugins/data/common/es_query/filters/exists_filter.test.ts +++ b/src/plugins/data/common/es_query/filters/exists_filter.test.ts @@ -19,7 +19,7 @@ import { buildExistsFilter, getExistsFilterField } from './exists_filter'; import { IIndexPattern } from '../../index_patterns'; -import { fields } from '../../index_patterns/fields/fields.mocks.ts'; +import { fields } from '../../index_patterns/fields/fields.mocks'; describe('exists filter', function () { const indexPattern: IIndexPattern = ({ diff --git a/src/plugins/data/common/es_query/filters/get_filter_field.test.ts b/src/plugins/data/common/es_query/filters/get_filter_field.test.ts index 4329a45f84ef9..3b27aa98cf5f6 100644 --- a/src/plugins/data/common/es_query/filters/get_filter_field.test.ts +++ b/src/plugins/data/common/es_query/filters/get_filter_field.test.ts @@ -21,7 +21,7 @@ import { buildPhraseFilter } from './phrase_filter'; import { buildQueryFilter } from './query_string_filter'; import { getFilterField } from './get_filter_field'; import { IIndexPattern } from '../../index_patterns'; -import { fields } from '../../index_patterns/fields/fields.mocks.ts'; +import { fields } from '../../index_patterns/fields/fields.mocks'; describe('getFilterField', function () { const indexPattern: IIndexPattern = ({ diff --git a/src/plugins/data/common/es_query/filters/phrases_filter.test.ts b/src/plugins/data/common/es_query/filters/phrases_filter.test.ts index 7fbab263ac040..ed42b63be7ecc 100644 --- a/src/plugins/data/common/es_query/filters/phrases_filter.test.ts +++ b/src/plugins/data/common/es_query/filters/phrases_filter.test.ts @@ -19,7 +19,7 @@ import { buildPhrasesFilter, getPhrasesFilterField } from './phrases_filter'; import { IIndexPattern } from '../../index_patterns'; -import { fields } from '../../index_patterns/fields/fields.mocks.ts'; +import { fields } from '../../index_patterns/fields/fields.mocks'; describe('phrases filter', function () { const indexPattern: IIndexPattern = ({ diff --git a/src/plugins/data/common/index_patterns/fields/__snapshots__/field.test.ts.snap b/src/plugins/data/common/index_patterns/fields/__snapshots__/index_pattern_field.test.ts.snap similarity index 100% rename from src/plugins/data/common/index_patterns/fields/__snapshots__/field.test.ts.snap rename to src/plugins/data/common/index_patterns/fields/__snapshots__/index_pattern_field.test.ts.snap diff --git a/src/plugins/data/common/index_patterns/fields/field.ts b/src/plugins/data/common/index_patterns/fields/field.ts deleted file mode 100644 index 81c7aff8a0faa..0000000000000 --- a/src/plugins/data/common/index_patterns/fields/field.ts +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -// @ts-ignore -import { ObjDefine } from './obj_define'; -import { IIndexPattern } from '../../types'; -import { - IFieldType, - getKbnFieldType, - IFieldSubType, - FieldFormat, - shortenDottedString, -} from '../../../common'; -import { - OnNotification, - FieldSpec, - FieldSpecConflictDescriptions, - FieldSpecExportFmt, -} from '../types'; -import { FieldFormatsStartCommon } from '../../field_formats'; - -interface FieldDependencies { - fieldFormats: FieldFormatsStartCommon; - onNotification: OnNotification; -} - -export class Field implements IFieldType { - name: string; - type: string; - script?: string; - lang?: string; - count?: number; - // esTypes might be undefined on old index patterns that have not been refreshed since we added - // this prop. It is also undefined on scripted fields. - esTypes?: string[]; - aggregatable?: boolean; - filterable?: boolean; - searchable?: boolean; - sortable?: boolean; - visualizable?: boolean; - scripted?: boolean; - subType?: IFieldSubType; - displayName?: string; - indexPattern?: IIndexPattern; - readFromDocValues?: boolean; - format: any; - $$spec: FieldSpec; - conflictDescriptions?: FieldSpecConflictDescriptions; - - constructor( - indexPattern: IIndexPattern, - spec: FieldSpecExportFmt | FieldSpec | Field, - shortDotsEnable: boolean, - { fieldFormats, onNotification }: FieldDependencies - ) { - // unwrap old instances of Field - if (spec instanceof Field) spec = spec.$$spec; - - // construct this object using ObjDefine class, which - // extends the Field.prototype but gets it's properties - // defined using the logic below - const obj = new ObjDefine(spec, Field.prototype); - - if (spec.name === '_source') { - spec.type = '_source'; - } - - // find the type for this field, fallback to unknown type - let type = getKbnFieldType(spec.type); - if (spec.type && !type) { - const title = i18n.translate('data.indexPatterns.unknownFieldHeader', { - values: { type: spec.type }, - defaultMessage: 'Unknown field type {type}', - }); - const text = i18n.translate('data.indexPatterns.unknownFieldErrorMessage', { - values: { name: spec.name, title: indexPattern.title }, - defaultMessage: 'Field {name} in indexPattern {title} is using an unknown field type.', - }); - onNotification({ title, text, color: 'danger', iconType: 'alert' }); - } - - if (!type) type = getKbnFieldType('unknown'); - - let format: any = spec.format; - - if (!FieldFormat.isInstanceOfFieldFormat(format)) { - format = - (indexPattern.fieldFormatMap && indexPattern.fieldFormatMap[spec.name]) || - fieldFormats.getDefaultInstance(spec.type, spec.esTypes); - } - - const indexed = !!spec.indexed; - const scripted = !!spec.scripted; - const searchable = !!spec.searchable || scripted; - const aggregatable = !!spec.aggregatable || scripted; - const readFromDocValues = !!spec.readFromDocValues && !scripted; - const sortable = spec.name === '_score' || ((indexed || aggregatable) && type && type.sortable); - const filterable = - spec.name === '_id' || scripted || ((indexed || searchable) && type && type.filterable); - const visualizable = aggregatable; - - this.name = ''; - obj.fact('name'); - this.type = ''; - obj.fact('type'); - obj.fact('esTypes'); - obj.writ('count', spec.count || 0); - - // scripted objs - obj.fact('scripted', scripted); - obj.writ('script', scripted ? spec.script : null); - obj.writ('lang', scripted ? spec.lang || 'painless' : null); - - // stats - obj.fact('searchable', searchable); - obj.fact('aggregatable', aggregatable); - obj.fact('readFromDocValues', readFromDocValues); - - // usage flags, read-only and won't be saved - obj.comp('format', format); - obj.comp('sortable', sortable); - obj.comp('filterable', filterable); - obj.comp('visualizable', visualizable); - - // computed values - obj.comp('indexPattern', indexPattern); - obj.comp('displayName', shortDotsEnable ? shortenDottedString(spec.name) : spec.name); - this.$$spec = spec; - obj.comp('$$spec', spec); - - // conflict info - obj.writ('conflictDescriptions'); - - // multi info - obj.fact('subType'); - - const newObj = obj.create(); - newObj.toSpec = function () { - return { - count: this.count, - script: this.script, - lang: this.lang, - conflictDescriptions: this.conflictDescriptions, - name: this.name, - type: this.type, - esTypes: this.esTypes, - scripted: this.scripted, - searchable: this.searchable, - aggregatable: this.aggregatable, - readFromDocValues: this.readFromDocValues, - subType: this.subType, - format: this.indexPattern?.fieldFormatMap[this.name]?.toJSON() || undefined, - }; - }; - return newObj; - } - // only providing type info as constructor returns new object instead of `this` - toSpec = () => (({} as unknown) as FieldSpecExportFmt); -} diff --git a/src/plugins/data/common/index_patterns/fields/field_list.ts b/src/plugins/data/common/index_patterns/fields/field_list.ts index c1ca5341328ce..172da9f9ca43f 100644 --- a/src/plugins/data/common/index_patterns/fields/field_list.ts +++ b/src/plugins/data/common/index_patterns/fields/field_list.ts @@ -18,95 +18,112 @@ */ import { findIndex } from 'lodash'; -import { IIndexPattern } from '../../types'; -import { IFieldType } from '../../../common'; -import { Field } from './field'; +import { IFieldType, shortenDottedString } from '../../../common'; +import { IndexPatternField } from './index_pattern_field'; import { OnNotification, FieldSpec } from '../types'; -import { FieldFormatsStartCommon } from '../../field_formats'; +import { IndexPattern } from '../index_patterns'; -type FieldMap = Map; +type FieldMap = Map; -interface FieldListDependencies { - fieldFormats: FieldFormatsStartCommon; - onNotification: OnNotification; -} - -export interface IIndexPatternFieldList extends Array { - getByName(name: Field['name']): Field | undefined; - getByType(type: Field['type']): Field[]; +export interface IIndexPatternFieldList extends Array { add(field: FieldSpec): void; + getAll(): IndexPatternField[]; + getByName(name: IndexPatternField['name']): IndexPatternField | undefined; + getByType(type: IndexPatternField['type']): IndexPatternField[]; remove(field: IFieldType): void; + removeAll(): void; + replaceAll(specs: FieldSpec[]): void; update(field: FieldSpec): void; } export type CreateIndexPatternFieldList = ( - indexPattern: IIndexPattern, + indexPattern: IndexPattern, specs?: FieldSpec[], - shortDotsEnable?: boolean + shortDotsEnable?: boolean, + onNotification?: OnNotification ) => IIndexPatternFieldList; -export const getIndexPatternFieldListCreator = ({ - fieldFormats, - onNotification, -}: FieldListDependencies): CreateIndexPatternFieldList => (...fieldListParams) => { - class FieldList extends Array implements IIndexPatternFieldList { - private byName: FieldMap = new Map(); - private groups: Map = new Map(); - private indexPattern: IIndexPattern; - private shortDotsEnable: boolean; - private setByName = (field: Field) => this.byName.set(field.name, field); - private setByGroup = (field: Field) => { - if (typeof this.groups.get(field.type) === 'undefined') { - this.groups.set(field.type, new Map()); - } - this.groups.get(field.type)!.set(field.name, field); - }; - private removeByGroup = (field: IFieldType) => this.groups.get(field.type)!.delete(field.name); +export class FieldList extends Array implements IIndexPatternFieldList { + private byName: FieldMap = new Map(); + private groups: Map = new Map(); + private indexPattern: IndexPattern; + private shortDotsEnable: boolean; + private onNotification: OnNotification; + private setByName = (field: IndexPatternField) => this.byName.set(field.name, field); + private setByGroup = (field: IndexPatternField) => { + if (typeof this.groups.get(field.type) === 'undefined') { + this.groups.set(field.type, new Map()); + } + this.groups.get(field.type)!.set(field.name, field); + }; + private removeByGroup = (field: IFieldType) => this.groups.get(field.type)!.delete(field.name); + private calcDisplayName = (name: string) => + this.shortDotsEnable ? shortenDottedString(name) : name; + constructor( + indexPattern: IndexPattern, + specs: FieldSpec[] = [], + shortDotsEnable = false, + onNotification = () => {} + ) { + super(); + this.indexPattern = indexPattern; + this.shortDotsEnable = shortDotsEnable; + this.onNotification = onNotification; - constructor(indexPattern: IIndexPattern, specs: FieldSpec[] = [], shortDotsEnable = false) { - super(); - this.indexPattern = indexPattern; - this.shortDotsEnable = shortDotsEnable; + specs.map((field) => this.add(field)); + } - specs.map((field) => this.add(field)); - } + public readonly getAll = () => [...this.byName.values()]; + public readonly getByName = (name: IndexPatternField['name']) => this.byName.get(name); + public readonly getByType = (type: IndexPatternField['type']) => [ + ...(this.groups.get(type) || new Map()).values(), + ]; + public readonly add = (field: FieldSpec) => { + const newField = new IndexPatternField( + this.indexPattern, + field, + this.calcDisplayName(field.name), + this.onNotification + ); + this.push(newField); + this.setByName(newField); + this.setByGroup(newField); + }; - getByName = (name: Field['name']) => this.byName.get(name); - getByType = (type: Field['type']) => [...(this.groups.get(type) || new Map()).values()]; - add = (field: FieldSpec) => { - const newField = new Field(this.indexPattern, field, this.shortDotsEnable, { - fieldFormats, - onNotification, - }); - this.push(newField); - this.setByName(newField); - this.setByGroup(newField); - }; + public readonly remove = (field: IFieldType) => { + this.removeByGroup(field); + this.byName.delete(field.name); - remove = (field: IFieldType) => { - this.removeByGroup(field); - this.byName.delete(field.name); + const fieldIndex = findIndex(this, { name: field.name }); + this.splice(fieldIndex, 1); + }; - const fieldIndex = findIndex(this, { name: field.name }); - this.splice(fieldIndex, 1); - }; + public readonly update = (field: FieldSpec) => { + const newField = new IndexPatternField( + this.indexPattern, + field, + this.calcDisplayName(field.name), + this.onNotification + ); + const index = this.findIndex((f) => f.name === newField.name); + this.splice(index, 1, newField); + this.setByName(newField); + this.removeByGroup(newField); + this.setByGroup(newField); + }; - update = (field: FieldSpec) => { - const newField = new Field(this.indexPattern, field, this.shortDotsEnable, { - fieldFormats, - onNotification, - }); - const index = this.findIndex((f) => f.name === newField.name); - this.splice(index, 1, newField); - this.setByName(newField); - this.removeByGroup(newField); - this.setByGroup(newField); - }; + public readonly removeAll = () => { + this.length = 0; + this.byName.clear(); + this.groups.clear(); + }; - toSpec = () => { - return [...this.map((field) => field.toSpec())]; - }; - } + public readonly replaceAll = (specs: FieldSpec[]) => { + this.removeAll(); + specs.forEach(this.add); + }; - return new FieldList(...fieldListParams); -}; + public readonly toSpec = () => { + return [...this.map((field) => field.toSpec())]; + }; +} diff --git a/src/plugins/data/common/index_patterns/fields/fields.mocks.ts.ts b/src/plugins/data/common/index_patterns/fields/fields.mocks.ts similarity index 100% rename from src/plugins/data/common/index_patterns/fields/fields.mocks.ts.ts rename to src/plugins/data/common/index_patterns/fields/fields.mocks.ts diff --git a/src/plugins/data/common/index_patterns/fields/index.ts b/src/plugins/data/common/index_patterns/fields/index.ts index 1b7c87d556f59..0c3b43181c5b4 100644 --- a/src/plugins/data/common/index_patterns/fields/index.ts +++ b/src/plugins/data/common/index_patterns/fields/index.ts @@ -20,4 +20,4 @@ export * from './types'; export { isFilterable, isNestedField } from './utils'; export * from './field_list'; -export * from './field'; +export * from './index_pattern_field'; diff --git a/src/plugins/data/common/index_patterns/fields/field.test.ts b/src/plugins/data/common/index_patterns/fields/index_pattern_field.test.ts similarity index 64% rename from src/plugins/data/common/index_patterns/fields/field.test.ts rename to src/plugins/data/common/index_patterns/fields/index_pattern_field.test.ts index 910f22088f43a..0cd0fe8324809 100644 --- a/src/plugins/data/common/index_patterns/fields/field.test.ts +++ b/src/plugins/data/common/index_patterns/fields/index_pattern_field.test.ts @@ -17,10 +17,10 @@ * under the License. */ -import { Field } from './field'; +import { IndexPatternField } from './index_pattern_field'; import { IndexPattern } from '../index_patterns'; -import { FieldFormatsStartCommon } from '../..'; -import { KBN_FIELD_TYPES, FieldSpec, FieldSpecExportFmt } from '../../../common'; +import { KBN_FIELD_TYPES } from '../../../common'; +import { FieldSpec } from '../types'; describe('Field', function () { function flatten(obj: Record) { @@ -28,14 +28,11 @@ describe('Field', function () { } function getField(values = {}) { - return new Field( + return new IndexPatternField( fieldValues.indexPattern as IndexPattern, { ...fieldValues, ...values }, - false, - { - fieldFormats: {} as FieldFormatsStartCommon, - onNotification: () => {}, - } + 'displayName', + () => {} ); } @@ -50,6 +47,7 @@ describe('Field', function () { filterable: true, searchable: true, sortable: true, + indexed: true, readFromDocValues: false, visualizable: true, scripted: true, @@ -58,11 +56,9 @@ describe('Field', function () { indexPattern: ({ fieldFormatMap: { name: {}, _source: {}, _score: {}, _id: {} }, } as unknown) as IndexPattern, - format: { name: 'formatName' }, $$spec: ({} as unknown) as FieldSpec, conflictDescriptions: { a: ['b', 'c'], d: ['e'] }, - toSpec: () => (({} as unknown) as FieldSpecExportFmt), - } as Field; + }; it('the correct properties are writable', () => { const field = getField(); @@ -84,72 +80,6 @@ describe('Field', function () { expect(field.conflictDescriptions).toEqual({}); }); - it('the correct properties are not writable', () => { - const field = getField(); - - expect(field.name).toEqual(fieldValues.name); - field.name = 'newName'; - expect(field.name).toEqual(fieldValues.name); - - expect(field.type).toEqual(fieldValues.type); - field.type = 'newType'; - expect(field.type).toEqual(fieldValues.type); - - expect(field.esTypes).toEqual(fieldValues.esTypes); - field.esTypes = ['newType']; - expect(field.esTypes).toEqual(fieldValues.esTypes); - - expect(field.scripted).toEqual(fieldValues.scripted); - field.scripted = false; - expect(field.scripted).toEqual(fieldValues.scripted); - - expect(field.searchable).toEqual(fieldValues.searchable); - field.searchable = false; - expect(field.searchable).toEqual(fieldValues.searchable); - - expect(field.aggregatable).toEqual(fieldValues.aggregatable); - field.aggregatable = false; - expect(field.aggregatable).toEqual(fieldValues.aggregatable); - - expect(field.readFromDocValues).toEqual(fieldValues.readFromDocValues); - field.readFromDocValues = true; - expect(field.readFromDocValues).toEqual(fieldValues.readFromDocValues); - - expect(field.subType).toEqual(fieldValues.subType); - field.subType = {}; - expect(field.subType).toEqual(fieldValues.subType); - - // not writable, not serialized - expect(() => { - field.indexPattern = {} as IndexPattern; - }).toThrow(); - - // computed fields - expect(() => { - field.format = { name: 'newFormatName' }; - }).toThrow(); - - expect(() => { - field.sortable = false; - }).toThrow(); - - expect(() => { - field.filterable = false; - }).toThrow(); - - expect(() => { - field.visualizable = false; - }).toThrow(); - - expect(() => { - field.displayName = 'newDisplayName'; - }).toThrow(); - - expect(() => { - field.$$spec = ({ a: 'b' } as unknown) as FieldSpec; - }).toThrow(); - }); - it('sets type field when _source field', () => { const field = getField({ name: '_source' }); expect(field.type).toEqual('_source'); @@ -214,26 +144,25 @@ describe('Field', function () { }); it('exports the property to JSON', () => { - const field = new Field({ fieldFormatMap: { name: {} } } as IndexPattern, fieldValues, false, { - fieldFormats: {} as FieldFormatsStartCommon, - onNotification: () => {}, - }); + const field = new IndexPatternField( + { fieldFormatMap: { name: {} } } as IndexPattern, + fieldValues, + 'displayName', + () => {} + ); expect(flatten(field)).toMatchSnapshot(); }); it('spec snapshot', () => { - const field = new Field( + const field = new IndexPatternField( { fieldFormatMap: { name: { toJSON: () => ({ id: 'number', params: { pattern: '$0,0.[00]' } }) }, }, } as IndexPattern, fieldValues, - false, - { - fieldFormats: {} as FieldFormatsStartCommon, - onNotification: () => {}, - } + 'displayName', + () => {} ); expect(field.toSpec()).toMatchSnapshot(); }); diff --git a/src/plugins/data/common/index_patterns/fields/index_pattern_field.ts b/src/plugins/data/common/index_patterns/fields/index_pattern_field.ts new file mode 100644 index 0000000000000..679de103f8019 --- /dev/null +++ b/src/plugins/data/common/index_patterns/fields/index_pattern_field.ts @@ -0,0 +1,188 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { + IFieldType, + KbnFieldType, + getKbnFieldType, + KBN_FIELD_TYPES, + FieldFormat, +} from '../../../common'; +import { OnNotification, FieldSpec } from '../types'; + +import { IndexPattern } from '../index_patterns'; + +export class IndexPatternField implements IFieldType { + readonly spec: FieldSpec; + // not writable or serialized + readonly indexPattern: IndexPattern; + readonly displayName: string; + private readonly kbnFieldType: KbnFieldType; + + constructor( + indexPattern: IndexPattern, + spec: FieldSpec, + displayName: string, + onNotification: OnNotification + ) { + this.indexPattern = indexPattern; + this.spec = { ...spec, type: spec.name === '_source' ? '_source' : spec.type }; + this.displayName = displayName; + + this.kbnFieldType = getKbnFieldType(spec.type); + if (spec.type && this.kbnFieldType?.name === KBN_FIELD_TYPES.UNKNOWN) { + const title = i18n.translate('data.indexPatterns.unknownFieldHeader', { + values: { type: spec.type }, + defaultMessage: 'Unknown field type {type}', + }); + const text = i18n.translate('data.indexPatterns.unknownFieldErrorMessage', { + values: { name: spec.name, title: indexPattern.title }, + defaultMessage: 'Field {name} in indexPattern {title} is using an unknown field type.', + }); + onNotification({ title, text, color: 'danger', iconType: 'alert' }); + } + } + + // writable attrs + public get count() { + return this.spec.count || 0; + } + + public set count(count) { + this.spec.count = count; + } + + public get script() { + return this.spec.script; + } + + public set script(script) { + this.spec.script = script; + } + + public get lang() { + return this.spec.lang; + } + + public set lang(lang) { + this.spec.lang = lang; + } + + public get conflictDescriptions() { + return this.spec.conflictDescriptions; + } + + public set conflictDescriptions(conflictDescriptions) { + this.spec.conflictDescriptions = conflictDescriptions; + } + + // read only attrs + public get name() { + return this.spec.name; + } + + public get type() { + return this.spec.type; + } + + public get esTypes() { + return this.spec.esTypes; + } + + public get scripted() { + return !!this.spec.scripted; + } + + public get searchable() { + return !!(this.spec.searchable || this.scripted); + } + + public get aggregatable() { + return !!(this.spec.aggregatable || this.scripted); + } + + public get readFromDocValues() { + return !!(this.spec.readFromDocValues && !this.scripted); + } + + public get subType() { + return this.spec.subType; + } + + // not writable, not serialized + public get sortable() { + return ( + this.name === '_score' || + ((this.spec.indexed || this.aggregatable) && this.kbnFieldType.sortable) + ); + } + + public get filterable() { + return ( + this.name === '_id' || + this.scripted || + ((this.spec.indexed || this.searchable) && this.kbnFieldType.filterable) + ); + } + + public get visualizable() { + return this.aggregatable; + } + + public get format(): FieldFormat { + return this.indexPattern.getFormatterForField(this); + } + + public toJSON() { + return { + count: this.count, + script: this.script, + lang: this.lang, + conflictDescriptions: this.conflictDescriptions, + + name: this.name, + type: this.type, + esTypes: this.esTypes, + scripted: this.scripted, + searchable: this.searchable, + aggregatable: this.aggregatable, + readFromDocValues: this.readFromDocValues, + subType: this.subType, + }; + } + + public toSpec() { + return { + count: this.count, + script: this.script, + lang: this.lang, + conflictDescriptions: this.conflictDescriptions, + name: this.name, + type: this.type, + esTypes: this.esTypes, + scripted: this.scripted, + searchable: this.searchable, + aggregatable: this.aggregatable, + readFromDocValues: this.readFromDocValues, + subType: this.subType, + format: this.indexPattern?.fieldFormatMap[this.name]?.toJSON() || undefined, + }; + } +} diff --git a/src/plugins/data/common/index_patterns/fields/obj_define.js b/src/plugins/data/common/index_patterns/fields/obj_define.js deleted file mode 100644 index 9c9e5c8f3d55f..0000000000000 --- a/src/plugins/data/common/index_patterns/fields/obj_define.js +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; - -export function ObjDefine(defaults, prototype) { - this.obj; // created by this.create() - - this.descs = {}; - this.defaults = defaults || {}; - this.prototype = prototype || Object.prototype; -} - -ObjDefine.REDEFINE_SUPPORTED = (function () { - const a = Object.create(Object.prototype, { - prop: { - configurable: true, - value: 1, - }, - }); - - Object.defineProperty(a, 'prop', { - configurable: true, - value: 2, - }); - - return a.prop === 2; -})(); - -/** - * normal value, writable and exported in JSON - * - * @param {any} v - value - * @return {object} - property descriptor - */ -ObjDefine.prototype.writ = function (name, val) { - this._define(name, val, true, true); -}; - -/** - * known value, exported in JSON, not changeable - * - * @param {any} v - value - * @return {object} - property descriptor - */ -ObjDefine.prototype.fact = function (name, val) { - this._define(name, val, true); -}; - -/** - * computed fact, not exported or changeable - * - * @param {any} v - value - * @return {object} - property descriptor - */ -ObjDefine.prototype.comp = function (name, val) { - this._define(name, val); -}; - -/** - * Creates an object, decorated by the property descriptors - * created by other ObjDefine methods and inheriting form the - * prototype - * - * # note: - * If a value is writable, but the value is undefined, the property will - * be created by not exported to JSON unless the property is written to - * - * @return {object} - created object - */ -ObjDefine.prototype.create = function () { - const self = this; - self.obj = Object.create(this.prototype, self.descs); - - if (!ObjDefine.REDEFINE_SUPPORTED && !self.prototype.toJSON) { - // since we can't redefine properties as enumerable we will - // clone the object on serialization and choose which properties - // to include or trim manually. This is currently only in use in PhantomJS - // due to https://github.com/ariya/phantomjs/issues/11856 - // TODO: remove this: https://github.com/elastic/kibana/issues/27136 - self.obj.toJSON = function () { - return _.transform( - self.obj, - function (json, val, key) { - const desc = self.descs[key]; - if (desc && desc.enumerable && val == null) return; - json[key] = val; - }, - {} - ); - }; - } - - return self.obj; -}; - -/** - * Private APIS - */ - -ObjDefine.prototype._define = function (name, val, exported, changeable) { - val = val != null ? val : this.defaults[name]; - this.descs[name] = this._describe(name, val, !!exported, !!changeable); -}; - -ObjDefine.prototype._describe = function (name, val, exported, changeable) { - const self = this; - const exists = val != null; - - if (exported && ObjDefine.REDEFINE_SUPPORTED) { - return { - enumerable: exists, - configurable: true, - get: _.constant(val), - set: function (update) { - if (!changeable) return false; - - // change the descriptor, since the value now exists. - self.descs[name] = self._describe(name, update, exported, changeable); - - // apply the updated descriptor - Object.defineProperty(self.obj, name, self.descs[name]); - }, - }; - } - - if (exported && !ObjDefine.REDEFINE_SUPPORTED) { - return { - enumerable: true, - configurable: true, - writable: changeable, - value: val, - }; - } - - return { - enumerable: false, - writable: changeable, - configurable: true, - value: val, - }; -}; diff --git a/src/plugins/data/common/index_patterns/fields/obj_define.test.js b/src/plugins/data/common/index_patterns/fields/obj_define.test.js deleted file mode 100644 index ec9a022253621..0000000000000 --- a/src/plugins/data/common/index_patterns/fields/obj_define.test.js +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import { ObjDefine } from './obj_define'; - -describe('ObjDefine Utility', function () { - function flatten(obj) { - return JSON.parse(JSON.stringify(obj)); - } - - describe('#writ', function () { - it('creates writeable properties', function () { - const def = new ObjDefine(); - def.writ('name', 'foo'); - - const obj = def.create(); - expect(obj).to.have.property('name', 'foo'); - - obj.name = 'bar'; - expect(obj).to.have.property('name', 'bar'); - }); - - it('exports the property to JSON', function () { - const def = new ObjDefine(); - def.writ('name', 'foo'); - expect(flatten(def.create())).to.have.property('name', 'foo'); - }); - - it("does not export property to JSON it it's undefined or null", function () { - const def = new ObjDefine(); - def.writ('name'); - expect(flatten(def.create())).to.not.have.property('name'); - - def.writ('name', null); - expect(flatten(def.create())).to.not.have.property('name'); - }); - - it('switched to exporting if a value is written', function () { - const def = new ObjDefine(); - def.writ('name'); - - const obj = def.create(); - expect(flatten(obj)).to.not.have.property('name'); - - obj.name = null; - expect(flatten(obj)).to.not.have.property('name'); - - obj.name = 'foo'; - expect(flatten(obj)).to.have.property('name', 'foo'); - }); - - it('setting a writ value to null prevents it from exporting', function () { - const def = new ObjDefine(); - def.writ('name', 'foo'); - - const obj = def.create(); - expect(flatten(obj)).to.have.property('name', 'foo'); - - obj.name = null; - expect(flatten(obj)).to.not.have.property('name'); - }); - }); - - describe('#fact', function () { - it('creates an immutable field', function () { - const def = new ObjDefine(); - const val = 'foo'; - const notval = 'bar'; - def.fact('name', val); - const obj = def.create(); - - obj.name = notval; // UPDATE SHOULD BE IGNORED - expect(obj).to.have.property('name', val); - }); - - it('exports the fact to JSON', function () { - const def = new ObjDefine(); - def.fact('name', 'foo'); - expect(flatten(def.create())).to.have.property('name', 'foo'); - }); - }); - - describe('#comp', function () { - it('creates an immutable field', function () { - const def = new ObjDefine(); - const val = 'foo'; - const notval = 'bar'; - def.comp('name', val); - const obj = def.create(); - - expect(function () { - 'use strict'; // eslint-disable-line strict - - obj.name = notval; - }).to.throwException(); - }); - - it('does not export the computed value to JSON', function () { - const def = new ObjDefine(); - def.comp('name', 'foo'); - expect(flatten(def.create())).to.not.have.property('name'); - }); - }); - - describe('#create', function () { - it('creates object that inherits from the prototype', function () { - function SomeClass() {} - - const def = new ObjDefine(null, SomeClass.prototype); - const obj = def.create(); - - expect(obj).to.be.a(SomeClass); - }); - - it('uses the defaults for property values', function () { - const def = new ObjDefine({ name: 'bar' }); - def.fact('name'); - - const obj = def.create(); - - expect(obj).to.have.property('name', 'bar'); - }); - - it('ignores default values that are not defined properties', function () { - const def = new ObjDefine({ name: 'foo', name2: 'bar' }); - const obj = def.create(); - - expect(obj).to.not.have.property('name'); - expect(obj).to.not.have.property('name2'); - }); - }); -}); diff --git a/src/plugins/data/common/index_patterns/index_patterns/index_pattern.test.ts b/src/plugins/data/common/index_patterns/index_patterns/index_pattern.test.ts index ebf873b14c379..e4f297b29c372 100644 --- a/src/plugins/data/common/index_patterns/index_patterns/index_pattern.test.ts +++ b/src/plugins/data/common/index_patterns/index_patterns/index_pattern.test.ts @@ -26,7 +26,7 @@ import { DuplicateField } from '../../../../kibana_utils/common'; import mockLogStashFields from '../../../../../fixtures/logstash_fields'; // @ts-ignore import { stubbedSavedObjectIndexPattern } from '../../../../../fixtures/stubbed_saved_object_index_pattern'; -import { Field } from '../fields'; +import { IndexPatternField } from '../fields'; import { fieldFormatsMock } from '../../field_formats/mocks'; @@ -170,8 +170,8 @@ describe('IndexPattern', () => { describe('getScriptedFields', () => { test('should return all scripted fields', () => { const scriptedNames = mockLogStashFields() - .filter((item: Field) => item.scripted === true) - .map((item: Field) => item.name); + .filter((item: IndexPatternField) => item.scripted === true) + .map((item: IndexPatternField) => item.name); const respNames = map(indexPattern.getScriptedFields(), 'name'); expect(respNames).toEqual(scriptedNames); @@ -214,8 +214,8 @@ describe('IndexPattern', () => { describe('getNonScriptedFields', () => { test('should return all non-scripted fields', () => { const notScriptedNames = mockLogStashFields() - .filter((item: Field) => item.scripted === false) - .map((item: Field) => item.name); + .filter((item: IndexPatternField) => item.scripted === false) + .map((item: IndexPatternField) => item.name); const respNames = map(indexPattern.getNonScriptedFields(), 'name'); expect(respNames).toEqual(notScriptedNames); @@ -235,7 +235,7 @@ describe('IndexPattern', () => { const newFields = indexPattern.getNonScriptedFields(); expect(newFields).toHaveLength(2); - expect(newFields.map((f) => f.name)).toEqual(['foo', 'bar']); + expect([...newFields.map((f) => f.name)]).toEqual(['foo', 'bar']); }); test('should preserve the scripted fields', async () => { @@ -249,8 +249,8 @@ describe('IndexPattern', () => { // sinon.assert.calledOnce(indexPattern.getScriptedFields); expect(indexPattern.getScriptedFields().map((f) => f.name)).toEqual( mockLogStashFields() - .filter((f: Field) => f.scripted) - .map((f: Field) => f.name) + .filter((f: IndexPatternField) => f.scripted) + .map((f: IndexPatternField) => f.name) ); }); }); @@ -278,7 +278,7 @@ describe('IndexPattern', () => { const scriptedFields = indexPattern.getScriptedFields(); // expect(saveSpy.callCount).to.equal(1); expect(scriptedFields).toHaveLength(oldCount + 1); - expect((indexPattern.fields.getByName(scriptedField.name) as Field).name).toEqual( + expect((indexPattern.fields.getByName(scriptedField.name) as IndexPatternField).name).toEqual( scriptedField.name ); }); @@ -287,9 +287,9 @@ describe('IndexPattern', () => { // const saveSpy = sinon.spy(indexPattern, 'save'); const scriptedFields = indexPattern.getScriptedFields(); const oldCount = scriptedFields.length; - const scriptedField = last(scriptedFields) as any; + const scriptedField = last(scriptedFields)!; - await indexPattern.removeScriptedField(scriptedField); + await indexPattern.removeScriptedField(scriptedField.name); // expect(saveSpy.callCount).to.equal(1); expect(indexPattern.getScriptedFields().length).toEqual(oldCount - 1); diff --git a/src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts b/src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts index 2acb9d5f767ad..4e484dce7826f 100644 --- a/src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts +++ b/src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts @@ -22,10 +22,10 @@ import { i18n } from '@kbn/i18n'; import { SavedObjectsClientCommon } from '../..'; import { DuplicateField, SavedObjectNotFound } from '../../../../kibana_utils/common'; -import { ES_FIELD_TYPES, KBN_FIELD_TYPES, IIndexPattern, IFieldType } from '../../../common'; +import { ES_FIELD_TYPES, KBN_FIELD_TYPES, IIndexPattern } from '../../../common'; import { findByTitle } from '../utils'; import { IndexPatternMissingIndices } from '../lib'; -import { Field, IIndexPatternFieldList, getIndexPatternFieldListCreator } from '../fields'; +import { IndexPatternField, IIndexPatternFieldList, FieldList } from '../fields'; import { createFieldsFetcher } from './_fields_fetcher'; import { formatHitProvider } from './format_hit'; import { flattenHitWrapper } from './flatten_hit'; @@ -36,7 +36,7 @@ import { IIndexPatternsApiClient, IndexPatternAttributes, } from '../types'; -import { FieldFormatsStartCommon } from '../../field_formats'; +import { FieldFormatsStartCommon, FieldFormat } from '../../field_formats'; import { PatternCache } from './_pattern_cache'; import { expandShorthand, FieldMappingSpec, MappingObject } from '../../field_mapping'; import { IndexPatternSpec, TypeMeta, FieldSpec, SourceFilter } from '../types'; @@ -138,12 +138,8 @@ export class IndexPattern implements IIndexPattern { this.shortDotsEnable = uiSettingsValues.shortDotsEnable; this.metaFields = uiSettingsValues.metaFields; - this.createFieldList = getIndexPatternFieldListCreator({ - fieldFormats, - onNotification, - }); + this.fields = new FieldList(this, [], this.shortDotsEnable, this.onUnknownType); - this.fields = this.createFieldList(this, [], this.shortDotsEnable); this.apiClient = apiClient; this.fieldsFetcher = createFieldsFetcher(this, apiClient, uiSettingsValues.metaFields); this.flattenHit = flattenHitWrapper(this, uiSettingsValues.metaFields); @@ -161,49 +157,45 @@ export class IndexPattern implements IIndexPattern { } private deserializeFieldFormatMap(mapping: any) { - const FieldFormat = this.fieldFormats.getType(mapping.id); + const FieldFormatter = this.fieldFormats.getType(mapping.id); return ( - FieldFormat && - new FieldFormat( + FieldFormatter && + new FieldFormatter( mapping.params, (key: string) => this.uiSettingsValues[key]?.userValue || this.uiSettingsValues[key]?.value ) ); } - private initFields(input?: any) { - const newValue = input || this.fields; - - this.fields = this.createFieldList(this, newValue, this.shortDotsEnable); - } - - private isFieldRefreshRequired(): boolean { - if (!this.fields) { + private isFieldRefreshRequired(specs?: FieldSpec[]): boolean { + if (!specs) { return true; } - return this.fields.every((field) => { + return specs.every((spec) => { // See https://github.com/elastic/kibana/pull/8421 - const hasFieldCaps = 'aggregatable' in field && 'searchable' in field; + const hasFieldCaps = 'aggregatable' in spec && 'searchable' in spec; // See https://github.com/elastic/kibana/pull/11969 - const hasDocValuesFlag = 'readFromDocValues' in field; + const hasDocValuesFlag = 'readFromDocValues' in spec; return !hasFieldCaps || !hasDocValuesFlag; }); } - private async indexFields(forceFieldRefresh: boolean = false) { + private async indexFields(forceFieldRefresh: boolean = false, specs?: FieldSpec[]) { if (!this.id) { return; } - if (forceFieldRefresh || this.isFieldRefreshRequired()) { + if (forceFieldRefresh || this.isFieldRefreshRequired(specs)) { await this.refreshFields(); + } else { + if (specs) { + this.fields.replaceAll(specs); + } } - - this.initFields(); } public initFromSpec(spec: IndexPatternSpec) { @@ -223,15 +215,13 @@ export class IndexPattern implements IIndexPattern { this.timeFieldName = spec.timeFieldName; this.sourceFilters = spec.sourceFilters; - // ignoring this because the same thing happens elsewhere but via _.assign - // @ts-expect-error - this.fields = spec.fields || []; + this.fields.replaceAll(spec.fields || []); this.typeMeta = spec.typeMeta; + this.fieldFormatMap = _.mapValues(fieldFormatMap, (mapping) => { return this.deserializeFieldFormatMap(mapping); }); - this.initFields(); return this; } @@ -249,14 +239,16 @@ export class IndexPattern implements IIndexPattern { }); // give index pattern all of the values + const fieldList = this.fields; _.assign(this, response); + this.fields = fieldList; if (!this.title && this.id) { this.title = this.id; } this.version = response.version; - return this.indexFields(forceFieldRefresh); + return this.indexFields(forceFieldRefresh, response.fields); } getComputedFields() { @@ -359,32 +351,26 @@ export class IndexPattern implements IIndexPattern { throw new DuplicateField(name); } - this.fields.add( - new Field( - this, - { - name, - script, - fieldType, - scripted: true, - lang, - aggregatable: true, - filterable: true, - searchable: true, - }, - false, - { - fieldFormats: this.fieldFormats, - onNotification: this.onNotification, - } - ) - ); + this.fields.add({ + name, + script, + type: fieldType, + scripted: true, + lang, + aggregatable: true, + searchable: true, + count: 0, + readFromDocValues: false, + }); await this.save(); } - removeScriptedField(field: IFieldType) { - this.fields.remove(field); + removeScriptedField(fieldName: string) { + const field = this.fields.getByName(fieldName); + if (field) { + this.fields.remove(field); + } return this.save(); } @@ -417,11 +403,11 @@ export class IndexPattern implements IIndexPattern { } getNonScriptedFields() { - return _.filter(this.fields, { scripted: false }); + return [...this.fields.getAll().filter((field) => !field.scripted)]; } getScriptedFields() { - return _.filter(this.fields, { scripted: true }); + return [...this.fields.getAll().filter((field) => field.scripted)]; } isTimeBased(): boolean { @@ -438,12 +424,12 @@ export class IndexPattern implements IIndexPattern { } getTimeField() { - if (!this.timeFieldName || !this.fields || !this.fields.getByName) return; - return this.fields.getByName(this.timeFieldName); + if (!this.timeFieldName || !this.fields || !this.fields.getByName) return undefined; + return this.fields.getByName(this.timeFieldName) || undefined; } - getFieldByName(name: string): Field | void { - if (!this.fields || !this.fields.getByName) return; + getFieldByName(name: string): IndexPatternField | undefined { + if (!this.fields || !this.fields.getByName) return undefined; return this.fields.getByName(name); } @@ -470,6 +456,16 @@ export class IndexPattern implements IIndexPattern { return body; } + getFormatterForField(field: IndexPatternField | IndexPatternField['spec']): FieldFormat { + return ( + this.fieldFormatMap[field.name] || + this.fieldFormats.getDefaultInstance( + field.type as KBN_FIELD_TYPES, + field.esTypes as ES_FIELD_TYPES[] + ) + ); + } + async create(allowOverride: boolean = false) { const _create = async (duplicateId?: string) => { if (duplicateId) { @@ -581,9 +577,8 @@ export class IndexPattern implements IIndexPattern { async _fetchFields() { const fields = await this.fieldsFetcher.fetch(this); - const scripted = this.getScriptedFields(); - const all = fields.concat(scripted); - await this.initFields(all); + const scripted = this.getScriptedFields().map((field) => field.spec); + this.fields.replaceAll([...fields, ...scripted]); } refreshFields() { diff --git a/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts b/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts index a07ffaf92aea5..8874ce5f04b7c 100644 --- a/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts +++ b/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts @@ -25,14 +25,13 @@ import { createEnsureDefaultIndexPattern, EnsureDefaultIndexPattern, } from './ensure_default_index_pattern'; -import { getIndexPatternFieldListCreator, CreateIndexPatternFieldList, Field } from '../fields'; +import { IndexPatternField } from '../fields'; import { OnNotification, OnError, UiSettingsCommon, IIndexPatternsApiClient, GetFieldsOptions, - FieldSpec, IndexPatternSpec, } from '../types'; import { FieldFormatsStartCommon } from '../../field_formats'; @@ -65,12 +64,6 @@ export class IndexPatternsService { private onNotification: OnNotification; private onError: OnError; ensureDefaultIndexPattern: EnsureDefaultIndexPattern; - createFieldList: CreateIndexPatternFieldList; - createField: ( - indexPattern: IndexPattern, - spec: FieldSpec | Field, - shortDotsEnable: boolean - ) => Field; constructor({ uiSettings, @@ -91,16 +84,15 @@ export class IndexPatternsService { uiSettings, onRedirectNoIndexPattern ); - this.createFieldList = getIndexPatternFieldListCreator({ - fieldFormats, - onNotification, - }); - this.createField = (indexPattern, spec, shortDotsEnable) => { - return new Field(indexPattern, spec, shortDotsEnable, { - fieldFormats, - onNotification, - }); - }; + } + + public createField( + indexPattern: IndexPattern, + spec: IndexPatternField['spec'], + displayName: string, + onNotification: OnNotification + ) { + return new IndexPatternField(indexPattern, spec, displayName, onNotification); } private async refreshSavedObjectsCache() { diff --git a/src/plugins/data/common/index_patterns/mocks.ts b/src/plugins/data/common/index_patterns/mocks.ts index 6036c08fa2b10..faf1b8307ea2e 100644 --- a/src/plugins/data/common/index_patterns/mocks.ts +++ b/src/plugins/data/common/index_patterns/mocks.ts @@ -17,4 +17,4 @@ * under the License. */ -export * from './fields/fields.mocks.ts'; +export * from './fields/fields.mocks'; diff --git a/src/plugins/data/common/index_patterns/types.ts b/src/plugins/data/common/index_patterns/types.ts index 4241df5718243..a771113acd231 100644 --- a/src/plugins/data/common/index_patterns/types.ts +++ b/src/plugins/data/common/index_patterns/types.ts @@ -149,8 +149,21 @@ export interface FieldSpecExportFmt { } export interface FieldSpec { - [key: string]: any; + count?: number; + script?: string; + lang?: string; + conflictDescriptions?: Record; format?: SerializedFieldFormat; + + name: string; + type: string; + esTypes?: string[]; + scripted?: boolean; + searchable: boolean; + aggregatable: boolean; + readFromDocValues?: boolean; + subType?: IFieldSubType; + indexed?: boolean; } export interface IndexPatternSpec { diff --git a/src/plugins/data/common/kbn_field_types/kbn_field_types.test.ts b/src/plugins/data/common/kbn_field_types/kbn_field_types.test.ts index a3fe19fa9b2fc..6a2d6edd04692 100644 --- a/src/plugins/data/common/kbn_field_types/kbn_field_types.test.ts +++ b/src/plugins/data/common/kbn_field_types/kbn_field_types.test.ts @@ -55,10 +55,10 @@ describe('utils/kbn_field_types', () => { expect(kbnFieldType).toHaveProperty('name', ES_FIELD_TYPES.STRING); }); - test('returns undefined for invalid name', () => { + test('returns unknown for invalid name', () => { const kbnFieldType = getKbnFieldType('wrongType'); - expect(kbnFieldType).toBeUndefined(); + expect(kbnFieldType).toHaveProperty('name', KBN_FIELD_TYPES.UNKNOWN); }); }); diff --git a/src/plugins/data/common/kbn_field_types/kbn_field_types.ts b/src/plugins/data/common/kbn_field_types/kbn_field_types.ts index ce05dc796bbab..ffeb9c517daf5 100644 --- a/src/plugins/data/common/kbn_field_types/kbn_field_types.ts +++ b/src/plugins/data/common/kbn_field_types/kbn_field_types.ts @@ -17,7 +17,7 @@ * under the License. */ -import { createKbnFieldTypes } from './kbn_field_types_factory'; +import { createKbnFieldTypes, kbnFieldTypeUnknown } from './kbn_field_types_factory'; import { KbnFieldType } from './kbn_field_type'; import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from './types'; @@ -30,8 +30,8 @@ const registeredKbnTypes = createKbnFieldTypes(); * @param {string} typeName * @return {KbnFieldType} */ -export const getKbnFieldType = (typeName: string): KbnFieldType | undefined => - registeredKbnTypes.find((t) => t.name === typeName); +export const getKbnFieldType = (typeName: string): KbnFieldType => + registeredKbnTypes.find((t) => t.name === typeName) || kbnFieldTypeUnknown; /** * Get the esTypes known by all kbnFieldTypes diff --git a/src/plugins/data/common/kbn_field_types/kbn_field_types_factory.ts b/src/plugins/data/common/kbn_field_types/kbn_field_types_factory.ts index cb9357eb9865e..b93ebcbbca9c8 100644 --- a/src/plugins/data/common/kbn_field_types/kbn_field_types_factory.ts +++ b/src/plugins/data/common/kbn_field_types/kbn_field_types_factory.ts @@ -20,6 +20,10 @@ import { KbnFieldType } from './kbn_field_type'; import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from './types'; +export const kbnFieldTypeUnknown = new KbnFieldType({ + name: KBN_FIELD_TYPES.UNKNOWN, +}); + export const createKbnFieldTypes = (): KbnFieldType[] => [ new KbnFieldType({ name: KBN_FIELD_TYPES.STRING, @@ -103,7 +107,5 @@ export const createKbnFieldTypes = (): KbnFieldType[] => [ new KbnFieldType({ name: KBN_FIELD_TYPES.CONFLICT, }), - new KbnFieldType({ - name: KBN_FIELD_TYPES.UNKNOWN, - }), + kbnFieldTypeUnknown, ]; diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index e95150e8f6f73..5a9930d2b6b56 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -249,9 +249,7 @@ export { IndexPatternsContract, IndexPattern, IIndexPatternFieldList, - Field as IndexPatternField, - // TODO: exported only in stub_index_pattern test. Move into data plugin and remove export. - getIndexPatternFieldListCreator, + IndexPatternField, } from './index_patterns'; export { @@ -264,6 +262,7 @@ export { UI_SETTINGS, TypeMeta as IndexPatternTypeMeta, AggregationRestrictions as IndexPatternAggRestrictions, + FieldList, } from '../common'; /* diff --git a/src/plugins/data/public/index_patterns/index.ts b/src/plugins/data/public/index_patterns/index.ts index a6ee71c624f5a..9cd5e5a4736f1 100644 --- a/src/plugins/data/public/index_patterns/index.ts +++ b/src/plugins/data/public/index_patterns/index.ts @@ -28,11 +28,7 @@ export { } from '../../common/index_patterns/lib'; export { flattenHitWrapper, formatHitProvider, onRedirectNoIndexPattern } from './index_patterns'; -export { - getIndexPatternFieldListCreator, - Field, - IIndexPatternFieldList, -} from '../../common/index_patterns'; +export { IndexPatternField, IIndexPatternFieldList } from '../../common/index_patterns'; export { IndexPatternsService, diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 2cfdab80123ed..adff7b205b931 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -576,6 +576,46 @@ export type FieldFormatsContentType = 'html' | 'text'; // @public (undocumented) export type FieldFormatsGetConfigFn = (key: string, defaultOverride?: T) => T; +// Warning: (ae-missing-release-tag) "FieldList" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class FieldList extends Array implements IIndexPatternFieldList { + // Warning: (ae-forgotten-export) The symbol "FieldSpec" needs to be exported by the entry point index.d.ts + constructor(indexPattern: IndexPattern, specs?: FieldSpec[], shortDotsEnable?: boolean, onNotification?: () => void); + // (undocumented) + readonly add: (field: FieldSpec) => void; + // (undocumented) + readonly getAll: () => IndexPatternField[]; + // (undocumented) + readonly getByName: (name: IndexPatternField['name']) => IndexPatternField | undefined; + // (undocumented) + readonly getByType: (type: IndexPatternField['type']) => any[]; + // (undocumented) + readonly remove: (field: IFieldType) => void; + // (undocumented) + readonly removeAll: () => void; + // (undocumented) + readonly replaceAll: (specs: FieldSpec[]) => void; + // (undocumented) + readonly toSpec: () => { + count: number; + script: string | undefined; + lang: string | undefined; + conflictDescriptions: Record | undefined; + name: string; + type: string; + esTypes: string[] | undefined; + scripted: boolean; + searchable: boolean; + aggregatable: boolean; + readFromDocValues: boolean; + subType: import("../types").IFieldSubType | undefined; + format: any; + }[]; + // (undocumented) + readonly update: (field: FieldSpec) => void; +} + // @public (undocumented) export interface FieldMappingSpec { // (undocumented) @@ -658,13 +698,6 @@ export function getDefaultQuery(language?: QueryLanguage): { // @public (undocumented) export function getEsPreference(uiSettings: IUiSettingsClient_2, sessionId?: string): any; -// Warning: (ae-forgotten-export) The symbol "FieldListDependencies" needs to be exported by the entry point index.d.ts -// Warning: (ae-forgotten-export) The symbol "CreateIndexPatternFieldList" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "getIndexPatternFieldListCreator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const getIndexPatternFieldListCreator: ({ fieldFormats, onNotification, }: FieldListDependencies) => CreateIndexPatternFieldList; - // Warning: (ae-missing-release-tag) "getKbnTypeNames" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public @@ -808,8 +841,6 @@ export interface IFieldType { sortable?: boolean; // (undocumented) subType?: IFieldSubType; - // Warning: (ae-forgotten-export) The symbol "FieldSpec" needs to be exported by the entry point index.d.ts - // // (undocumented) toSpec?: () => FieldSpec; // (undocumented) @@ -850,12 +881,18 @@ export interface IIndexPatternFieldList extends Array { // (undocumented) add(field: FieldSpec): void; // (undocumented) + getAll(): IndexPatternField[]; + // (undocumented) getByName(name: IndexPatternField['name']): IndexPatternField | undefined; // (undocumented) getByType(type: IndexPatternField['type']): IndexPatternField[]; // (undocumented) remove(field: IFieldType): void; // (undocumented) + removeAll(): void; + // (undocumented) + replaceAll(specs: FieldSpec[]): void; + // (undocumented) update(field: FieldSpec): void; } @@ -929,7 +966,9 @@ export class IndexPattern implements IIndexPattern { }[]; }; // (undocumented) - getFieldByName(name: string): IndexPatternField | void; + getFieldByName(name: string): IndexPatternField | undefined; + // (undocumented) + getFormatterForField(field: IndexPatternField | IndexPatternField['spec']): FieldFormat; // (undocumented) getNonScriptedFields(): IndexPatternField[]; // (undocumented) @@ -967,7 +1006,7 @@ export class IndexPattern implements IIndexPattern { // (undocumented) refreshFields(): Promise; // (undocumented) - removeScriptedField(field: IFieldType): Promise; + removeScriptedField(fieldName: string): Promise; // (undocumented) save(saveAttempts?: number): Promise; // (undocumented) @@ -1018,55 +1057,85 @@ export interface IndexPatternAttributes { typeMeta: string; } -// Warning: (ae-missing-release-tag) "Field" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// Warning: (ae-missing-release-tag) "IndexPatternField" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export class IndexPatternField implements IFieldType { + // Warning: (ae-forgotten-export) The symbol "OnNotification" needs to be exported by the entry point index.d.ts + constructor(indexPattern: IndexPattern, spec: FieldSpec, displayName: string, onNotification: OnNotification); // (undocumented) - $$spec: FieldSpec; - // Warning: (ae-forgotten-export) The symbol "FieldSpecExportFmt" needs to be exported by the entry point index.d.ts - // Warning: (ae-forgotten-export) The symbol "FieldDependencies" needs to be exported by the entry point index.d.ts - constructor(indexPattern: IIndexPattern, spec: FieldSpecExportFmt | FieldSpec | IndexPatternField, shortDotsEnable: boolean, { fieldFormats, onNotification }: FieldDependencies); + get aggregatable(): boolean; // (undocumented) - aggregatable?: boolean; - // Warning: (ae-forgotten-export) The symbol "FieldSpecConflictDescriptions" needs to be exported by the entry point index.d.ts - // + get conflictDescriptions(): Record | undefined; + set conflictDescriptions(conflictDescriptions: Record | undefined); // (undocumented) - conflictDescriptions?: FieldSpecConflictDescriptions; + get count(): number; + set count(count: number); // (undocumented) - count?: number; + readonly displayName: string; // (undocumented) - displayName?: string; + get esTypes(): string[] | undefined; // (undocumented) - esTypes?: string[]; + get filterable(): boolean; // (undocumented) - filterable?: boolean; + get format(): FieldFormat; // (undocumented) - format: any; + readonly indexPattern: IndexPattern; // (undocumented) - indexPattern?: IIndexPattern; + get lang(): string | undefined; + set lang(lang: string | undefined); // (undocumented) - lang?: string; + get name(): string; // (undocumented) - name: string; + get readFromDocValues(): boolean; // (undocumented) - readFromDocValues?: boolean; + get script(): string | undefined; + set script(script: string | undefined); // (undocumented) - script?: string; + get scripted(): boolean; // (undocumented) - scripted?: boolean; + get searchable(): boolean; // (undocumented) - searchable?: boolean; + get sortable(): boolean; // (undocumented) - sortable?: boolean; + readonly spec: FieldSpec; // (undocumented) - subType?: IFieldSubType; + get subType(): import("../types").IFieldSubType | undefined; // (undocumented) - toSpec: () => FieldSpecExportFmt; + toJSON(): { + count: number; + script: string | undefined; + lang: string | undefined; + conflictDescriptions: Record | undefined; + name: string; + type: string; + esTypes: string[] | undefined; + scripted: boolean; + searchable: boolean; + aggregatable: boolean; + readFromDocValues: boolean; + subType: import("../types").IFieldSubType | undefined; + }; // (undocumented) - type: string; + toSpec(): { + count: number; + script: string | undefined; + lang: string | undefined; + conflictDescriptions: Record | undefined; + name: string; + type: string; + esTypes: string[] | undefined; + scripted: boolean; + searchable: boolean; + aggregatable: boolean; + readFromDocValues: boolean; + subType: import("../types").IFieldSubType | undefined; + format: any; + }; // (undocumented) - visualizable?: boolean; + get type(): string; + // (undocumented) + get visualizable(): boolean; } // Warning: (ae-missing-release-tag) "indexPatterns" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -1899,21 +1968,21 @@ export const UI_SETTINGS: { // src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "getFromSavedObject" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:371:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:371:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:371:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:371:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:373:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:374:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:383:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:384:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:385:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:386:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:390:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:391:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:394:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:395:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:398:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:370:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:370:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:370:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:370:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:372:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:373:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:382:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:383:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:384:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:385:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:389:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:390:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:393:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:394:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:397:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts // src/plugins/data/public/query/state_sync/connect_to_query_state.ts:45:5 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts // src/plugins/data/public/types.ts:54:5 - (ae-forgotten-export) The symbol "createFiltersFromValueClickAction" needs to be exported by the entry point index.d.ts // src/plugins/data/public/types.ts:55:5 - (ae-forgotten-export) The symbol "createFiltersFromRangeSelectAction" needs to be exported by the entry point index.d.ts diff --git a/src/plugins/data/public/search/aggs/agg_configs.test.ts b/src/plugins/data/public/search/aggs/agg_configs.test.ts index df4a5420ae0db..ff0cc3341929e 100644 --- a/src/plugins/data/public/search/aggs/agg_configs.test.ts +++ b/src/plugins/data/public/search/aggs/agg_configs.test.ts @@ -22,7 +22,7 @@ import { AggConfig } from './agg_config'; import { AggConfigs } from './agg_configs'; import { AggTypesRegistryStart } from './agg_types_registry'; import { mockAggTypesRegistry } from './test_helpers'; -import { Field as IndexPatternField, IndexPattern } from '../../index_patterns'; +import { IndexPatternField, IndexPattern } from '../../index_patterns'; import { stubIndexPattern, stubIndexPatternWithFields } from '../../../public/stubs'; describe('AggConfigs', () => { diff --git a/src/plugins/data/public/search/aggs/param_types/field.ts b/src/plugins/data/public/search/aggs/param_types/field.ts index cb3617b02e882..7c00bc668a39f 100644 --- a/src/plugins/data/public/search/aggs/param_types/field.ts +++ b/src/plugins/data/public/search/aggs/param_types/field.ts @@ -23,7 +23,7 @@ import { SavedObjectNotFound } from '../../../../../../plugins/kibana_utils/comm import { BaseParamType } from './base'; import { propFilter } from '../utils'; import { isNestedField, KBN_FIELD_TYPES } from '../../../../common'; -import { Field as IndexPatternField } from '../../../index_patterns'; +import { IndexPatternField } from '../../../index_patterns'; const filterByType = propFilter('type'); diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index e6eca16c5ca4b..677ad0ccea677 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -170,7 +170,7 @@ export class SearchInterceptor { if (this.longRunningToast) return; this.longRunningToast = this.deps.toasts.addInfo( { - title: 'Your query is taking awhile', + title: 'Your query is taking a while', text: getLongQueryNotification({ application: this.deps.application, }), diff --git a/src/plugins/discover/public/application/angular/context.js b/src/plugins/discover/public/application/angular/context.js index a6f591eebb52d..6223090aa9f97 100644 --- a/src/plugins/discover/public/application/angular/context.js +++ b/src/plugins/discover/public/application/angular/context.js @@ -83,6 +83,7 @@ function ContextAppRouteController($routeParams, $scope, $route) { timeFieldName: indexPattern.timeFieldName, storeInSessionStorage: getServices().uiSettings.get('state:storeInSessionStorage'), history: getServices().history(), + toasts: getServices().core.notifications.toasts, }); this.state = { ...appState.getState() }; this.anchorId = $routeParams.id; diff --git a/src/plugins/discover/public/application/angular/context_state.ts b/src/plugins/discover/public/application/angular/context_state.ts index 7a92a6ace125b..5b05d8729c41d 100644 --- a/src/plugins/discover/public/application/angular/context_state.ts +++ b/src/plugins/discover/public/application/angular/context_state.ts @@ -18,11 +18,13 @@ */ import _ from 'lodash'; import { History } from 'history'; +import { NotificationsStart } from 'kibana/public'; import { createStateContainer, createKbnUrlStateStorage, syncStates, BaseStateContainer, + withNotifyOnErrors, } from '../../../../kibana_utils/public'; import { esFilters, FilterManager, Filter, Query } from '../../../../data/public'; @@ -74,6 +76,13 @@ interface GetStateParams { * History instance to use */ history: History; + + /** + * Core's notifications.toasts service + * In case it is passed in, + * kbnUrlStateStorage will use it notifying about inner errors + */ + toasts?: NotificationsStart['toasts']; } interface GetStateReturn { @@ -123,10 +132,12 @@ export function getState({ timeFieldName, storeInSessionStorage = false, history, + toasts, }: GetStateParams): GetStateReturn { const stateStorage = createKbnUrlStateStorage({ useHash: storeInSessionStorage, history, + ...(toasts && withNotifyOnErrors(toasts)), }); const globalStateInitial = stateStorage.get(GLOBAL_STATE_URL_KEY) as GlobalState; diff --git a/src/plugins/discover/public/application/angular/discover.js b/src/plugins/discover/public/application/angular/discover.js index 4a27f261a6220..22da3e877054a 100644 --- a/src/plugins/discover/public/application/angular/discover.js +++ b/src/plugins/discover/public/application/angular/discover.js @@ -220,6 +220,7 @@ function discoverController($element, $route, $scope, $timeout, $window, Promise defaultAppState: getStateDefaults(), storeInSessionStorage: config.get('state:storeInSessionStorage'), history, + toasts: core.notifications.toasts, }); if (appStateContainer.getState().index !== $scope.indexPattern.id) { //used index pattern is different than the given by url/state which is invalid diff --git a/src/plugins/discover/public/application/angular/discover_state.ts b/src/plugins/discover/public/application/angular/discover_state.ts index 46500d9fdf85e..ff8fb9f80a723 100644 --- a/src/plugins/discover/public/application/angular/discover_state.ts +++ b/src/plugins/discover/public/application/angular/discover_state.ts @@ -18,12 +18,14 @@ */ import { isEqual } from 'lodash'; import { History } from 'history'; +import { NotificationsStart } from 'kibana/public'; import { createStateContainer, createKbnUrlStateStorage, syncState, ReduxLikeStateContainer, IKbnUrlStateStorage, + withNotifyOnErrors, } from '../../../../kibana_utils/public'; import { esFilters, Filter, Query } from '../../../../data/public'; import { migrateLegacyQuery } from '../../../../kibana_legacy/public'; @@ -68,6 +70,13 @@ interface GetStateParams { * Browser history */ history: History; + + /** + * Core's notifications.toasts service + * In case it is passed in, + * kbnUrlStateStorage will use it notifying about inner errors + */ + toasts?: NotificationsStart['toasts']; } export interface GetStateReturn { @@ -122,10 +131,12 @@ export function getState({ defaultAppState = {}, storeInSessionStorage = false, history, + toasts, }: GetStateParams): GetStateReturn { const stateStorage = createKbnUrlStateStorage({ useHash: storeInSessionStorage, history, + ...(toasts && withNotifyOnErrors(toasts)), }); const appStateFromUrl = stateStorage.get(APP_STATE_URL_KEY) as AppState; diff --git a/src/plugins/discover/public/application/angular/doc_table/components/row_headers.test.js b/src/plugins/discover/public/application/angular/doc_table/components/row_headers.test.js index b30b13b1f0b6e..d85ca6a072890 100644 --- a/src/plugins/discover/public/application/angular/doc_table/components/row_headers.test.js +++ b/src/plugins/discover/public/application/angular/doc_table/components/row_headers.test.js @@ -23,7 +23,7 @@ import 'angular-sanitize'; import 'angular-route'; import _ from 'lodash'; import sinon from 'sinon'; -import { getFakeRow, getFakeRowVals } from 'fixtures/fake_row'; +import { getFakeRow } from 'fixtures/fake_row'; import $ from 'jquery'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import { setScopedHistory, setServices, setDocViewsRegistry } from '../../../../kibana_services'; @@ -33,6 +33,13 @@ import { navigationPluginMock } from '../../../../../../navigation/public/mocks' import { getInnerAngularModule } from '../../../../get_inner_angular'; import { createBrowserHistory } from 'history'; +const fakeRowVals = { + time: 'time_formatted', + bytes: 'bytes_formatted', + '@timestamp': '@timestamp_formatted', + request_body: 'request_body_formatted', +}; + describe('Doc Table', () => { const core = coreMock.createStart(); const dataMock = dataPluginMock.createStartContract(); @@ -45,8 +52,6 @@ describe('Doc Table', () => { // Stub out a minimal mapping of 4 fields let mapping; - let fakeRowVals; - let stubFieldFormatConverter; beforeAll(() => setScopedHistory(createBrowserHistory())); beforeEach(() => { angular.element.prototype.slice = jest.fn(function (index) { @@ -97,21 +102,15 @@ describe('Doc Table', () => { mapping = $parentScope.indexPattern.fields; // Stub `getConverterFor` for a field in the indexPattern to return mock data. - // Returns `val` if provided, otherwise generates fake data for the field. - fakeRowVals = getFakeRowVals('formatted', 0, mapping); - stubFieldFormatConverter = function ($root, field, val) { - const convertFn = (value, type, options) => { - if (val) { - return val; - } - const fieldName = _.get(options, 'field.name', null); - - return fakeRowVals[fieldName] || ''; - }; - - $root.indexPattern.fields.getByName(field).format.convert = convertFn; - $root.indexPattern.fields.getByName(field).format.getConverterFor = () => convertFn; + + const convertFn = (value, type, options) => { + const fieldName = _.get(options, 'field.name', null); + return fakeRowVals[fieldName] || ''; }; + $parentScope.indexPattern.getFormatterForField = () => ({ + convert: convertFn, + getConverterFor: () => convertFn, + }); }) ); @@ -148,9 +147,6 @@ describe('Doc Table', () => { test('should be able to add and remove columns', () => { let childElems; - stubFieldFormatConverter($parentScope, 'bytes'); - stubFieldFormatConverter($parentScope, 'request_body'); - // Should include a column for toggling and the time column by default $parentScope.columns = ['bytes']; $elementScope.$digest(); @@ -302,9 +298,6 @@ describe('Doc Table', () => { $root.mapping = mapping; $root.indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - // Stub field format converters for every field in the indexPattern - $root.indexPattern.fields.forEach((f) => stubFieldFormatConverter($root, f.name)); - $row = $('').attr({ 'kbn-table-row': 'row', columns: 'columns', @@ -417,7 +410,8 @@ describe('Doc Table', () => { }); test('handles two columns with the same content', () => { - stubFieldFormatConverter($root, 'request_body', fakeRowVals.bytes); + const tempVal = fakeRowVals.request_body; + fakeRowVals.request_body = 'bytes_formatted'; $root.columns.length = 0; $root.columns.push('bytes'); @@ -428,6 +422,7 @@ describe('Doc Table', () => { expect($after).toHaveLength(4); expect($after.eq(2).text().trim()).toMatch(/^bytes_formatted/); expect($after.eq(3).text().trim()).toMatch(/^bytes_formatted/); + fakeRowVals.request_body = tempVal; }); test('handles two columns swapping position', () => { diff --git a/src/plugins/discover/public/application/components/sidebar/discover_field.test.tsx b/src/plugins/discover/public/application/components/sidebar/discover_field.test.tsx index 099ec2e5b1ffc..3f12a8c0fa769 100644 --- a/src/plugins/discover/public/application/components/sidebar/discover_field.test.tsx +++ b/src/plugins/discover/public/application/components/sidebar/discover_field.test.tsx @@ -28,7 +28,6 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers'; import { DiscoverField } from './discover_field'; import { coreMock } from '../../../../../../core/public/mocks'; import { IndexPatternField } from '../../../../../data/public'; -import { FieldSpecExportFmt } from '../../../../../data/common'; jest.mock('../../../kibana_services', () => ({ getServices: () => ({ @@ -63,20 +62,21 @@ function getComponent(selected = false, showDetails = false, useShortDots = fals coreMock.createStart() ); - const field = { - name: 'bytes', - type: 'number', - esTypes: ['long'], - count: 10, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - format: null, - routes: {}, - $$spec: {}, - toSpec: () => (({} as unknown) as FieldSpecExportFmt), - } as IndexPatternField; + const field = new IndexPatternField( + indexPattern, + { + name: 'bytes', + type: 'number', + esTypes: ['long'], + count: 10, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + 'bytes', + () => {} + ); const props = { indexPattern, diff --git a/src/plugins/discover/public/application/components/sidebar/discover_sidebar.tsx b/src/plugins/discover/public/application/components/sidebar/discover_sidebar.tsx index e8ed8b80da3bb..58b468762c501 100644 --- a/src/plugins/discover/public/application/components/sidebar/discover_sidebar.tsx +++ b/src/plugins/discover/public/application/components/sidebar/discover_sidebar.tsx @@ -29,12 +29,7 @@ import { IndexPatternAttributes } from '../../../../../data/common'; import { SavedObject } from '../../../../../../core/types'; import { FIELDS_LIMIT_SETTING } from '../../../../common'; import { groupFields } from './lib/group_fields'; -import { - IIndexPatternFieldList, - IndexPatternField, - IndexPattern, - UI_SETTINGS, -} from '../../../../../data/public'; +import { IndexPatternField, IndexPattern, UI_SETTINGS } from '../../../../../data/public'; import { AppState } from '../../angular/discover_state'; import { getDetails } from './lib/get_details'; import { getDefaultFieldFilter, setFieldFilterProp } from './lib/field_filter'; @@ -99,12 +94,12 @@ export function DiscoverSidebar({ }: DiscoverSidebarProps) { const [openFieldMap, setOpenFieldMap] = useState(new Map()); const [showFields, setShowFields] = useState(false); - const [fields, setFields] = useState(null); + const [fields, setFields] = useState(null); const [fieldFilterState, setFieldFilterState] = useState(getDefaultFieldFilter()); const services = useMemo(() => getServices(), []); useEffect(() => { - const newFields = getIndexPatternFieldList(selectedIndexPattern, fieldCounts, services); + const newFields = getIndexPatternFieldList(selectedIndexPattern, fieldCounts); setFields(newFields); }, [selectedIndexPattern, fieldCounts, hits, services]); diff --git a/src/plugins/discover/public/application/components/sidebar/lib/get_index_pattern_field_list.ts b/src/plugins/discover/public/application/components/sidebar/lib/get_index_pattern_field_list.ts index 0fcbe925e0798..00e00aa8e2991 100644 --- a/src/plugins/discover/public/application/components/sidebar/lib/get_index_pattern_field_list.ts +++ b/src/plugins/discover/public/application/components/sidebar/lib/get_index_pattern_field_list.ts @@ -16,27 +16,25 @@ * specific language governing permissions and limitations * under the License. */ -import { difference, map } from 'lodash'; +import { difference } from 'lodash'; import { IndexPattern, IndexPatternField } from 'src/plugins/data/public'; -import { DiscoverServices } from '../../../../build_services'; export function getIndexPatternFieldList( indexPattern: IndexPattern, - fieldCounts: Record, - { data }: DiscoverServices + fieldCounts: Record ) { - if (!indexPattern || !fieldCounts) return data.indexPatterns.createFieldList(indexPattern); + if (!indexPattern || !fieldCounts) return []; - const fieldSpecs = indexPattern.fields.slice(0); const fieldNamesInDocs = Object.keys(fieldCounts); - const fieldNamesInIndexPattern = map(indexPattern.fields, 'name'); + const fieldNamesInIndexPattern = indexPattern.fields.getAll().map((fld) => fld.name); + const unknownTypes: IndexPatternField[] = []; difference(fieldNamesInDocs, fieldNamesInIndexPattern).forEach((unknownFieldName) => { - fieldSpecs.push({ + unknownTypes.push({ name: String(unknownFieldName), type: 'unknown', } as IndexPatternField); }); - return data.indexPatterns.createFieldList(indexPattern, fieldSpecs); + return [...indexPattern.fields.getAll(), ...unknownTypes]; } diff --git a/src/plugins/discover/public/application/components/sidebar/lib/group_fields.tsx b/src/plugins/discover/public/application/components/sidebar/lib/group_fields.tsx index fab4637d87ca7..c6a06618900fd 100644 --- a/src/plugins/discover/public/application/components/sidebar/lib/group_fields.tsx +++ b/src/plugins/discover/public/application/components/sidebar/lib/group_fields.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { IIndexPatternFieldList, IndexPatternField } from 'src/plugins/data/public'; +import { IndexPatternField } from 'src/plugins/data/public'; import { FieldFilterState, isFieldFiltered } from './field_filter'; interface GroupedFields { @@ -29,7 +29,7 @@ interface GroupedFields { * group the fields into selected, popular and unpopular, filter by fieldFilterState */ export function groupFields( - fields: IIndexPatternFieldList | null, + fields: IndexPatternField[] | null, columns: string[], popularLimit: number, fieldCounts: Record, diff --git a/src/plugins/discover/public/application/components/table/table.test.tsx b/src/plugins/discover/public/application/components/table/table.test.tsx index 0793072fd0cf4..29659b3969365 100644 --- a/src/plugins/discover/public/application/components/table/table.test.tsx +++ b/src/plugins/discover/public/application/components/table/table.test.tsx @@ -24,45 +24,47 @@ import { DocViewTable } from './table'; import { indexPatterns, IndexPattern } from '../../../../../data/public'; const indexPattern = { - fields: [ - { - name: '_index', - type: 'string', - scripted: false, - filterable: true, - }, - { - name: 'message', - type: 'string', - scripted: false, - filterable: false, - }, - { - name: 'extension', - type: 'string', - scripted: false, - filterable: true, - }, - { - name: 'bytes', - type: 'number', - scripted: false, - filterable: true, - }, - { - name: 'scripted', - type: 'number', - scripted: true, - filterable: false, - }, - ], + fields: { + getAll: () => [ + { + name: '_index', + type: 'string', + scripted: false, + filterable: true, + }, + { + name: 'message', + type: 'string', + scripted: false, + filterable: false, + }, + { + name: 'extension', + type: 'string', + scripted: false, + filterable: true, + }, + { + name: 'bytes', + type: 'number', + scripted: false, + filterable: true, + }, + { + name: 'scripted', + type: 'number', + scripted: true, + filterable: false, + }, + ], + }, metaFields: ['_index', '_score'], flattenHit: undefined, formatHit: jest.fn((hit) => hit._source), } as IndexPattern; indexPattern.fields.getByName = (name: string) => { - return indexPattern.fields.find((field) => field.name === name); + return indexPattern.fields.getAll().find((field) => field.name === name); }; indexPattern.flattenHit = indexPatterns.flattenHitWrapper(indexPattern, indexPattern.metaFields); diff --git a/src/plugins/discover/public/application/components/table/table.tsx b/src/plugins/discover/public/application/components/table/table.tsx index 9b95f2fc6bd27..628045bd32f61 100644 --- a/src/plugins/discover/public/application/components/table/table.tsx +++ b/src/plugins/discover/public/application/components/table/table.tsx @@ -104,15 +104,13 @@ export function DocViewTable({ // to the index pattern, but that has its own complications which you can read more about in the following // issue: https://github.com/elastic/kibana/issues/54957 const isNestedField = - !indexPattern.fields.find((patternField) => patternField.name === field) && - !!indexPattern.fields.find((patternField) => { + !indexPattern.fields.getByName(field) && + !!indexPattern.fields.getAll().find((patternField) => { // We only want to match a full path segment const nestedRootRegex = new RegExp(escapeRegExp(field) + '(\\.|$)'); return nestedRootRegex.test(patternField.subType?.nested?.path ?? ''); }); - const fieldType = isNestedField - ? 'nested' - : indexPattern.fields.find((patternField) => patternField.name === field)?.type; + const fieldType = isNestedField ? 'nested' : indexPattern.fields.getByName(field)?.type; return ( `math`. Another case, `IndexManagement` -> `index_management`. +2. Write your function in `./__packages_do_not_import__/math/calculate_fibonacci.ts`, adding any relevant tests in the same folder. +3. Export functionality intended _for consumers_ from `./__packages_do_not_import__/math/index.ts`. +4. Create a folder `./public/math`. +5. Export all functionality from `./__packages_do_not_import__/math` in `./public/math/index.ts`. +6. In `./public/index.ts` import `./public/math` using `import * as Math from './public/math;`. The name (`Math`) given here is really important and will be what consumers depend on. +7. Add the `Math` module to the list of exported modules in `./public/index.ts`, e.g. `export { <...other modules>, Math }` +8. Use `Math` in your public side code elsewhere! + +This example assumes no other appropriate home for such a function exists. diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx index f7b982ef1659e..22bc78ee0538e 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx @@ -21,7 +21,7 @@ import { withRouter, RouteComponentProps } from 'react-router-dom'; import { EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { IndexPattern } from '../../../../../../plugins/data/public'; +import { IndexPattern, IndexPatternField } from '../../../../../../plugins/data/public'; import { useKibana } from '../../../../../../plugins/kibana_react/public'; import { IndexPatternManagmentContext } from '../../../types'; import { IndexHeader } from '../index_header'; @@ -44,24 +44,21 @@ const newFieldPlaceholder = i18n.translate( export const CreateEditField = withRouter( ({ indexPattern, mode, fieldName, history }: CreateEditFieldProps) => { - const { data, uiSettings, chrome, notifications } = useKibana< + const { uiSettings, chrome, notifications } = useKibana< IndexPatternManagmentContext >().services; - const field = + const spec = mode === 'edit' && fieldName - ? indexPattern.fields.getByName(fieldName) - : data.indexPatterns.createField( - indexPattern, - { - scripted: true, - type: 'number', - }, - false - ); + ? indexPattern.fields.getByName(fieldName)?.spec + : (({ + scripted: true, + type: 'number', + name: undefined, + } as unknown) as IndexPatternField); const url = `/patterns/${indexPattern.id}`; - if (mode === 'edit' && !field) { + if (mode === 'edit' && !spec) { const message = i18n.translate( 'indexPatternManagement.editIndexPattern.scripted.noFieldLabel', { @@ -74,17 +71,17 @@ export const CreateEditField = withRouter( history.push(url); } - const docFieldName = field?.name || newFieldPlaceholder; + const docFieldName = spec?.name || newFieldPlaceholder; chrome.docTitle.change([docFieldName, indexPattern.title]); const redirectAway = () => { history.push( - `${url}#/?_a=(tab:${field?.scripted ? TAB_SCRIPTED_FIELDS : TAB_INDEXED_FIELDS})` + `${url}#/?_a=(tab:${spec?.scripted ? TAB_SCRIPTED_FIELDS : TAB_INDEXED_FIELDS})` ); }; - if (field) { + if (spec) { return ( @@ -97,7 +94,7 @@ export const CreateEditField = withRouter( ().services; const [fields, setFields] = useState(indexPattern.getNonScriptedFields()); const [conflictedFields, setConflictedFields] = useState( - indexPattern.fields.filter((field) => field.type === 'conflict') + indexPattern.fields.getAll().filter((field) => field.type === 'conflict') ); const [defaultIndex, setDefaultIndex] = useState(uiSettings.get('defaultIndex')); const [tags, setTags] = useState([]); useEffect(() => { setFields(indexPattern.getNonScriptedFields()); - setConflictedFields(indexPattern.fields.filter((field) => field.type === 'conflict')); + setConflictedFields( + indexPattern.fields.getAll().filter((field) => field.type === 'conflict') + ); }, [indexPattern]); useEffect(() => { diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/__snapshots__/indexed_fields_table.test.tsx.snap b/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/__snapshots__/indexed_fields_table.test.tsx.snap index db2a032b1e4d9..47cabc4df662f 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/__snapshots__/indexed_fields_table.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/__snapshots__/indexed_fields_table.test.tsx.snap @@ -15,7 +15,9 @@ exports[`IndexedFieldsTable should filter based on the query bar 1`] = ` "displayName": "Elastic", "excluded": false, "format": undefined, - "indexPattern": undefined, + "indexPattern": Object { + "getNonScriptedFields": [Function], + }, "info": Array [], "name": "Elastic", "searchable": true, @@ -42,7 +44,9 @@ exports[`IndexedFieldsTable should filter based on the type filter 1`] = ` "displayName": "timestamp", "excluded": false, "format": undefined, - "indexPattern": undefined, + "indexPattern": Object { + "getNonScriptedFields": [Function], + }, "info": Array [], "name": "timestamp", "type": "date", @@ -68,7 +72,9 @@ exports[`IndexedFieldsTable should render normally 1`] = ` "displayName": "Elastic", "excluded": false, "format": undefined, - "indexPattern": undefined, + "indexPattern": Object { + "getNonScriptedFields": [Function], + }, "info": Array [], "name": "Elastic", "searchable": true, @@ -78,7 +84,9 @@ exports[`IndexedFieldsTable should render normally 1`] = ` "displayName": "timestamp", "excluded": false, "format": undefined, - "indexPattern": undefined, + "indexPattern": Object { + "getNonScriptedFields": [Function], + }, "info": Array [], "name": "timestamp", "type": "date", @@ -87,7 +95,9 @@ exports[`IndexedFieldsTable should render normally 1`] = ` "displayName": "conflictingField", "excluded": false, "format": undefined, - "indexPattern": undefined, + "indexPattern": Object { + "getNonScriptedFields": [Function], + }, "info": Array [], "name": "conflictingField", "type": "conflict", diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.test.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.test.tsx index 8c024fa7adcf5..411bbe23e4761 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.test.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.test.tsx @@ -19,7 +19,7 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { IndexPatternField, IIndexPattern } from 'src/plugins/data/public'; +import { IndexPatternField, IIndexPattern, IndexPattern } from 'src/plugins/data/public'; import { IndexedFieldsTable } from './indexed_fields_table'; jest.mock('@elastic/eui', () => ({ @@ -41,6 +41,19 @@ const helpers = { getFieldInfo: () => [], }; +const indexPattern = ({ + getNonScriptedFields: () => fields, +} as unknown) as IIndexPattern; + +const mockFieldToIndexPatternField = (spec: Record) => { + return new IndexPatternField( + indexPattern as IndexPattern, + (spec as unknown) as IndexPatternField['spec'], + spec.displayName as string, + () => {} + ); +}; + const fields = [ { name: 'Elastic', @@ -50,11 +63,7 @@ const fields = [ }, { name: 'timestamp', displayName: 'timestamp', type: 'date' }, { name: 'conflictingField', displayName: 'conflictingField', type: 'conflict' }, -] as IndexPatternField[]; - -const indexPattern = ({ - getNonScriptedFields: () => fields, -} as unknown) as IIndexPattern; +].map(mockFieldToIndexPatternField); describe('IndexedFieldsTable', () => { test('should render normally', async () => { diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx index 3344c46c35ac6..90f81a88b3da0 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx @@ -75,7 +75,7 @@ export class IndexedFieldsTable extends Component< (fields && fields.map((field) => { return { - ...field, + ...field.spec, displayName: field.displayName, indexPattern: field.indexPattern, format: getFieldFormat(indexPattern, field.name), diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/tabs.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/tabs.tsx index a59dca80a3684..f32eb63ad04b4 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/tabs.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/tabs.tsx @@ -87,7 +87,7 @@ export function Tabs({ indexPattern, fields, history, location }: TabsProps) { const refreshFilters = useCallback(() => { const tempIndexedFieldTypes: string[] = []; const tempScriptedFieldLanguages: string[] = []; - indexPattern.fields.forEach((field) => { + indexPattern.fields.getAll().forEach((field) => { if (field.scripted) { if (field.lang) { tempScriptedFieldLanguages.push(field.lang); diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/utils.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/utils.ts index 5ab9c695caaa0..b422de93de7a9 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/utils.ts +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/utils.ts @@ -84,9 +84,9 @@ export function getTabs( fieldFilter: string, indexPatternListProvider: IndexPatternManagementStart['list'] ) { - const totalCount = getCounts(indexPattern.fields, indexPattern.getSourceFiltering()); + const totalCount = getCounts(indexPattern.fields.getAll(), indexPattern.getSourceFiltering()); const filteredCount = getCounts( - indexPattern.fields, + indexPattern.fields.getAll(), indexPattern.getSourceFiltering(), fieldFilter ); diff --git a/src/plugins/index_pattern_management/public/components/field_editor/__snapshots__/field_editor.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/__snapshots__/field_editor.test.tsx.snap index 7a7545580d82a..3f4190eed9170 100644 --- a/src/plugins/index_pattern_management/public/components/field_editor/__snapshots__/field_editor.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/field_editor/__snapshots__/field_editor.test.tsx.snap @@ -25,11 +25,11 @@ exports[`FieldEditor should render create new scripted field correctly 1`] = ` executeScript={[Function]} indexPattern={ Object { - "fields": Array [ - Object { - "name": "foobar", - }, - ], + "fields": Object { + "getAll": [Function], + "getByName": [Function], + }, + "getFormatterForField": [Function], } } isVisible={false} @@ -260,19 +260,11 @@ exports[`FieldEditor should render edit scripted field correctly 1`] = ` executeScript={[Function]} indexPattern={ Object { - "fields": Array [ - Object { - "name": "foobar", - }, - Object { - "format": Format {}, - "lang": "painless", - "name": "test", - "script": "doc.test.value", - "scripted": true, - "type": "number", - }, - ], + "fields": Object { + "getAll": [Function], + "getByName": [Function], + }, + "getFormatterForField": [Function], } } isVisible={false} @@ -502,27 +494,11 @@ exports[`FieldEditor should show conflict field warning 1`] = ` executeScript={[Function]} indexPattern={ Object { - "fields": Array [ - Object { - "name": "foobar", - }, - Object { - "format": Format {}, - "lang": "painless", - "name": "test", - "script": "doc.test.value", - "scripted": true, - "type": "number", - }, - Object { - "format": Format {}, - "lang": "testlang", - "name": "test", - "script": "doc.test.value", - "scripted": true, - "type": "number", - }, - ], + "fields": Object { + "getAll": [Function], + "getByName": [Function], + }, + "getFormatterForField": [Function], } } isVisible={false} @@ -781,27 +757,11 @@ exports[`FieldEditor should show deprecated lang warning 1`] = ` executeScript={[Function]} indexPattern={ Object { - "fields": Array [ - Object { - "name": "foobar", - }, - Object { - "format": Format {}, - "lang": "painless", - "name": "test", - "script": "doc.test.value", - "scripted": true, - "type": "number", - }, - Object { - "format": Format {}, - "lang": "testlang", - "name": "test", - "script": "doc.test.value", - "scripted": true, - "type": "number", - }, - ], + "fields": Object { + "getAll": [Function], + "getByName": [Function], + }, + "getFormatterForField": [Function], } } isVisible={false} @@ -1112,27 +1072,11 @@ exports[`FieldEditor should show multiple type field warning with a table contai executeScript={[Function]} indexPattern={ Object { - "fields": Array [ - Object { - "name": "foobar", - }, - Object { - "format": Format {}, - "lang": "painless", - "name": "test", - "script": "doc.test.value", - "scripted": true, - "type": "number", - }, - Object { - "format": Format {}, - "lang": "testlang", - "name": "test", - "script": "doc.test.value", - "scripted": true, - "type": "number", - }, - ], + "fields": Object { + "getAll": [Function], + "getByName": [Function], + }, + "getFormatterForField": [Function], } } isVisible={false} diff --git a/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/string/string.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/string/string.tsx index 7a3bb6f5cd398..cdc29e129c457 100644 --- a/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/string/string.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/string/string.tsx @@ -68,7 +68,7 @@ export class StringFormatEditor extends DefaultFormatEditor { + options={(format.type.transformOptions || []).map((option: TransformOptions) => { return { value: option.kind, text: option.text, diff --git a/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/test_script.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/test_script.tsx index cb1d5a25c01ae..77c6698fdc337 100644 --- a/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/test_script.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/test_script.tsx @@ -188,6 +188,7 @@ export class TestScript extends Component { const fields: EuiComboBoxOptionOption[] = []; this.props.indexPattern.fields + .getAll() .filter((field) => { const isMultiField = field.subType && field.subType.multi; return !field.name.startsWith('_') && !isMultiField && !field.scripted; diff --git a/src/plugins/index_pattern_management/public/components/field_editor/field_editor.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/field_editor.test.tsx index e0e053d8b606b..96d3fc549ece0 100644 --- a/src/plugins/index_pattern_management/public/components/field_editor/field_editor.test.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/field_editor.test.tsx @@ -17,16 +17,11 @@ * under the License. */ -import { - IndexPattern, - IndexPatternField, - IIndexPatternFieldList, - FieldFormatInstanceType, -} from 'src/plugins/data/public'; +import { IndexPattern, IndexPatternField, FieldFormatInstanceType } from 'src/plugins/data/public'; jest.mock('brace/mode/groovy', () => ({})); -import { FieldEditor } from './field_editor'; +import { FieldEditor, FieldEdiorProps } from './field_editor'; import { mockManagementPlugin } from '../../mocks'; import { createComponentWithContext } from '../test_utils'; @@ -71,15 +66,19 @@ jest.mock('./components/field_format_editor', () => ({ FieldFormatEditor: 'field-format-editor', })); -const fields: IndexPatternField[] = [ +const fieldList = [ { name: 'foobar', } as IndexPatternField, ]; +const fields = { + getAll: () => fieldList, +}; + // @ts-ignore fields.getByName = (name: string) => { - return fields.find((field) => field.name === name); + return fields.getAll().find((field) => field.name === name); }; class Format { @@ -112,16 +111,17 @@ describe('FieldEditor', () => { beforeEach(() => { indexPattern = ({ - fields: fields as IIndexPatternFieldList, + fields, + getFormatterForField: () => ({ params: () => ({}) }), } as unknown) as IndexPattern; }); it('should render create new scripted field correctly', async () => { - const component = createComponentWithContext( + const component = createComponentWithContext( FieldEditor, { indexPattern, - field: (field as unknown) as IndexPatternField, + spec: (field as unknown) as IndexPatternField, services: { redirectAway: () => {} }, }, mockContext @@ -138,7 +138,7 @@ describe('FieldEditor', () => { name: 'test', script: 'doc.test.value', }; - indexPattern.fields.push(testField as IndexPatternField); + fieldList.push(testField as IndexPatternField); indexPattern.fields.getByName = (name) => { const flds = { [testField.name]: testField, @@ -146,11 +146,11 @@ describe('FieldEditor', () => { return flds[name] as IndexPatternField; }; - const component = createComponentWithContext( + const component = createComponentWithContext( FieldEditor, { indexPattern, - field: (testField as unknown) as IndexPatternField, + spec: (testField as unknown) as IndexPatternField, services: { redirectAway: () => {} }, }, mockContext @@ -168,7 +168,7 @@ describe('FieldEditor', () => { script: 'doc.test.value', lang: 'testlang', }; - indexPattern.fields.push((testField as unknown) as IndexPatternField); + fieldList.push((testField as unknown) as IndexPatternField); indexPattern.fields.getByName = (name) => { const flds = { [testField.name]: testField, @@ -176,11 +176,11 @@ describe('FieldEditor', () => { return flds[name] as IndexPatternField; }; - const component = createComponentWithContext( + const component = createComponentWithContext( FieldEditor, { indexPattern, - field: (testField as unknown) as IndexPatternField, + spec: (testField as unknown) as IndexPatternField, services: { redirectAway: () => {} }, }, mockContext @@ -193,11 +193,11 @@ describe('FieldEditor', () => { it('should show conflict field warning', async () => { const testField = { ...field }; - const component = createComponentWithContext( + const component = createComponentWithContext( FieldEditor, { indexPattern, - field: (testField as unknown) as IndexPatternField, + spec: (testField as unknown) as IndexPatternField, services: { redirectAway: () => {} }, }, mockContext @@ -218,11 +218,11 @@ describe('FieldEditor', () => { text: ['index_name_3'], }, }; - const component = createComponentWithContext( + const component = createComponentWithContext( FieldEditor, { indexPattern, - field: (testField as unknown) as IndexPatternField, + spec: (testField as unknown) as IndexPatternField, services: { redirectAway: () => {} }, }, mockContext diff --git a/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx b/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx index 99ef83604239a..6a3f632a9582e 100644 --- a/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx @@ -76,7 +76,7 @@ import { executeScript, isScriptValid } from './lib'; import 'brace/mode/groovy'; const getFieldTypeFormatsList = ( - field: IFieldType, + field: IndexPatternField['spec'], defaultFieldFormat: FieldFormatInstanceType, fieldFormats: DataPublicPluginStart['fieldFormats'] ) => { @@ -108,10 +108,6 @@ interface InitialFieldTypeFormat extends FieldTypeFormat { defaultFieldFormat: FieldFormatInstanceType; } -interface FieldClone extends IndexPatternField { - format: any; -} - export interface FieldEditorState { isReady: boolean; isCreating: boolean; @@ -120,7 +116,6 @@ export interface FieldEditorState { fieldTypes: string[]; fieldTypeFormats: FieldTypeFormat[]; existingFieldNames: string[]; - field: FieldClone; fieldFormatId?: string; fieldFormatParams: { [key: string]: unknown }; showScriptingHelp: boolean; @@ -129,11 +124,13 @@ export interface FieldEditorState { hasScriptError: boolean; isSaving: boolean; errors?: string[]; + format: any; + spec: IndexPatternField['spec']; } export interface FieldEdiorProps { indexPattern: IndexPattern; - field: IndexPatternField; + spec: IndexPatternField['spec']; services: { redirectAway: () => void; }; @@ -149,7 +146,7 @@ export class FieldEditor extends PureComponent f.name), - field: { ...field, format: field.format }, + existingFieldNames: indexPattern.fields.getAll().map((f: IFieldType) => f.name), fieldFormatId: undefined, fieldFormatParams: {}, showScriptingHelp: false, @@ -167,6 +163,8 @@ export class FieldEditor extends PureComponent f.name === field.name), - isDeprecatedLang: this.deprecatedLangs.includes(field.lang || ''), + isCreating: !indexPattern.fields.getByName(spec.name), + isDeprecatedLang: this.deprecatedLangs.includes(spec.lang || ''), errors: [], scriptingLangs, fieldTypes, fieldTypeFormats: getFieldTypeFormatsList( - field, + spec, DefaultFieldFormat as FieldFormatInstanceType, data.fieldFormats ), - fieldFormatId: get(indexPattern, ['fieldFormatMap', field.name, 'type', 'id']), - fieldFormatParams: field.format.params(), + fieldFormatId: get(indexPattern, ['fieldFormatMap', spec.name, 'type', 'id']), + fieldFormatParams: format.params(), }); } onFieldChange = (fieldName: string, value: string | number) => { - const { field } = this.state; - (field as any)[fieldName] = value; + const { spec } = this.state; + (spec as any)[fieldName] = value; this.forceUpdate(); }; onTypeChange = (type: KBN_FIELD_TYPES) => { const { uiSettings, data } = this.context.services; - const { field } = this.state; + const { spec, format } = this.state; const DefaultFieldFormat = data.fieldFormats.getDefaultType(type) as FieldFormatInstanceType; - field.type = type; + spec.type = type; - field.format = new DefaultFieldFormat(null, (key) => uiSettings.get(key)); + spec.format = new DefaultFieldFormat(null, (key) => uiSettings.get(key)); this.setState({ - fieldTypeFormats: getFieldTypeFormatsList(field, DefaultFieldFormat, data.fieldFormats), + fieldTypeFormats: getFieldTypeFormatsList(spec, DefaultFieldFormat, data.fieldFormats), fieldFormatId: DefaultFieldFormat.id, - fieldFormatParams: field.format.params(), + fieldFormatParams: format.params(), }); }; onLangChange = (lang: string) => { - const { field } = this.state; + const { spec } = this.state; const fieldTypes = get(FIELD_TYPES_BY_LANG, lang, DEFAULT_FIELD_TYPES); - field.lang = lang; - field.type = fieldTypes.includes(field.type) ? field.type : fieldTypes[0]; + spec.lang = lang; + spec.type = fieldTypes.includes(spec.type) ? spec.type : fieldTypes[0]; this.setState({ fieldTypes, @@ -244,18 +246,20 @@ export class FieldEditor extends PureComponent { - const { field, fieldTypeFormats } = this.state; + const { spec, fieldTypeFormats } = this.state; const { uiSettings, data } = this.context.services; const FieldFormat = data.fieldFormats.getType( formatId || (fieldTypeFormats[0] as InitialFieldTypeFormat).defaultFieldFormat.id ) as FieldFormatInstanceType; - field.format = new FieldFormat(params, (key) => uiSettings.get(key)); + const newFormat = new FieldFormat(params, (key) => uiSettings.get(key)); + spec.format = newFormat; this.setState({ fieldFormatId: FieldFormat.id, - fieldFormatParams: field.format.params(), + fieldFormatParams: newFormat.params(), + format: newFormat, }); }; @@ -271,13 +275,13 @@ export class FieldEditor extends PureComponent ), - fieldName: {field.name}, + fieldName: {spec.name}, }} /> @@ -316,7 +320,7 @@ export class FieldEditor extends PureComponent {field.lang}, + language: {spec.lang}, painlessLink: ( { return { value: lang, text: lang }; })} @@ -388,15 +392,15 @@ export class FieldEditor extends PureComponent { return { value: type, text: type }; })} @@ -414,8 +418,8 @@ export class FieldEditor extends PureComponent ({ + const items = Object.entries(spec.conflictDescriptions).map(([type, indices]) => ({ type, indices: Array.isArray(indices) ? indices.join(', ') : 'Index names unavailable', })); @@ -466,7 +470,7 @@ export class FieldEditor extends PureComponent { - return { value: format.id || '', text: format.title }; + options={fieldTypeFormats.map((fmt) => { + return { value: fmt.id || '', text: fmt.title }; })} data-test-subj="editorSelectedFormatId" onChange={(e) => { @@ -507,8 +511,8 @@ export class FieldEditor extends PureComponent {fieldFormatId ? ( { this.onFieldChange('count', e.target.value ? Number(e.target.value) : ''); @@ -550,8 +554,8 @@ export class FieldEditor extends PureComponent ); - return field.scripted ? ( + return spec.scripted ? ( { - const { field } = this.state; + const { spec } = this.state; return this.state.showDeleteModal ? ( { @@ -674,7 +678,7 @@ export class FieldEditor extends PureComponent - {!isCreating && field.scripted ? ( + {!isCreating && spec.scripted ? ( @@ -729,9 +733,9 @@ export class FieldEditor extends PureComponent { - const { scriptingLangs, field, showScriptingHelp } = this.state; + const { scriptingLangs, spec, showScriptingHelp } = this.state; - if (!field.scripted) { + if (!spec.scripted) { return; } @@ -743,9 +747,9 @@ export class FieldEditor extends PureComponent @@ -755,14 +759,14 @@ export class FieldEditor extends PureComponent { const { redirectAway } = this.props.services; const { indexPattern } = this.props; - const { field } = this.state; - const remove = indexPattern.removeScriptedField(field); + const { spec } = this.state; + const remove = indexPattern.removeScriptedField(spec.name); if (remove) { remove.then(() => { const message = i18n.translate('indexPatternManagement.deleteField.deletedHeader', { defaultMessage: "Deleted '{fieldName}'", - values: { fieldName: field.name }, + values: { fieldName: spec.name }, }); this.context.services.notifications.toasts.addSuccess(message); redirectAway(); @@ -773,7 +777,7 @@ export class FieldEditor extends PureComponent { - const field = this.state.field; + const field = this.state.spec; const { indexPattern } = this.props; const { fieldFormatId } = this.state; @@ -800,12 +804,12 @@ export class FieldEditor extends PureComponent f.name === field.name); + const fieldExists = !!indexPattern.fields.getByName(field.name); - let oldField: IFieldType | undefined; + let oldField: IndexPatternField['spec']; - if (index > -1) { - oldField = indexPattern.fields.getByName(field.name); + if (fieldExists) { + oldField = indexPattern.fields.getByName(field.name)!.spec; indexPattern.fields.update(field); } else { indexPattern.fields.add(field); @@ -837,14 +841,14 @@ export class FieldEditor extends PureComponent @@ -868,7 +872,7 @@ export class FieldEditor extends PureComponent )} diff --git a/src/plugins/index_pattern_management/public/components/test_utils.tsx b/src/plugins/index_pattern_management/public/components/test_utils.tsx index 938547cca04ab..6aa71785d779c 100644 --- a/src/plugins/index_pattern_management/public/components/test_utils.tsx +++ b/src/plugins/index_pattern_management/public/components/test_utils.tsx @@ -23,9 +23,9 @@ import { shallow } from 'enzyme'; // since the 'shallow' from 'enzyme' doesn't support context API for React 16 and above (https://github.com/facebook/react/pull/14329) // we use this workaround where define legacy contextTypes for react class component -export function createComponentWithContext( +export function createComponentWithContext>( MyComponent: React.ComponentClass, - props: Record, + props: Props, mockedContext: Record ) { MyComponent.contextTypes = { diff --git a/src/plugins/input_control_vis/public/control/list_control_factory.ts b/src/plugins/input_control_vis/public/control/list_control_factory.ts index 65a3e37a93edf..acbbf08c7d004 100644 --- a/src/plugins/input_control_vis/public/control/list_control_factory.ts +++ b/src/plugins/input_control_vis/public/control/list_control_factory.ts @@ -216,7 +216,7 @@ export async function listControlFactory( // dynamic options are only allowed on String fields but the setting defaults to true so it could // be enabled for non-string fields (since UI input is hidden for non-string fields). // If field is not string, then disable dynamic options. - const field = indexPattern.fields.find(({ name }) => name === controlParams.fieldName); + const field = indexPattern.fields.getAll().find(({ name }) => name === controlParams.fieldName); if (field && field.type !== 'string') { controlParams.options.dynamicOptions = false; } diff --git a/src/plugins/input_control_vis/public/test_utils/get_deps_mock.tsx b/src/plugins/input_control_vis/public/test_utils/get_deps_mock.tsx index feedcab1850eb..f72bc96f9e7c1 100644 --- a/src/plugins/input_control_vis/public/test_utils/get_deps_mock.tsx +++ b/src/plugins/input_control_vis/public/test_utils/get_deps_mock.tsx @@ -26,6 +26,7 @@ fields.push({ name: 'myField' } as any); fields.getByName = (name: any) => { return fields.find(({ name: n }: { name: string }) => n === name); }; +fields.getAll = () => [...fields]; export const getDepsMock = ({ searchSource = { diff --git a/src/plugins/kibana_utils/docs/state_sync/README.md b/src/plugins/kibana_utils/docs/state_sync/README.md index acfe6dcf76fe9..c84bf7f236330 100644 --- a/src/plugins/kibana_utils/docs/state_sync/README.md +++ b/src/plugins/kibana_utils/docs/state_sync/README.md @@ -58,3 +58,4 @@ To run them, start kibana with `--run-examples` flag. - [On-the-fly state migrations](./on_fly_state_migrations.md). - [syncStates helper](./sync_states.md). - [Helpers for Data plugin (syncing TimeRange, RefreshInterval and Filters)](./data_plugin_helpers.md). +- [Error handling](./error_handling.md) diff --git a/src/plugins/kibana_utils/docs/state_sync/error_handling.md b/src/plugins/kibana_utils/docs/state_sync/error_handling.md new file mode 100644 index 0000000000000..b12e1040af260 --- /dev/null +++ b/src/plugins/kibana_utils/docs/state_sync/error_handling.md @@ -0,0 +1,6 @@ +# Error handling + +State syncing util doesn't have specific api for handling errors. +It expects that errors are handled on storage level. + +see [KbnUrlStateStorage](./storages/kbn_url_storage.md#) error handling section for details. diff --git a/src/plugins/kibana_utils/docs/state_sync/storages/kbn_url_storage.md b/src/plugins/kibana_utils/docs/state_sync/storages/kbn_url_storage.md index 3a31f5a326edb..ec27895eed666 100644 --- a/src/plugins/kibana_utils/docs/state_sync/storages/kbn_url_storage.md +++ b/src/plugins/kibana_utils/docs/state_sync/storages/kbn_url_storage.md @@ -65,7 +65,7 @@ To prevent bugs caused by missing history updates, make sure your app uses one i For example, if you use `react-router`: ```tsx -const App = props => { +const App = (props) => { useEffect(() => { const stateStorage = createKbnUrlStateStorage({ useHash: props.uiSettings.get('state:storeInSessionStorage'), @@ -160,3 +160,58 @@ const { start, stop } = syncStates([ ; ``` + +### Error handling + +Errors could occur both during `kbnUrlStateStorage.get()` and `kbnUrlStateStorage.set()` + +#### Handling kbnUrlStateStorage.get() errors + +Possible error scenarios during `kbnUrlStateStorage.get()`: + +1. Rison in URL is malformed. Parsing exception. +2. useHash is enabled and current hash is missing in `sessionStorage` + +In all the cases error is handled internally and `kbnUrlStateStorage.get()` returns `null`, just like if there is no state in the URL anymore + +You can pass callback to get notified about errors. Use it, for example, for notifying users + +```ts +const kbnUrlStateStorage = createKbnUrlStateStorage({ + history, + onGetError: (error) => { + alert(error.message); + }, +}); +``` + +#### Handling kbnUrlStateStorage.set() errors + +Possible errors during `kbnUrlStateStorage.set()`: + +1. `useHash` is enabled and can't store state in `sessionStorage` (overflow or no access) + +In all the cases error is handled internally and URL update is skipped + +You can pass callback to get notified about errors. Use it, for example, for notifying users: + +```ts +const kbnUrlStateStorage = createKbnUrlStateStorage({ + history, + onSetError: (error) => { + alert(error.message); + }, +}); +``` + +#### Helper to integrate with core.notifications.toasts + +The most common scenario is to notify users about issues with state syncing using toast service from core +There is a convenient helper for this: + +```ts +const kbnUrlStateStorage = createKbnUrlStateStorage({ + history, + ...withNotifyOnErrors(core.notifications.toasts), +}); +``` diff --git a/src/plugins/kibana_utils/public/index.ts b/src/plugins/kibana_utils/public/index.ts index e2d6ae647abb1..d1c9eec0e9906 100644 --- a/src/plugins/kibana_utils/public/index.ts +++ b/src/plugins/kibana_utils/public/index.ts @@ -57,6 +57,7 @@ export { getStateFromKbnUrl, getStatesFromKbnUrl, setStateToKbnUrl, + withNotifyOnErrors, } from './state_management/url'; export { syncState, diff --git a/src/plugins/kibana_utils/public/state_management/url/errors.ts b/src/plugins/kibana_utils/public/state_management/url/errors.ts new file mode 100644 index 0000000000000..b8b6523e8070c --- /dev/null +++ b/src/plugins/kibana_utils/public/state_management/url/errors.ts @@ -0,0 +1,62 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { NotificationsStart } from 'kibana/public'; + +export const restoreUrlErrorTitle = i18n.translate( + 'kibana_utils.stateManagement.url.restoreUrlErrorTitle', + { + defaultMessage: `Error restoring state from URL`, + } +); + +export const saveStateInUrlErrorTitle = i18n.translate( + 'kibana_utils.stateManagement.url.saveStateInUrlErrorTitle', + { + defaultMessage: `Error saving state in URL`, + } +); + +/** + * Helper for configuring {@link IKbnUrlStateStorage} to notify about inner errors + * + * @example + * ```ts + * const kbnUrlStateStorage = createKbnUrlStateStorage({ + * history, + * ...withNotifyOnErrors(core.notifications.toast)) + * } + * ``` + * @param toast - toastApi from core.notifications.toasts + */ +export const withNotifyOnErrors = (toasts: NotificationsStart['toasts']) => { + return { + onGetError: (error: Error) => { + toasts.addError(error, { + title: restoreUrlErrorTitle, + }); + }, + onSetError: (error: Error) => { + toasts.addError(error, { + title: saveStateInUrlErrorTitle, + }); + }, + }; +}; diff --git a/src/plugins/kibana_utils/public/state_management/url/index.ts b/src/plugins/kibana_utils/public/state_management/url/index.ts index e28d183c6560a..66fecd723e3ba 100644 --- a/src/plugins/kibana_utils/public/state_management/url/index.ts +++ b/src/plugins/kibana_utils/public/state_management/url/index.ts @@ -27,3 +27,4 @@ export { } from './kbn_url_storage'; export { createKbnUrlTracker } from './kbn_url_tracker'; export { createUrlTracker } from './url_tracker'; +export { withNotifyOnErrors, saveStateInUrlErrorTitle, restoreUrlErrorTitle } from './errors'; diff --git a/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts b/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts index d9149095a2fa2..fefd5f668c6b3 100644 --- a/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts +++ b/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts @@ -103,7 +103,7 @@ export function setStateToKbnUrl( export interface IKbnUrlControls { /** * Listen for url changes - * @param cb - get's called when url has been changed + * @param cb - called when url has been changed */ listen: (cb: () => void) => () => void; @@ -142,12 +142,12 @@ export interface IKbnUrlControls { */ cancel: () => void; } -export type UrlUpdaterFnType = (currentUrl: string) => string; +export type UrlUpdaterFnType = (currentUrl: string) => string | undefined; export const createKbnUrlControls = ( history: History = createBrowserHistory() ): IKbnUrlControls => { - const updateQueue: Array<(currentUrl: string) => string> = []; + const updateQueue: UrlUpdaterFnType[] = []; // if we should replace or push with next async update, // if any call in a queue asked to push, then we should push @@ -188,7 +188,7 @@ export const createKbnUrlControls = ( function getPendingUrl() { if (updateQueue.length === 0) return undefined; const resultUrl = updateQueue.reduce( - (url, nextUpdate) => nextUpdate(url), + (url, nextUpdate) => nextUpdate(url) ?? url, getCurrentUrl(history) ); @@ -201,7 +201,7 @@ export const createKbnUrlControls = ( cb(); }), update: (newUrl: string, replace = false) => updateUrl(newUrl, replace), - updateAsync: (updater: (currentUrl: string) => string, replace = false) => { + updateAsync: (updater: UrlUpdaterFnType, replace = false) => { updateQueue.push(updater); if (shouldReplace) { shouldReplace = replace; diff --git a/src/plugins/kibana_utils/public/state_sync/public.api.md b/src/plugins/kibana_utils/public/state_sync/public.api.md index ae8c0e8e401b8..a4dfea82cdb59 100644 --- a/src/plugins/kibana_utils/public/state_sync/public.api.md +++ b/src/plugins/kibana_utils/public/state_sync/public.api.md @@ -8,9 +8,11 @@ import { History } from 'history'; import { Observable } from 'rxjs'; // @public -export const createKbnUrlStateStorage: ({ useHash, history }?: { +export const createKbnUrlStateStorage: ({ useHash, history, onGetError, onSetError, }?: { useHash: boolean; history?: History | undefined; + onGetError?: ((error: Error) => void) | undefined; + onSetError?: ((error: Error) => void) | undefined; }) => IKbnUrlStateStorage; // Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "Storage" diff --git a/src/plugins/kibana_utils/public/state_sync/state_sync_state_storage/create_kbn_url_state_storage.test.ts b/src/plugins/kibana_utils/public/state_sync/state_sync_state_storage/create_kbn_url_state_storage.test.ts index cc708d14ea8b5..e222af91d7729 100644 --- a/src/plugins/kibana_utils/public/state_sync/state_sync_state_storage/create_kbn_url_state_storage.test.ts +++ b/src/plugins/kibana_utils/public/state_sync/state_sync_state_storage/create_kbn_url_state_storage.test.ts @@ -16,12 +16,14 @@ * specific language governing permissions and limitations * under the License. */ -import '../../storage/hashed_item_store/mock'; +import { mockStorage } from '../../storage/hashed_item_store/mock'; import { createKbnUrlStateStorage, IKbnUrlStateStorage } from './create_kbn_url_state_storage'; import { History, createBrowserHistory } from 'history'; import { takeUntil, toArray } from 'rxjs/operators'; import { Subject } from 'rxjs'; import { ScopedHistory } from '../../../../../core/public'; +import { withNotifyOnErrors } from '../../state_management/url'; +import { coreMock } from '../../../../../core/public/mocks'; describe('KbnUrlStateStorage', () => { describe('useHash: false', () => { @@ -93,6 +95,37 @@ describe('KbnUrlStateStorage', () => { expect(await result).toEqual([{ test: 'test', ok: 1 }, { test: 'test', ok: 2 }, null]); }); + + it("shouldn't throw in case of parsing error", async () => { + const key = '_s'; + history.replace(`/#?${key}=(ok:2,test:`); // malformed rison + expect(() => urlStateStorage.get(key)).not.toThrow(); + expect(urlStateStorage.get(key)).toBeNull(); + }); + + it('should notify about errors', () => { + const cb = jest.fn(); + urlStateStorage = createKbnUrlStateStorage({ useHash: false, history, onGetError: cb }); + const key = '_s'; + history.replace(`/#?${key}=(ok:2,test:`); // malformed rison + expect(() => urlStateStorage.get(key)).not.toThrow(); + expect(cb).toBeCalledWith(expect.any(Error)); + }); + + describe('withNotifyOnErrors integration', () => { + test('toast is shown', () => { + const toasts = coreMock.createStart().notifications.toasts; + urlStateStorage = createKbnUrlStateStorage({ + useHash: true, + history, + ...withNotifyOnErrors(toasts), + }); + const key = '_s'; + history.replace(`/#?${key}=(ok:2,test:`); // malformed rison + expect(() => urlStateStorage.get(key)).not.toThrow(); + expect(toasts.addError).toBeCalled(); + }); + }); }); describe('useHash: true', () => { @@ -128,6 +161,44 @@ describe('KbnUrlStateStorage', () => { expect(await result).toEqual([{ test: 'test', ok: 1 }, { test: 'test', ok: 2 }, null]); }); + + describe('hashStorage overflow exception', () => { + let oldLimit: number; + beforeAll(() => { + oldLimit = mockStorage.getStubbedSizeLimit(); + mockStorage.clear(); + mockStorage.setStubbedSizeLimit(0); + }); + afterAll(() => { + mockStorage.setStubbedSizeLimit(oldLimit); + }); + + it("shouldn't throw in case of error", async () => { + expect(() => urlStateStorage.set('_s', { test: 'test' })).not.toThrow(); + await expect(urlStateStorage.set('_s', { test: 'test' })).resolves; // not rejects + expect(getCurrentUrl()).toBe('/'); // url wasn't updated with hash + }); + + it('should notify about errors', async () => { + const cb = jest.fn(); + urlStateStorage = createKbnUrlStateStorage({ useHash: true, history, onSetError: cb }); + await expect(urlStateStorage.set('_s', { test: 'test' })).resolves; // not rejects + expect(cb).toBeCalledWith(expect.any(Error)); + }); + + describe('withNotifyOnErrors integration', () => { + test('toast is shown', async () => { + const toasts = coreMock.createStart().notifications.toasts; + urlStateStorage = createKbnUrlStateStorage({ + useHash: true, + history, + ...withNotifyOnErrors(toasts), + }); + await expect(urlStateStorage.set('_s', { test: 'test' })).resolves; // not rejects + expect(toasts.addError).toBeCalled(); + }); + }); + }); }); describe('ScopedHistory integration', () => { diff --git a/src/plugins/kibana_utils/public/state_sync/state_sync_state_storage/create_kbn_url_state_storage.ts b/src/plugins/kibana_utils/public/state_sync/state_sync_state_storage/create_kbn_url_state_storage.ts index 0c74e1eb9f421..460720b98e30f 100644 --- a/src/plugins/kibana_utils/public/state_sync/state_sync_state_storage/create_kbn_url_state_storage.ts +++ b/src/plugins/kibana_utils/public/state_sync/state_sync_state_storage/create_kbn_url_state_storage.ts @@ -17,8 +17,8 @@ * under the License. */ -import { Observable } from 'rxjs'; -import { map, share } from 'rxjs/operators'; +import { Observable, of } from 'rxjs'; +import { catchError, map, share } from 'rxjs/operators'; import { History } from 'history'; import { IStateStorage } from './types'; import { @@ -68,7 +68,19 @@ export interface IKbnUrlStateStorage extends IStateStorage { * @public */ export const createKbnUrlStateStorage = ( - { useHash = false, history }: { useHash: boolean; history?: History } = { useHash: false } + { + useHash = false, + history, + onGetError, + onSetError, + }: { + useHash: boolean; + history?: History; + onGetError?: (error: Error) => void; + onSetError?: (error: Error) => void; + } = { + useHash: false, + } ): IKbnUrlStateStorage => { const url = createKbnUrlControls(history); return { @@ -78,15 +90,23 @@ export const createKbnUrlStateStorage = ( { replace = false }: { replace: boolean } = { replace: false } ) => { // syncState() utils doesn't wait for this promise - return url.updateAsync( - (currentUrl) => setStateToKbnUrl(key, state, { useHash }, currentUrl), - replace - ); + return url.updateAsync((currentUrl) => { + try { + return setStateToKbnUrl(key, state, { useHash }, currentUrl); + } catch (error) { + if (onSetError) onSetError(error); + } + }, replace); }, get: (key) => { // if there is a pending url update, then state will be extracted from that pending url, // otherwise current url will be used to retrieve state from - return getStateFromKbnUrl(key, url.getPendingUrl()); + try { + return getStateFromKbnUrl(key, url.getPendingUrl()); + } catch (e) { + if (onGetError) onGetError(e); + return null; + } }, change$: (key: string) => new Observable((observer) => { @@ -99,6 +119,10 @@ export const createKbnUrlStateStorage = ( }; }).pipe( map(() => getStateFromKbnUrl(key)), + catchError((error) => { + if (onGetError) onGetError(error); + return of(null); + }), share() ), flush: ({ replace = false }: { replace?: boolean } = {}) => { diff --git a/src/plugins/kibana_utils/public/storage/__tests__/storage.js b/src/plugins/kibana_utils/public/storage/__tests__/storage.js deleted file mode 100644 index 073ed275b9aac..0000000000000 --- a/src/plugins/kibana_utils/public/storage/__tests__/storage.js +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import sinon from 'sinon'; -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; -import '..'; - -let storage; -let $window; -const payload = { first: 'john', last: 'smith' }; - -function init() { - ngMock.module('kibana/storage', function ($provide) { - // mock $window.localStorage for storage - $provide.value('$window', { - localStorage: { - getItem: sinon.stub(), - setItem: sinon.spy(), - removeItem: sinon.spy(), - clear: sinon.spy(), - }, - }); - }); - - ngMock.inject(function ($injector) { - storage = $injector.get('localStorage'); - $window = $injector.get('$window'); - }); -} - -describe('StorageService', function () { - beforeEach(function () { - init(); - }); - - describe('expected API', function () { - it('should have expected methods', function () { - expect(storage.get).to.be.a('function'); - expect(storage.set).to.be.a('function'); - expect(storage.remove).to.be.a('function'); - expect(storage.clear).to.be.a('function'); - }); - }); - - describe('call behavior', function () { - it('should call getItem on the store', function () { - storage.get('name'); - - expect($window.localStorage.getItem.callCount).to.equal(1); - }); - - it('should call setItem on the store', function () { - storage.set('name', 'john smith'); - - expect($window.localStorage.setItem.callCount).to.equal(1); - }); - - it('should call removeItem on the store', function () { - storage.remove('name'); - - expect($window.localStorage.removeItem.callCount).to.equal(1); - }); - - it('should call clear on the store', function () { - storage.clear(); - - expect($window.localStorage.clear.callCount).to.equal(1); - }); - }); - - describe('json data', function () { - it('should parse JSON when reading from the store', function () { - const getItem = $window.localStorage.getItem; - getItem.returns(JSON.stringify(payload)); - - const data = storage.get('name'); - expect(data).to.eql(payload); - }); - - it('should write JSON string to the store', function () { - const setItem = $window.localStorage.setItem; - const key = 'name'; - const value = payload; - - storage.set(key, value); - - const call = setItem.getCall(0); - expect(call.args[0]).to.equal(key); - expect(call.args[1]).to.equal(JSON.stringify(value)); - }); - }); - - describe('expected responses', function () { - it('should return null when not exists', function () { - const data = storage.get('notexists'); - expect(data).to.equal(null); - }); - - it('should return null when invalid JSON', function () { - const getItem = $window.localStorage.getItem; - getItem.returns('not: json'); - - const data = storage.get('name'); - expect(data).to.equal(null); - }); - }); -}); diff --git a/src/plugins/kibana_utils/public/storage/storage.test.ts b/src/plugins/kibana_utils/public/storage/storage.test.ts new file mode 100644 index 0000000000000..8c5d3d11a21fe --- /dev/null +++ b/src/plugins/kibana_utils/public/storage/storage.test.ts @@ -0,0 +1,109 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Storage } from './storage'; +import { IStorage, IStorageWrapper } from './types'; + +const payload = { first: 'john', last: 'smith' }; +const createMockStore = (): MockedKeys => { + let store: Record = {}; + return { + getItem: jest.fn().mockImplementation((key) => store[key]), + setItem: jest.fn().mockImplementation((key, value) => (store[key] = value)), + removeItem: jest.fn().mockImplementation((key: string) => delete store[key]), + clear: jest.fn().mockImplementation(() => (store = {})), + }; +}; + +describe('StorageService', () => { + let storage: IStorageWrapper; + let mockStore: MockedKeys; + + beforeEach(() => { + jest.resetAllMocks(); + mockStore = createMockStore(); + storage = new Storage(mockStore); + }); + + describe('expected API', () => { + test('should have expected methods', () => { + expect(typeof storage.get).toBe('function'); + expect(typeof storage.set).toBe('function'); + expect(typeof storage.remove).toBe('function'); + expect(typeof storage.clear).toBe('function'); + }); + }); + + describe('call behavior', () => { + test('should call getItem on the store', () => { + storage.get('name'); + + expect(mockStore.getItem).toHaveBeenCalledTimes(1); + }); + + test('should call setItem on the store', () => { + storage.set('name', 'john smith'); + + expect(mockStore.setItem).toHaveBeenCalledTimes(1); + }); + + test('should call removeItem on the store', () => { + storage.remove('name'); + + expect(mockStore.removeItem).toHaveBeenCalledTimes(1); + }); + + test('should call clear on the store', () => { + storage.clear(); + + expect(mockStore.clear).toHaveBeenCalledTimes(1); + }); + }); + + describe('json data', () => { + test('should parse JSON when reading from the store', () => { + mockStore.getItem = jest.fn().mockImplementationOnce(() => JSON.stringify(payload)); + + const data = storage.get('name'); + expect(data).toEqual(payload); + }); + + test('should write JSON string to the store', () => { + const key = 'name'; + const value = payload; + + storage.set(key, value); + expect(mockStore.setItem).toHaveBeenCalledWith(key, JSON.stringify(value)); + }); + }); + + describe('expected responses', () => { + test('should return null when not exists', () => { + const data = storage.get('notexists'); + expect(data).toBe(null); + }); + + test('should return null when invalid JSON', () => { + mockStore.getItem = jest.fn().mockImplementationOnce(() => 'not: json'); + + const data = storage.get('name'); + expect(data).toBe(null); + }); + }); +}); diff --git a/src/plugins/maps_legacy/public/__tests__/map/kibana_map.js b/src/plugins/maps_legacy/public/__tests__/map/kibana_map.js deleted file mode 100644 index ae6d3144335cf..0000000000000 --- a/src/plugins/maps_legacy/public/__tests__/map/kibana_map.js +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import { KibanaMap } from '../../map/kibana_map'; -import { KibanaMapLayer } from '../../map/kibana_map_layer'; - -describe('kibana_map tests', function () { - let domNode; - let kibanaMap; - - function createDiv(width, height) { - const div = document.createElement('div'); - div.style.top = '0'; - div.style.left = '0'; - div.style.width = width; - div.style.height = height; - div.style.position = 'fixed'; - div.style['pointer-events'] = 'none'; - return div; - } - - function setupDOM(width, height) { - domNode = createDiv(width, height); - document.body.appendChild(domNode); - } - - function teardownDOM() { - domNode.innerHTML = ''; - document.body.removeChild(domNode); - } - - describe('KibanaMap - basics', function () { - beforeEach(async function () { - setupDOM('512px', '512px'); - kibanaMap = new KibanaMap(domNode, { - minZoom: 1, - maxZoom: 10, - center: [0, 0], - zoom: 0, - }); - }); - - afterEach(function () { - kibanaMap.destroy(); - teardownDOM(); - }); - - it('should instantiate at zoom level 2', function () { - const bounds = kibanaMap.getBounds(); - expect(bounds.bottom_right.lon).to.equal(90); - expect(bounds.top_left.lon).to.equal(-90); - expect(kibanaMap.getCenter().lon).to.equal(0); - expect(kibanaMap.getCenter().lat).to.equal(0); - expect(kibanaMap.getZoomLevel()).to.equal(2); - }); - - it('should resize to fit container', function () { - kibanaMap.setZoomLevel(2); - expect(kibanaMap.getCenter().lon).to.equal(0); - expect(kibanaMap.getCenter().lat).to.equal(0); - - domNode.style.width = '1024px'; - domNode.style.height = '1024px'; - kibanaMap.resize(); - - expect(kibanaMap.getCenter().lon).to.equal(0); - expect(kibanaMap.getCenter().lat).to.equal(0); - }); - }); - - describe('getBounds', function () { - afterEach(function () { - kibanaMap.destroy(); - teardownDOM(); - }); - - describe('extended bounds', function () { - beforeEach(async function () { - setupDOM('1600px', '1024px'); - kibanaMap = new KibanaMap(domNode, { - minZoom: 1, - maxZoom: 10, - center: [0, 0], - zoom: 2, - }); - }); - - it('should get untrimmed map bounds', function () { - const bounds = kibanaMap.getBounds(); - expect(bounds.bottom_right.lon.toFixed(2)).to.equal('281.25'); - expect(bounds.top_left.lon.toFixed(2)).to.equal('-281.25'); - }); - }); - - describe('no map height (should default to size of 1px for height)', function () { - beforeEach(async function () { - setupDOM('386px', '256px'); - const noHeightNode = createDiv('386px', '0px'); - domNode.appendChild(noHeightNode); - kibanaMap = new KibanaMap(noHeightNode, { - minZoom: 1, - maxZoom: 10, - center: [0, 0], - zoom: 10, - }); - }); - - it('should calculate map dimensions based on enforcement of single pixel min-width CSS-rule', function () { - const bounds = kibanaMap.getBounds(); - expect(bounds).to.have.property('bottom_right'); - expect(round(bounds.bottom_right.lon, 2)).to.equal(0.27); - expect(round(bounds.bottom_right.lat, 2)).to.equal(0); - expect(bounds).to.have.property('top_left'); - expect(round(bounds.top_left.lon, 2)).to.equal(-0.27); - expect(round(bounds.top_left.lat, 2)).to.equal(0); - }); - - function round(num, dig) { - return Math.round(num * Math.pow(10, dig)) / Math.pow(10, dig); - } - }); - - describe('no map width (should default to size of 1px for width)', function () { - beforeEach(async function () { - setupDOM('386px', '256px'); - const noWidthNode = createDiv('0px', '256px'); - domNode.appendChild(noWidthNode); - kibanaMap = new KibanaMap(noWidthNode, { - minZoom: 1, - maxZoom: 10, - center: [0, 0], - zoom: 10, - }); - }); - - it('should calculate map dimensions based on enforcement of single pixel min-width CSS-rule', function () { - const bounds = kibanaMap.getBounds(); - expect(bounds).to.have.property('bottom_right'); - expect(Math.round(bounds.bottom_right.lon)).to.equal(0); - expect(bounds.bottom_right.lat.toFixed(2)).to.equal('-0.18'); - expect(bounds).to.have.property('top_left'); - expect(Math.round(bounds.top_left.lon)).to.equal(0); - expect(bounds.top_left.lat.toFixed(2)).to.equal('0.18'); - }); - }); - - describe('wrapping', function () { - beforeEach(async function () { - setupDOM('1600px', '1024px'); - kibanaMap = new KibanaMap(domNode, { - minZoom: 1, - maxZoom: 10, - center: [0, -800], //swing the map over two earth-rotations west - zoom: 2, - }); - }); - - it('coordinates should be corrected to center the -180,180 range', function () { - const bounds = kibanaMap.getBounds(); - expect(bounds.bottom_right.lon.toFixed(2)).to.equal('201.09'); - expect(bounds.top_left.lon.toFixed(2)).to.equal('-361.41'); - }); - }); - - describe('wrapping - zoomed in', function () { - beforeEach(async function () { - setupDOM('1600px', '1024px'); - kibanaMap = new KibanaMap(domNode, { - minZoom: 1, - maxZoom: 10, - center: [0, -800], //swing the map over two earth-rotations west - zoom: 8, - }); - }); - - it('coordinates should be corrected to fall within the -180,180 range', function () { - const bounds = kibanaMap.getBounds(); - expect(bounds.bottom_right.lon.toFixed(2)).to.equal('-75.61'); - expect(bounds.top_left.lon.toFixed(2)).to.equal('-84.40'); - }); - }); - }); - - describe('KibanaMap - attributions', function () { - beforeEach(async function () { - setupDOM('512px', '512px'); - kibanaMap = new KibanaMap(domNode, { - minZoom: 1, - maxZoom: 10, - center: [0, 0], - zoom: 0, - }); - }); - - afterEach(function () { - kibanaMap.destroy(); - teardownDOM(); - }); - - function makeMockLayer(attribution) { - const layer = new KibanaMapLayer(); - layer._attribution = attribution; - // eslint-disable-next-line no-undef - layer._leafletLayer = L.geoJson(null); - return layer; - } - - it('should update attributions correctly', function () { - kibanaMap.addLayer(makeMockLayer('foo|bar')); - expect(domNode.querySelectorAll('.leaflet-control-attribution')[0].innerHTML).to.equal( - 'foo, bar' - ); - - kibanaMap.addLayer(makeMockLayer('bar')); - expect(domNode.querySelectorAll('.leaflet-control-attribution')[0].innerHTML).to.equal( - 'foo, bar' - ); - - const layer = makeMockLayer('bar,stool'); - kibanaMap.addLayer(layer); - expect(domNode.querySelectorAll('.leaflet-control-attribution')[0].innerHTML).to.equal( - 'foo, bar, stool' - ); - - kibanaMap.removeLayer(layer); - expect(domNode.querySelectorAll('.leaflet-control-attribution')[0].innerHTML).to.equal( - 'foo, bar' - ); - }); - }); - - describe('KibanaMap - baseLayer', function () { - beforeEach(async function () { - setupDOM('512px', '512px'); - kibanaMap = new KibanaMap(domNode, { - minZoom: 1, - maxZoom: 10, - center: [0, 0], - zoom: 0, - }); - }); - - afterEach(function () { - kibanaMap.destroy(); - teardownDOM(); - }); - - it('TMS', async function () { - const options = { - url: - 'https://tiles-stage.elastic.co/v2/default/{z}/{x}/{y}.png?elastic_tile_service_tos=agree&my_app_name=kibana', - minZoom: 0, - maxZoom: 12, - attribution: '© [Elastic Maps Service](https://www.elastic.co/elastic-maps-service)', - }; - - return new Promise(function (resolve) { - kibanaMap.on('baseLayer:loaded', () => { - resolve(); - }); - kibanaMap.setBaseLayer({ - baseLayerType: 'tms', - options: options, - }); - }); - }); - - it('WMS - should handle empty settings', async function () { - const invalidOptions = { - url: undefined, - version: undefined, - layers: undefined, - format: 'image/png', - transparent: true, - attribution: undefined, - styles: '', - minZoom: 1, - maxZoom: 18, - }; - - kibanaMap.setBaseLayer({ - baseLayerType: 'wms', - options: invalidOptions, - }); - - expect(kibanaMap.getLeafletBaseLayer()).to.eql(null); - }); - - it('WMS - should clean attribution', async function () { - const options = { - url: 'https://basemap.nationalmap.gov/arcgis/services/USGSTopo/MapServer/WMSServer', - version: '1.1.0', - layers: '0', - format: 'image/png', - transparent: true, - attribution: '
foobar
', - styles: '', - minZoom: 1, - maxZoom: 18, - }; - - kibanaMap.setBaseLayer({ - baseLayerType: 'wms', - options: options, - }); - - expect(domNode.querySelectorAll('.leaflet-control-attribution')[0].innerHTML).to.equal( - '<div>foobar</div>' - ); - }); - }); -}); diff --git a/src/plugins/region_map/public/__tests__/aftercolorchange.png b/src/plugins/region_map/public/__tests__/aftercolorchange.png deleted file mode 100644 index d5a5316e2e99c..0000000000000 Binary files a/src/plugins/region_map/public/__tests__/aftercolorchange.png and /dev/null differ diff --git a/src/plugins/region_map/public/__tests__/afterdatachange.png b/src/plugins/region_map/public/__tests__/afterdatachange.png deleted file mode 100644 index ba388f18d7f35..0000000000000 Binary files a/src/plugins/region_map/public/__tests__/afterdatachange.png and /dev/null differ diff --git a/src/plugins/region_map/public/__tests__/afterdatachangeandresize.png b/src/plugins/region_map/public/__tests__/afterdatachangeandresize.png deleted file mode 100644 index 7da57511c5831..0000000000000 Binary files a/src/plugins/region_map/public/__tests__/afterdatachangeandresize.png and /dev/null differ diff --git a/src/plugins/region_map/public/__tests__/afterresize.png b/src/plugins/region_map/public/__tests__/afterresize.png deleted file mode 100644 index 7656d69bdac1f..0000000000000 Binary files a/src/plugins/region_map/public/__tests__/afterresize.png and /dev/null differ diff --git a/src/plugins/region_map/public/__tests__/changestartup.png b/src/plugins/region_map/public/__tests__/changestartup.png deleted file mode 100644 index a94affddbd941..0000000000000 Binary files a/src/plugins/region_map/public/__tests__/changestartup.png and /dev/null differ diff --git a/src/plugins/region_map/public/__tests__/initial.png b/src/plugins/region_map/public/__tests__/initial.png deleted file mode 100644 index 9ec48af9fe1e2..0000000000000 Binary files a/src/plugins/region_map/public/__tests__/initial.png and /dev/null differ diff --git a/src/plugins/region_map/public/__tests__/region_map_visualization.js b/src/plugins/region_map/public/__tests__/region_map_visualization.js deleted file mode 100644 index 648193e8e2490..0000000000000 --- a/src/plugins/region_map/public/__tests__/region_map_visualization.js +++ /dev/null @@ -1,417 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; -import _ from 'lodash'; - -import ChoroplethLayer from '../choropleth_layer'; -import { ImageComparator } from 'test_utils/image_comparator'; -import worldJson from './world.json'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import EMS_CATALOGUE from '../../../maps_legacy/public/__tests__/map/ems_mocks/sample_manifest.json'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import EMS_FILES from '../../../maps_legacy/public/__tests__/map/ems_mocks/sample_files.json'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import EMS_TILES from '../../../maps_legacy/public/__tests__/map/ems_mocks/sample_tiles.json'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import EMS_STYLE_ROAD_MAP_BRIGHT from '../../../maps_legacy/public/__tests__/map/ems_mocks/sample_style_bright'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import EMS_STYLE_ROAD_MAP_DESATURATED from '../../../maps_legacy/public/__tests__/map/ems_mocks/sample_style_desaturated'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import EMS_STYLE_DARK_MAP from '../../../maps_legacy/public/__tests__/map/ems_mocks/sample_style_dark'; - -import initialPng from './initial.png'; -import toiso3Png from './toiso3.png'; -import afterresizePng from './afterresize.png'; -import afterdatachangePng from './afterdatachange.png'; -import afterdatachangeandresizePng from './afterdatachangeandresize.png'; -import aftercolorchangePng from './aftercolorchange.png'; -import changestartupPng from './changestartup.png'; - -import { createRegionMapVisualization } from '../region_map_visualization'; -import { createRegionMapTypeDefinition } from '../region_map_type'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { ExprVis } from '../../../visualizations/public/expressions/vis'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { BaseVisType } from '../../../visualizations/public/vis_types/base_vis_type'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { ServiceSettings } from '../../../maps_legacy/public/map/service_settings'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { BaseMapsVisualizationProvider } from '../../../maps_legacy/public/map/base_maps_visualization'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { KibanaMap } from '../../../maps_legacy/public/map/kibana_map'; - -const THRESHOLD = 0.45; -const PIXEL_DIFF = 96; - -describe('RegionMapsVisualizationTests', function () { - let domNode; - let RegionMapsVisualization; - let vis; - let regionMapVisType; - let dependencies; - - let imageComparator; - - const _makeJsonAjaxCallOld = ChoroplethLayer.prototype._makeJsonAjaxCall; - - const dummyTableGroup = { - columns: [ - { - id: 'col-0', - aggConfig: { - id: '2', - enabled: true, - type: 'terms', - schema: 'segment', - params: { field: 'geo.dest', size: 5, order: 'desc', orderBy: '1' }, - }, - title: 'geo.dest: Descending', - }, - { - id: 'col-1', - aggConfig: { id: '1', enabled: true, type: 'count', schema: 'metric', params: {} }, - title: 'Count', - }, - ], - rows: [ - { 'col-0': 'CN', 'col-1': 26 }, - { 'col-0': 'IN', 'col-1': 17 }, - { 'col-0': 'US', 'col-1': 6 }, - { 'col-0': 'DE', 'col-1': 4 }, - { 'col-0': 'BR', 'col-1': 3 }, - ], - }; - - beforeEach(ngMock.module('kibana')); - - let getManifestStub; - beforeEach( - ngMock.inject(() => { - const mapConfig = { - emsFileApiUrl: '', - emsTileApiUrl: '', - emsLandingPageUrl: '', - }; - const tilemapsConfig = { - options: { - attribution: '123', - }, - }; - const serviceSettings = new ServiceSettings(mapConfig, tilemapsConfig); - const regionmapsConfig = { - includeElasticMapsService: true, - layers: [], - }; - const coreSetupMock = { - notifications: { - toasts: {}, - }, - uiSettings: { - get: () => {}, - }, - injectedMetadata: { - getInjectedVar: () => {}, - }, - }; - const BaseMapsVisualization = new BaseMapsVisualizationProvider( - (...args) => new KibanaMap(...args), - serviceSettings - ); - - dependencies = { - serviceSettings, - regionmapsConfig, - uiSettings: coreSetupMock.uiSettings, - BaseMapsVisualization, - }; - - regionMapVisType = new BaseVisType(createRegionMapTypeDefinition(dependencies)); - RegionMapsVisualization = createRegionMapVisualization(dependencies); - - ChoroplethLayer.prototype._makeJsonAjaxCall = async function () { - //simulate network call - return new Promise((resolve) => { - setTimeout(() => { - resolve(worldJson); - }, 10); - }); - }; - - getManifestStub = serviceSettings.__debugStubManifestCalls(async (url) => { - //simulate network calls - if (url.startsWith('https://foobar')) { - return EMS_CATALOGUE; - } else if (url.startsWith('https://tiles.foobar')) { - return EMS_TILES; - } else if (url.startsWith('https://files.foobar')) { - return EMS_FILES; - } else if (url.startsWith('https://raster-style.foobar')) { - if (url.includes('osm-bright-desaturated')) { - return EMS_STYLE_ROAD_MAP_DESATURATED; - } else if (url.includes('osm-bright')) { - return EMS_STYLE_ROAD_MAP_BRIGHT; - } else if (url.includes('dark-matter')) { - return EMS_STYLE_DARK_MAP; - } - } - }); - }) - ); - - afterEach(function () { - ChoroplethLayer.prototype._makeJsonAjaxCall = _makeJsonAjaxCallOld; - getManifestStub.removeStub(); - }); - - describe('RegionMapVisualization - basics', function () { - beforeEach(async function () { - setupDOM('512px', '512px'); - - imageComparator = new ImageComparator(); - - vis = new ExprVis({ - type: regionMapVisType, - }); - - vis.params.bucket = { - accessor: 0, - }; - vis.params.metric = { - accessor: 1, - }; - - vis.params.selectedJoinField = { name: 'iso2', description: 'Two letter abbreviation' }; - vis.params.selectedLayer = { - attribution: - '

Made with NaturalEarth | Elastic Maps Service

', - name: 'World Countries', - format: 'geojson', - url: - 'https://vector-staging.maps.elastic.co/blob/5715999101812736?elastic_tile_service_tos=agree&my_app_version=7.0.0-alpha1', - fields: [ - { name: 'iso2', description: 'Two letter abbreviation' }, - { - name: 'iso3', - description: 'Three letter abbreviation', - }, - { name: 'name', description: 'Country name' }, - ], - created_at: '2017-07-31T16:00:19.996450', - id: 5715999101812736, - layerId: 'elastic_maps_service.World Countries', - }; - }); - - afterEach(function () { - teardownDOM(); - imageComparator.destroy(); - }); - - it('should instantiate at zoom level 2 (may fail in dev env)', async function () { - const regionMapsVisualization = new RegionMapsVisualization(domNode, vis); - await regionMapsVisualization.render(dummyTableGroup, vis.params, { - resize: false, - params: true, - aggs: true, - data: true, - uiState: false, - }); - const mismatchedPixels = await compareImage(initialPng); - regionMapsVisualization.destroy(); - expect(mismatchedPixels).to.be.lessThan(PIXEL_DIFF); - }); - - it('should update after resetting join field', async function () { - const regionMapsVisualization = new RegionMapsVisualization(domNode, vis); - await regionMapsVisualization.render(dummyTableGroup, vis.params, { - resize: false, - params: true, - aggs: true, - data: true, - uiState: false, - }); - - //this will actually create an empty image - vis.params.selectedJoinField = { name: 'iso3', description: 'Three letter abbreviation' }; - vis.params.isDisplayWarning = false; //so we don't get notifications - await regionMapsVisualization.render(dummyTableGroup, vis.params, { - resize: false, - params: true, - aggs: false, - data: false, - uiState: false, - }); - - const mismatchedPixels = await compareImage(toiso3Png); - regionMapsVisualization.destroy(); - expect(mismatchedPixels).to.be.lessThan(PIXEL_DIFF); - }); - - it('should resize (may fail in dev env)', async function () { - const regionMapsVisualization = new RegionMapsVisualization(domNode, vis); - await regionMapsVisualization.render(dummyTableGroup, vis.params, { - resize: false, - params: true, - aggs: true, - data: true, - uiState: false, - }); - - domNode.style.width = '256px'; - domNode.style.height = '128px'; - await regionMapsVisualization.render(dummyTableGroup, vis.params, { - resize: true, - params: false, - aggs: false, - data: false, - uiState: false, - }); - const mismatchedPixelsAfterFirstResize = await compareImage(afterresizePng); - - domNode.style.width = '512px'; - domNode.style.height = '512px'; - await regionMapsVisualization.render(dummyTableGroup, vis.params, { - resize: true, - params: false, - aggs: false, - data: false, - uiState: false, - }); - const mismatchedPixelsAfterSecondResize = await compareImage(initialPng); - - regionMapsVisualization.destroy(); - expect(mismatchedPixelsAfterFirstResize).to.be.lessThan(PIXEL_DIFF); - expect(mismatchedPixelsAfterSecondResize).to.be.lessThan(PIXEL_DIFF); - }); - - it('should redo data (may fail in dev env)', async function () { - const regionMapsVisualization = new RegionMapsVisualization(domNode, vis); - await regionMapsVisualization.render(dummyTableGroup, vis.params, { - resize: false, - params: true, - aggs: true, - data: true, - uiState: false, - }); - - const newTableGroup = _.cloneDeep(dummyTableGroup); - - newTableGroup.rows.pop(); //remove one shape - - await regionMapsVisualization.render(newTableGroup, vis.params, { - resize: false, - params: false, - aggs: false, - data: true, - uiState: false, - }); - - const mismatchedPixelsAfterDataChange = await compareImage(afterdatachangePng); - const anotherTableGroup = _.cloneDeep(newTableGroup); - - anotherTableGroup.rows.pop(); //remove one shape - domNode.style.width = '412px'; - domNode.style.height = '112px'; - await regionMapsVisualization.render(anotherTableGroup, vis.params, { - resize: true, - params: false, - aggs: false, - data: true, - uiState: false, - }); - const mismatchedPixelsAfterDataChangeAndResize = await compareImage( - afterdatachangeandresizePng - ); - - regionMapsVisualization.destroy(); - expect(mismatchedPixelsAfterDataChange).to.be.lessThan(PIXEL_DIFF); - expect(mismatchedPixelsAfterDataChangeAndResize).to.be.lessThan(PIXEL_DIFF); - }); - - it('should redo data and color ramp (may fail in dev env)', async function () { - const regionMapsVisualization = new RegionMapsVisualization(domNode, vis); - await regionMapsVisualization.render(dummyTableGroup, vis.params, { - resize: false, - params: true, - aggs: true, - data: true, - uiState: false, - }); - - const newTableGroup = _.cloneDeep(dummyTableGroup); - newTableGroup.rows.pop(); //remove one shape - vis.params.colorSchema = 'Blues'; - await regionMapsVisualization.render(newTableGroup, vis.params, { - resize: false, - params: true, - aggs: false, - data: true, - uiState: false, - }); - const mismatchedPixelsAfterDataAndColorChange = await compareImage(aftercolorchangePng); - - regionMapsVisualization.destroy(); - expect(mismatchedPixelsAfterDataAndColorChange).to.be.lessThan(PIXEL_DIFF); - }); - - it('should zoom and center elsewhere', async function () { - vis.params.mapZoom = 4; - vis.params.mapCenter = [36, -85]; - const regionMapsVisualization = new RegionMapsVisualization(domNode, vis); - await regionMapsVisualization.render(dummyTableGroup, vis.params, { - resize: false, - params: true, - aggs: true, - data: true, - uiState: false, - }); - - const mismatchedPixels = await compareImage(changestartupPng); - regionMapsVisualization.destroy(); - - expect(mismatchedPixels).to.be.lessThan(PIXEL_DIFF); - }); - }); - - async function compareImage(expectedImageSource) { - const elementList = domNode.querySelectorAll('canvas'); - expect(elementList.length).to.equal(1); - const firstCanvasOnMap = elementList[0]; - return imageComparator.compareImage(firstCanvasOnMap, expectedImageSource, THRESHOLD); - } - - function setupDOM(width, height) { - domNode = document.createElement('div'); - domNode.style.top = '0'; - domNode.style.left = '0'; - domNode.style.width = width; - domNode.style.height = height; - domNode.style.position = 'fixed'; - domNode.style.border = '1px solid blue'; - domNode.style['pointer-events'] = 'none'; - document.body.appendChild(domNode); - } - - function teardownDOM() { - domNode.innerHTML = ''; - document.body.removeChild(domNode); - } -}); diff --git a/src/plugins/region_map/public/__tests__/toiso3.png b/src/plugins/region_map/public/__tests__/toiso3.png deleted file mode 100644 index eebae19ae4364..0000000000000 Binary files a/src/plugins/region_map/public/__tests__/toiso3.png and /dev/null differ diff --git a/src/plugins/region_map/public/__tests__/world.json b/src/plugins/region_map/public/__tests__/world.json deleted file mode 100644 index 162e1f456e183..0000000000000 --- a/src/plugins/region_map/public/__tests__/world.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"name":"Antigua and Barbuda","iso2":"AG","iso3":"ATG"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-61.686668,17.024441000000152],[-61.887222,17.105274],[-61.794449,17.1633300000001],[-61.686668,17.024441000000152]]],[[[-61.72917199999989,17.608608],[-61.853058,17.583054000000104],[-61.873062,17.703888],[-61.72917199999989,17.608608]]]]}},{"type":"Feature","properties":{"name":"Algeria","iso2":"DZ","iso3":"DZA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[2.96361,36.802216],[4.785832,36.894722],[5.328055,36.640274],[6.398333,37.086388],[8.62203,36.941368],[8.183611,36.524162],[8.251665,34.64444],[7.492499000000123,33.887497],[8.34861,32.533333],[9.055277,32.099998],[9.537113,30.23439],[9.303888,30.122498],[9.766388,29.427776],[9.948332,27.824444],[9.871666,26.514164],[9.398333,26.153332],[10.252222,24.605831],[11.558887,24.302498],[11.986475,23.522305],[7.450807,20.852863],[5.812499,19.44611],[4.245277,19.146664],[3.331944,18.976387],[3.233055,19.820274],[1.795833,20.308331],[1.1675,20.741108],[1.169662,21.102543],[-4.806111,25.000275],[-6.662778,26.129166],[-8.66679,27.290459],[-8.666668,27.666664],[-8.667223,28.709442],[-7.123889,29.636944],[-5.538334,29.902496],[-4.920556,30.508053],[-3.626667,30.970554],[-3.818334,31.695553],[-2.853889,32.088333],[-1.180556,32.11055],[-1.010278,32.508331],[-1.668056,33.261108],[-1.747222,34.747215],[-2.209445,35.085831],[0.95,36.450272],[2.96361,36.802216]]]]}},{"type":"Feature","properties":{"name":"Azerbaijan","iso2":"AZ","iso3":"AZE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[45.083322525024414,39.76804542541504],[45.81998634338379,39.54972267150879],[46.17824745178223,38.84115028381348],[45.00443458557129,39.41638374328613],[44.81304359436035,39.630815505981445],[44.77886390686035,39.70638465881348],[45.083322525024414,39.76804542541504]]],[[[45.513051986694336,40.607221603393555],[45.51749229431152,40.66554069519043],[45.57305335998535,40.632490158081055],[45.513051986694336,40.607221603393555]]],[[[45.24527168273926,40.97694206237793],[45.22916221618652,40.96915245056152],[45.19582176208496,40.99777030944824],[45.24527168273926,40.97694206237793]]],[[[45.045270919799805,41.0352725982666],[45.009992599487305,41.03305244445801],[45.00111198425293,41.08888053894043],[45.045270919799805,41.0352725982666]]],[[[46.57138252258301,41.87193489074707],[47.76693153381348,41.19609260559082],[48.58395576477051,41.835771560668945],[49.52804756164551,40.66276741027832],[50.3749942779541,40.262216567993164],[49.488046646118164,40.15053749084473],[48.88828468322754,38.44240760803223],[48.020822525024414,38.83554267883301],[48.35978889465332,39.38521766662598],[47.97666358947754,39.7192325592041],[46.54037666320801,38.87558937072754],[46.54138374328613,39.56443977355957],[45.5958194732666,39.978044509887695],[46.00193977355957,40.22554969787598],[45.15387153625488,41.1986026763916],[45.0229434967041,41.29705238342285],[45.33665657043457,41.46249580383301],[46.520822525024414,41.04998970031738],[46.69387245178223,41.312204360961914],[46.19442939758301,41.68582344055176],[46.45175361633301,41.89705848693848],[46.57138252258301,41.87193489074707]]]]}},{"type":"Feature","properties":{"name":"Albania","iso2":"AL","iso3":"ALB"},"geometry":{"type":"MultiPolygon","coordinates":[[[[19.436214,41.021065],[19.600555,41.796661],[19.367771,41.848999],[19.645832,42.61805],[20.071423,42.560913],[20.589642,41.882187],[20.492775,41.331108],[20.82111,40.908882],[20.98349,40.855888],[20.671944,40.09805300000012],[20.010029,39.6912],[19.863052,40.039719],[19.288609,40.417496],[19.478611,40.350273],[19.436214,41.021065]]]]}},{"type":"Feature","properties":{"name":"Armenia","iso2":"AM","iso3":"ARM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[45.15387153625488,41.1986026763916],[46.00193977355957,40.22554969787598],[45.5958194732666,39.978044509887695],[46.54138374328613,39.56443977355957],[46.54037666320801,38.87558937072754],[46.17824745178223,38.84115028381348],[45.81998634338379,39.54972267150879],[45.083322525024414,39.76804542541504],[44.77886390686035,39.70638465881348],[44.34721565246582,40.02388954162598],[43.65749549865723,40.108598709106445],[43.75193977355957,40.739999771118164],[43.460771560668945,41.11296272277832],[45.0229434967041,41.29705238342285],[45.15387153625488,41.1986026763916]],[[45.009992599487305,41.03305244445801],[45.045270919799805,41.0352725982666],[45.00111198425293,41.08888053894043],[45.009992599487305,41.03305244445801]],[[45.19582176208496,40.99777030944824],[45.22916221618652,40.96915245056152],[45.24527168273926,40.97694206237793],[45.19582176208496,40.99777030944824]],[[45.57305335998535,40.632490158081055],[45.51749229431152,40.66554069519043],[45.513051986694336,40.607221603393555],[45.57305335998535,40.632490158081055]]]]}},{"type":"Feature","properties":{"name":"Angola","iso2":"AO","iso3":"AGO"},"geometry":{"type":"MultiPolygon","coordinates":[[[[11.750833511352539,-16.755279541015625],[11.693609237670898,-16.53555679321289],[11.774999618530273,-16.804725646972656],[11.750833511352539,-16.755279541015625]]],[[[13.997499465942383,-5.848611831665039],[16.579721450805664,-5.900833129882813],[16.941667556762695,-7.198610305786133],[17.62416648864746,-8.09805679321289],[19.373056411743164,-7.996110916137695],[19.538949966430664,-6.996614456176758],[20.62974739074707,-6.913881301879883],[20.548715591430664,-7.283615112304688],[21.782960891723633,-7.280841827392578],[21.790555953979492,-9.405555725097656],[22.312223434448242,-10.364444732666016],[22.253889083862305,-11.209722518920898],[23.986207962036133,-10.870460510253906],[24.02055549621582,-13.006389617919922],[21.998334884643555,-13.004167556762695],[22.000150680541992,-16.171661376953125],[23.476110458374023,-17.625835418701172],[23.28472328186035,-17.66250228881836],[20.85416603088379,-18.01639175415039],[18.915834426879883,-17.815555572509766],[18.451539993286133,-17.389835357666016],[13.993219375610352,-17.423946380615234],[13.160554885864258,-16.952777862548828],[11.752782821655273,-17.254833221435547],[11.820833206176758,-16.503055572509766],[11.810834884643555,-15.993057250976562],[11.731389999389648,-15.846668243408203],[12.509721755981445,-13.42527961730957],[13.792501449584961,-11.791667938232422],[13.773611068725586,-10.684722900390625],[12.984445571899414,-9.087501525878906],[13.391389846801758,-8.387222290039062],[12.245000839233398,-6.098054885864258],[13.17888069152832,-5.856328964233398],[13.997499465942383,-5.848611831665039]]],[[[13.088888168334961,-4.662500381469727],[12.565553665161133,-5.025554656982422],[12.526666641235352,-5.724166870117188],[12.21455192565918,-5.7685546875],[12.026132583618164,-5.014995574951172],[12.779047012329102,-4.38899040222168],[13.091390609741211,-4.633054733276367],[13.088888168334961,-4.662500381469727]]]]}},{"type":"Feature","properties":{"name":"American Samoa","iso2":"AS","iso3":"ASM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-170.542511,-14.297503],[-170.560822,-14.287781],[-170.540039,-14.283892],[-170.542511,-14.297503]]],[[[-170.637268,-14.289446],[-170.826111,-14.325003],[-170.560028,-14.265837],[-170.637268,-14.289446]]],[[[-169.444489,-14.261667],[-169.513062,-14.275833],[-169.536133,-14.231668],[-169.444489,-14.261667]]],[[[-169.62558,-14.189722],[-169.644745,-14.176111],[-169.621948,-14.168612],[-169.62558,-14.189722]]],[[[-169.685577,-14.191944],[-169.690857,-14.167501],[-169.662231,-14.175001],[-169.685577,-14.191944]]]]}},{"type":"Feature","properties":{"name":"Argentina","iso2":"AR","iso3":"ARG"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-68.60861199999988,-54.891396],[-68.643112,-54.888611],[-68.636124,-54.804771],[-68.60861199999988,-54.891396]]],[[[-63.813614,-54.731392],[-64.678345,-54.907227],[-64.75528,-54.835007],[-63.813614,-54.731392]]],[[[-68.261948,-52.98806],[-68.543625,-53.229446],[-67.359177,-54.028893],[-65.138062,-54.651672],[-65.353897,-54.929169],[-66.44612099999989,-55.051674],[-68.635834,-54.788338],[-68.617584,-52.64151],[-68.261948,-52.98806]]],[[[-61.878891,-39.2425],[-62.095284,-39.089172],[-61.890556,-39.139168],[-61.878891,-39.2425]]],[[[-61.996948,-39.066948],[-62.132782,-39.01889],[-61.981392,-39.026947],[-61.996948,-39.066948]]],[[[-65.748062,-22.111668],[-65.190201,-22.09473],[-64.590561,-22.214725],[-64.324722,-22.873611],[-63.941116,-22.000835],[-62.811951,-21.996948],[-62.643768,-22.238903],[-61.007782,-23.813335],[-57.75611099999986,-25.176945],[-57.576668,-25.549446],[-58.604622,-27.316921],[-55.736115,-27.439445],[-54.698334,-26.438335],[-54.59891499999989,-25.573223],[-53.863335,-25.681114],[-53.807785,-27.129169],[-55.765282,-28.226112],[-57.608002,-30.184925],[-57.806396,-30.748219],[-58.199242,-32.45031],[-58.147224,-33.051674],[-58.426948999999865,-33.096947],[-58.531951999999876,-33.516945],[-58.383896,-34.05584],[-58.469726999999864,-34.539726],[-57.188339,-35.320557],[-57.376671,-35.962784],[-56.741669,-36.318336],[-56.663063,-36.900558],[-57.571671,-38.133057],[-58.301117,-38.485001],[-61.094452,-38.995834],[-62.38139299999989,-38.798615],[-62.020004,-39.378059],[-62.277229,-39.335281],[-62.06778,-39.505562],[-62.489449,-40.299446],[-62.183891,-40.629723],[-62.390006999999855,-40.901947],[-63.765839,-41.16584],[-65.134445,-40.847778],[-65.013626,-42.092224],[-64.45195,-42.445839],[-63.746948,-42.090561],[-63.580559,-42.623894],[-64.086945,-42.890282],[-64.398056,-42.515839],[-64.960556,-42.666389],[-64.295013,-42.991951],[-65.32251,-43.653061],[-65.249451,-44.313057],[-65.691681,-44.716949],[-65.604736,-45.016396],[-66.949448,-45.255562],[-67.584351,-46.000298],[-67.506119,-46.458893],[-66.816956,-46.991669],[-65.779449,-47.189445],[-65.871948,-47.758057],[-66.243622,-47.860283],[-65.787231,-47.962502],[-67.579453,-49.034172],[-67.897232,-49.98584],[-69.011124,-50.011948],[-68.37028499999988,-50.146667],[-68.941116,-50.388062],[-69.40888999999987,-51.077782],[-69.183624,-50.970558],[-68.968063,-51.573891],[-69.613892,-51.625839],[-68.988068,-51.624725],[-68.441757,-52.377777],[-69.998337,-51.996391],[-71.910568,-51.995834],[-72.400558,-51.513618],[-72.294174,-50.649727],[-73.16612199999986,-50.753334],[-73.58361799999989,-49.538063],[-72.564178,-48.804451],[-72.287231,-48.341949],[-72.53639199999986,-47.921394],[-72.360291,-47.470001],[-71.868622,-47.221672],[-71.940292,-46.815559],[-71.669449,-46.679169],[-71.780563,-45.648895],[-71.297791,-45.293335],[-72.078613,-44.769447],[-71.282227,-44.800285],[-71.108063,-44.539726],[-71.855011,-44.371674],[-71.732788,-43.188057],[-72.136948,-43.009171],[-72.131958,-42.288895],[-71.72612,-42.096672],[-71.95056199999988,-40.73278],[-71.695557,-39.58445],[-71.401398,-38.92028],[-70.824173,-38.568062],[-71.185287,-36.842224],[-70.424316,-36.13604],[-70.567505,-35.24778],[-69.8125,-34.235558],[-69.774445,-33.381111],[-70.098892,-33.172501],[-70.533066,-31.188057],[-69.83168,-30.190556],[-70.031403,-29.306393],[-69.65538,-28.400932],[-68.810837,-27.120556],[-68.287231,-26.915279],[-68.583618,-26.50528],[-68.35195899999988,-25.117226],[-68.56500199999988,-24.774445],[-67.335846,-24.021667],[-67.00083899999987,-23.002781],[-67.183624,-22.821667],[-66.22300699999988,-21.780521],[-65.748062,-22.111668]]]]}},{"type":"Feature","properties":{"name":"Australia","iso2":"AU","iso3":"AUS"},"geometry":{"type":"MultiPolygon","coordinates":[[[[158.882173538208,-54.711387634277344],[158.83331489562988,-54.749725341796875],[158.95746040344238,-54.47471618652344],[158.882173538208,-54.711387634277344]]],[[[147.36273384094238,-43.39805603027344],[147.1230182647705,-43.42194366455078],[147.29193305969238,-43.26194763183594],[147.36273384094238,-43.39805603027344]]],[[[147.42968940734863,-43.25361633300781],[147.29193305969238,-43.16444396972656],[147.359956741333,-43.07361602783203],[147.42968940734863,-43.25361633300781]]],[[[148.17053413391113,-42.66388702392578],[148.01416206359863,-42.75305938720703],[148.021089553833,-42.61805725097656],[148.17053413391113,-42.66388702392578]]],[[[148.33331489562988,-42.35889434814453],[148.23108100891113,-42.30194091796875],[148.31912422180176,-42.312774658203125],[148.33331489562988,-42.35889434814453]]],[[[145.10772895812988,-40.82167053222656],[146.58609199523926,-41.18666076660156],[148.22329902648926,-40.85083770751953],[148.36551094055176,-42.215003967285156],[148.18387031555176,-41.94305419921875],[147.84301948547363,-42.86944580078125],[147.99524116516113,-43.22972106933594],[147.317476272583,-42.84666442871094],[146.91670417785645,-43.61784362792969],[146.0383014678955,-43.49805450439453],[146.23636054992676,-43.32722473144531],[145.496919631958,-42.95777893066406],[145.20523262023926,-42.25695037841797],[145.55191230773926,-42.34416198730469],[144.682466506958,-41.22332763671875],[144.70135688781738,-40.75917053222656],[145.10772895812988,-40.82167053222656]]],[[[144.926362991333,-40.722496032714844],[144.92413520812988,-40.61528015136719],[145.0160846710205,-40.69554901123047],[144.926362991333,-40.722496032714844]]],[[[148.20025825500488,-40.59416198730469],[148.09720039367676,-40.53388977050781],[148.2157917022705,-40.501943588256836],[148.20025825500488,-40.59416198730469]]],[[[144.75555610656738,-40.59666442871094],[144.71747016906738,-40.50389099121094],[144.77969551086426,-40.40943908691406],[144.75555610656738,-40.59666442871094]]],[[[144.94134712219238,-40.458892822265625],[144.83218574523926,-40.43360900878906],[144.94970893859863,-40.38722229003906],[144.94134712219238,-40.458892822265625]]],[[[148.35467720031738,-40.3155517578125],[148.4758014678955,-40.443885803222656],[147.99356269836426,-40.420555114746094],[148.35467720031738,-40.3155517578125]]],[[[148.1774616241455,-40.25695037841797],[147.88189888000488,-39.754173278808594],[148.27942085266113,-39.96583557128906],[148.1774616241455,-40.25695037841797]]],[[[143.9577350616455,-40.11000061035156],[143.97302436828613,-39.573333740234375],[144.14749336242676,-39.927223205566406],[143.9577350616455,-40.11000061035156]]],[[[147.35357856750488,-39.49944305419922],[147.307466506958,-39.48750305175781],[147.34442329406738,-39.44805145263672],[147.35357856750488,-39.49944305419922]]],[[[147.29998970031738,-39.482215881347656],[147.285249710083,-39.47388458251953],[147.315523147583,-39.43194580078125],[147.29998970031738,-39.482215881347656]]],[[[146.65555000305176,-38.76972198486328],[146.54471015930176,-38.80027770996094],[146.4677448272705,-38.758056640625],[146.65555000305176,-38.76972198486328]]],[[[145.31164741516113,-38.4677734375],[145.36136054992676,-38.56916809082031],[145.11358833312988,-38.52888488769531],[145.31164741516113,-38.4677734375]]],[[[145.49273872375488,-38.37444305419922],[145.271089553833,-38.36333465576172],[145.30581855773926,-38.29695129394531],[145.49273872375488,-38.37444305419922]]],[[[137.58496284484863,-35.65083312988281],[138.11273384094238,-35.869720458984375],[136.53442573547363,-35.912498474121094],[137.58496284484863,-35.65083312988281]]],[[[136.49524116516113,-35.175559997558594],[136.434419631958,-35.158050537109375],[136.466646194458,-35.13861083984375],[136.49524116516113,-35.175559997558594]]],[[[136.20276069641113,-35.07695007324219],[136.0866413116455,-34.94721984863281],[136.19580268859863,-35.026390075683594],[136.20276069641113,-35.07695007324219]]],[[[118.4719181060791,-34.938331604003906],[118.4246997833252,-34.90777587890625],[118.47638130187988,-34.918060302734375],[118.4719181060791,-34.938331604003906]]],[[[137.358003616333,-34.540283203125],[137.33441352844238,-34.51555633544922],[137.36578559875488,-34.47777557373047],[137.358003616333,-34.540283203125]]],[[[122.24693489074707,-34.15166473388672],[122.22998237609863,-34.112220764160156],[122.25554847717285,-34.12444305419922],[122.24693489074707,-34.15166473388672]]],[[[123.20749092102051,-34.11194610595703],[123.16776466369629,-34.094444274902344],[123.21582221984863,-34.08611297607422],[123.20749092102051,-34.11194610595703]]],[[[134.48663520812988,-33.779998779296875],[134.48025703430176,-33.71416473388672],[134.5402545928955,-33.69666290283203],[134.48663520812988,-33.779998779296875]]],[[[133.58941841125488,-32.311668395996094],[133.53360176086426,-32.304443359375],[133.67498970031738,-32.24055480957031],[133.58941841125488,-32.311668395996094]]],[[[115.68026924133301,-32.22833251953125],[115.66081428527832,-32.233612060546875],[115.64888191223145,-32.1522216796875],[115.68026924133301,-32.22833251953125]]],[[[159.07080268859863,-31.52361297607422],[159.101900100708,-31.57111358642578],[159.07080268859863,-31.599998474121094],[159.07080268859863,-31.52361297607422]]],[[[153.45135688781738,-27.729164123535156],[153.43359565734863,-27.41611099243164],[153.53857612609863,-27.416664123535156],[153.45135688781738,-27.729164123535156]]],[[[153.41497993469238,-27.24805450439453],[153.45413398742676,-27.017780303955078],[153.4252643585205,-27.362777709960938],[153.41497993469238,-27.24805450439453]]],[[[113.20915412902832,-26.14083480834961],[112.95332527160645,-25.786945343017578],[112.95110511779785,-25.488609313964844],[113.20915412902832,-26.14083480834961]]],[[[153.00360298156738,-25.34000015258789],[152.94885444641113,-25.272502899169922],[152.99246406555176,-25.307777404785156],[153.00360298156738,-25.34000015258789]]],[[[113.07361030578613,-25.23360824584961],[113.06165504455566,-25.278614044189453],[113.10164833068848,-25.09722137451172],[113.07361030578613,-25.23360824584961]]],[[[113.13971138000488,-24.926666259765625],[113.11499214172363,-24.995830535888672],[113.14721870422363,-24.76000213623047],[113.13971138000488,-24.926666259765625]]],[[[153.07718086242676,-25.79861068725586],[152.94302558898926,-25.558334350585938],[153.28164863586426,-24.69916534423828],[153.07718086242676,-25.79861068725586]]],[[[151.382173538208,-23.88277816772461],[151.3305377960205,-23.813335418701172],[151.32690620422363,-23.753055572509766],[151.382173538208,-23.88277816772461]]],[[[151.26944160461426,-23.780555725097656],[151.0199909210205,-23.454444885253906],[151.20303535461426,-23.528888702392578],[151.26944160461426,-23.780555725097656]]],[[[150.98217964172363,-23.195552825927734],[150.94720649719238,-23.195552825927734],[150.97830390930176,-23.150554656982422],[150.98217964172363,-23.195552825927734]]],[[[149.73550605773926,-22.423053741455078],[149.73358345031738,-22.340557098388672],[149.76080513000488,-22.363887786865234],[149.73550605773926,-22.423053741455078]]],[[[150.49164009094238,-22.354721069335938],[150.4899616241455,-22.213054656982422],[150.56024360656738,-22.304447174072266],[150.49164009094238,-22.354721069335938]]],[[[149.90081977844238,-22.22833251953125],[149.86578559875488,-22.17388916015625],[149.90832710266113,-22.046945571899414],[149.90081977844238,-22.22833251953125]]],[[[150.33691596984863,-21.775558471679688],[150.29443550109863,-21.744441986083984],[150.3588581085205,-21.73332977294922],[150.33691596984863,-21.775558471679688]]],[[[150.28692817687988,-21.6875],[150.2538776397705,-21.63805389404297],[150.30523872375488,-21.65999984741211],[150.28692817687988,-21.6875]]],[[[115.45498847961426,-20.782501220703125],[115.30386543273926,-20.87277603149414],[115.43525886535645,-20.667221069335938],[115.45498847961426,-20.782501220703125]]],[[[149.06665229797363,-20.526668548583984],[149.03692817687988,-20.501667022705078],[149.07498359680176,-20.486942291259766],[149.06665229797363,-20.526668548583984]]],[[[149.00638008117676,-20.31833267211914],[148.9555377960205,-20.29138946533203],[148.97552680969238,-20.154998779296875],[149.00638008117676,-20.31833267211914]]],[[[148.93579292297363,-20.17194366455078],[148.88189888000488,-20.130279541015625],[148.97024726867676,-20.04861068725586],[148.93579292297363,-20.17194366455078]]],[[[148.47134590148926,-20.046390533447266],[148.44970893859863,-19.97083282470703],[148.48217964172363,-20.00611114501953],[148.47134590148926,-20.046390533447266]]],[[[146.86773872375488,-19.165000915527344],[146.7760944366455,-19.13111114501953],[146.86969184875488,-19.106666564941406],[146.86773872375488,-19.165000915527344]]],[[[146.299409866333,-18.48944091796875],[146.08331489562988,-18.25611114501953],[146.26971626281738,-18.308334350585938],[146.299409866333,-18.48944091796875]]],[[[139.57608222961426,-17.09583282470703],[139.39886665344238,-17.091388702392578],[139.502779006958,-16.996665954589844],[139.57608222961426,-17.09583282470703]]],[[[139.11218452453613,-16.862220764160156],[139.0907917022705,-16.82666778564453],[139.139986038208,-16.810558319091797],[139.11218452453613,-16.862220764160156]]],[[[139.73636054992676,-16.49721908569336],[139.14026069641113,-16.755001068115234],[139.30664253234863,-16.46249771118164],[139.73636054992676,-16.49721908569336]]],[[[136.6672077178955,-15.776666641235352],[136.6349811553955,-15.676111221313477],[136.71301460266113,-15.697778701782227],[136.6672077178955,-15.776666641235352]]],[[[136.7419147491455,-15.75222396850586],[136.73413276672363,-15.648056030273438],[136.809419631958,-15.650278091430664],[136.7419147491455,-15.75222396850586]]],[[[137.06720161437988,-15.829444885253906],[136.934419631958,-15.698888778686523],[137.00305366516113,-15.591388702392578],[137.06720161437988,-15.829444885253906]]],[[[136.52997016906738,-15.645278930664062],[136.57940864562988,-15.511112213134766],[136.597749710083,-15.616109848022461],[136.52997016906738,-15.645278930664062]]],[[[136.85135078430176,-15.634166717529297],[136.84192085266113,-15.549722671508789],[136.87857246398926,-15.501943588256836],[136.85135078430176,-15.634166717529297]]],[[[124.62164497375488,-15.412221908569336],[124.52249336242676,-15.44527816772461],[124.45942878723145,-15.366943359375],[124.54221534729004,-15.261667251586914],[124.62164497375488,-15.412221908569336]]],[[[124.42637825012207,-15.315000534057617],[124.33664894104004,-15.296112060546875],[124.43747901916504,-15.249443054199219],[124.42637825012207,-15.315000534057617]]],[[[124.81609535217285,-15.281112670898438],[124.79749488830566,-15.239721298217773],[124.8499927520752,-15.247220993041992],[124.81609535217285,-15.281112670898438]]],[[[128.19192695617676,-15.18861198425293],[128.11468696594238,-15.131942749023438],[128.12051582336426,-15.043054580688477],[128.19192695617676,-15.18861198425293]]],[[[124.94331550598145,-15.030000686645508],[124.87468910217285,-14.95222282409668],[124.92442512512207,-14.944999694824219],[124.94331550598145,-15.030000686645508]]],[[[128.44107246398926,-15.037500381469727],[128.35717964172363,-14.959999084472656],[128.35635566711426,-14.870277404785156],[128.44107246398926,-15.037500381469727]]],[[[135.764986038208,-14.904167175292969],[135.69940376281738,-14.907777786254883],[135.72830390930176,-14.836666107177734],[135.764986038208,-14.904167175292969]]],[[[129.62994575500488,-14.879444122314453],[129.5805377960205,-14.802778244018555],[129.63080024719238,-14.850831985473633],[129.62994575500488,-14.879444122314453]]],[[[129.58941841125488,-14.907777786254883],[129.59247016906738,-14.966665267944336],[129.5019245147705,-14.788612365722656],[129.58941841125488,-14.907777786254883]]],[[[125.1383228302002,-14.648611068725586],[125.08471870422363,-14.61722183227539],[125.1594181060791,-14.438333511352539],[125.1383228302002,-14.648611068725586]]],[[[126.60637092590332,-13.895553588867188],[126.51193428039551,-13.909444808959961],[126.50248908996582,-13.877777099609375],[126.60637092590332,-13.895553588867188]]],[[[136.7116413116455,-13.835832595825195],[136.91247749328613,-13.774444580078125],[136.69940376281738,-14.120832443237305],[136.94165229797363,-14.277778625488281],[136.378023147583,-14.216388702392578],[136.7116413116455,-13.835832595825195]]],[[[136.2883014678955,-13.733331680297852],[136.10553169250488,-13.818056106567383],[136.19885444641113,-13.664722442626953],[136.2883014678955,-13.733331680297852]]],[[[136.15081977844238,-13.485832214355469],[136.16165351867676,-13.531112670898438],[136.0988483428955,-13.36111068725586],[136.15081977844238,-13.485832214355469]]],[[[132.40469551086426,-12.14083480834961],[132.34024238586426,-12.0897216796875],[132.402193069458,-12.072221755981445],[132.40469551086426,-12.14083480834961]]],[[[136.8205280303955,-12.140556335449219],[136.80053901672363,-12.094165802001953],[136.82608222961426,-12.072221755981445],[136.8205280303955,-12.140556335449219]]],[[[134.90997505187988,-12.121110916137695],[134.8669147491455,-12.066665649414062],[134.92776679992676,-12.072776794433594],[134.90997505187988,-12.121110916137695]]],[[[134.98578071594238,-12.03416633605957],[134.94497871398926,-12.061389923095703],[134.91137886047363,-12.022222518920898],[134.98578071594238,-12.03416633605957]]],[[[136.28192329406738,-12.03555679321289],[136.15832710266113,-12.071388244628906],[136.3063678741455,-11.976943969726562],[136.28192329406738,-12.03555679321289]]],[[[135.11551094055176,-11.934444427490234],[135.04748725891113,-11.945554733276367],[135.06497383117676,-11.913612365722656],[135.11551094055176,-11.934444427490234]]],[[[136.47357368469238,-11.911111831665039],[136.46942329406738,-11.840555191040039],[136.494966506958,-11.803054809570312],[136.47357368469238,-11.911111831665039]]],[[[136.58941841125488,-11.780555725097656],[136.5160846710205,-11.79861068725586],[136.62466621398926,-11.740276336669922],[136.58941841125488,-11.780555725097656]]],[[[136.01275825500488,-11.719165802001953],[135.95996284484863,-11.684165954589844],[136.05386543273926,-11.65999984741211],[136.01275825500488,-11.719165802001953]]],[[[132.56024360656738,-11.724443435668945],[132.5138874053955,-11.643890380859375],[132.6430377960205,-11.648056030273438],[132.56024360656738,-11.724443435668945]]],[[[133.383882522583,-11.667499542236328],[133.3669147491455,-11.614721298217773],[133.48245429992676,-11.586944580078125],[133.383882522583,-11.667499542236328]]],[[[136.47052192687988,-11.519166946411133],[136.178316116333,-11.68777847290039],[136.478853225708,-11.466110229492188],[136.47052192687988,-11.519166946411133]]],[[[133.50555610656738,-11.503889083862305],[133.39135932922363,-11.543889999389648],[133.46942329406738,-11.460832595825195],[133.50555610656738,-11.503889083862305]]],[[[130.491060256958,-11.68861198425293],[130.01638984680176,-11.779722213745117],[130.34247016906738,-11.323610305786133],[130.491060256958,-11.68861198425293]]],[[[130.57330513000488,-11.349443435668945],[131.274995803833,-11.189167022705078],[131.539155960083,-11.461666107177734],[130.95886421203613,-11.938888549804688],[130.37744331359863,-11.170555114746094],[130.57330513000488,-11.349443435668945]]],[[[132.62384223937988,-11.279167175292969],[132.51248359680176,-11.143056869506836],[132.57885932922363,-11.022500991821289],[132.62384223937988,-11.279167175292969]]],[[[136.5361042022705,-11.454999923706055],[136.77191352844238,-11.019721984863281],[136.72497749328613,-11.20694351196289],[136.5361042022705,-11.454999923706055]]],[[[142.51275825500488,-10.866943359375],[143.42914009094238,-12.614444732666016],[143.7821979522705,-14.413333892822266],[144.51053047180176,-14.168333053588867],[145.31579780578613,-14.945554733276367],[145.40359687805176,-16.46221923828125],[145.96051216125488,-16.895278930664062],[145.878023147583,-17.06277847290039],[146.10663032531738,-17.683609008789062],[146.00943183898926,-18.238052368164062],[146.33691596984863,-18.536666870117188],[146.27527046203613,-18.883888244628906],[148.77746772766113,-20.232498168945312],[148.9355182647705,-20.532779693603516],[148.69165229797363,-20.62444305419922],[149.214693069458,-21.080001831054688],[149.6611042022705,-22.496665954589844],[150.043306350708,-22.650833129882812],[150.0341510772705,-22.149723052978516],[150.59301948547363,-22.58611297607422],[150.63720893859863,-22.343891143798828],[150.86718940734863,-23.505001068115234],[151.53857612609863,-24.089168548583984],[151.68387031555176,-23.988887786865234],[151.93719673156738,-24.221664428710938],[153.18191719055176,-25.949443817138672],[153.03387641906738,-27.179443359375],[153.62552070617676,-28.666664123535156],[153.0524616241455,-31.03499984741211],[152.52969551086426,-32.40361022949219],[151.45276069641113,-33.31916809082031],[150.84051704406738,-35.08277893066406],[150.16247749328613,-35.9405517578125],[149.9738483428955,-37.52055358886719],[147.76443672180176,-37.97999572753906],[146.87356758117676,-38.65166473388672],[146.22302436828613,-38.712501525878906],[146.394136428833,-39.14722442626953],[145.41607856750488,-38.54583740234375],[145.55719184875488,-38.37638854980469],[145.44134712219238,-38.226104736328125],[144.89886665344238,-38.50444793701172],[145.13244819641113,-38.140281677246094],[144.92914009094238,-37.869163513183594],[143.54385566711426,-38.86000061035156],[142.3888874053955,-38.364723205566406],[141.57135200500488,-38.41722106933594],[140.52997016906738,-38.000282287597656],[139.8144245147705,-37.29972839355469],[139.8205280303955,-36.54583740234375],[139.07734870910645,-35.68263626098633],[139.66775703430176,-36.23082733154297],[139.09674263000488,-35.61588668823242],[139.33719062805176,-35.69416046142578],[139.35522651672363,-35.37249755859375],[138.09301948547363,-35.62083435058594],[138.51416206359863,-35.028053283691406],[138.09802436828613,-34.13722229003906],[137.74469184875488,-35.13861083984375],[136.8305377960205,-35.254722595214844],[137.0199909210205,-34.90110778808594],[137.43774604797363,-34.934722900390625],[137.44998359680176,-34.151390075683594],[137.95025825500488,-33.55944061279297],[137.77331733703613,-32.52361297607422],[137.77832221984863,-32.99250030517578],[137.20996284484863,-33.666107177734375],[135.93274116516113,-34.54194641113281],[135.95413398742676,-35.010284423828125],[135.105806350708,-34.599998474121094],[135.506929397583,-34.61805725097656],[134.70913887023926,-33.179168701171875],[134.269136428833,-33.15972137451172],[134.18414497375488,-32.486663818359375],[133.851900100708,-32.545005798339844],[133.95218086242676,-32.39472198486328],[133.62219429016113,-32.09833526611328],[133.4172077178955,-32.21333312988281],[132.76443672180176,-31.95083236694336],[132.20385932922363,-32.03166961669922],[131.152193069458,-31.474166870117188],[128.98745918273926,-31.694164276123047],[127.26776313781738,-32.27833557128906],[125.96832466125488,-32.26611328125],[124.28193855285645,-32.985557556152344],[123.54081916809082,-33.90583038330078],[120.00499153137207,-33.92888641357422],[117.93441963195801,-35.125831604003906],[116.46331977844238,-35.00083923339844],[115.00804328918457,-34.2630615234375],[114.98872566223145,-33.52253723144531],[115.36360359191895,-33.633056640625],[115.71111488342285,-33.269996643066406],[115.73943519592285,-31.865276336669922],[115.04553413391113,-30.506946563720703],[114.88553810119629,-29.20111083984375],[113.22442817687988,-26.239166259765625],[113.27916145324707,-26.018333435058594],[113.6413745880127,-26.65277862548828],[113.85582160949707,-26.507503509521484],[113.39166450500488,-25.718055725097656],[113.46943855285645,-25.540836334228516],[113.7119312286377,-26.19527816772461],[113.87886238098145,-26.028888702392578],[114.06609535217285,-26.461944580078125],[114.22083473205566,-26.30638885498047],[114.25916481018066,-25.846668243408203],[113.38971138000488,-24.429443359375],[114.01805305480957,-21.850833892822266],[114.15387153625488,-22.52777862548828],[114.65109443664551,-21.84000015258789],[116.70749092102051,-20.649166107177734],[117.68802833557129,-20.675830841064453],[119.08249092102051,-19.967498779296875],[121.0274829864502,-19.59222412109375],[122.35331916809082,-18.105554580688477],[122.17498970031738,-17.243331909179688],[122.91776466369629,-16.41555404663086],[123.57527351379395,-17.59749984741211],[123.59665107727051,-16.98999786376953],[123.91832160949707,-17.204444885253906],[123.42442512512207,-16.50250244140625],[123.7088794708252,-16.430278778076172],[123.5697193145752,-16.17194366455078],[123.72943305969238,-16.13888931274414],[123.8913745880127,-16.378887176513672],[123.96443367004395,-16.24555206298828],[124.23858833312988,-16.406665802001953],[124.8994312286377,-16.415000915527344],[124.40054512023926,-16.329444885253906],[124.72831916809082,-15.810556411743164],[124.4013843536377,-15.871110916137695],[124.4477481842041,-15.486387252807617],[124.65637397766113,-15.479721069335938],[124.70221138000488,-15.252500534057617],[125.18181037902832,-15.520685195922852],[124.82554817199707,-15.155834197998047],[125.43332099914551,-15.138612747192383],[125.13553810119629,-14.741388320922852],[125.5888843536377,-14.549444198608398],[125.60693550109863,-14.223054885864258],[125.63720893859863,-14.635000228881836],[125.71887397766113,-14.400278091430664],[126.03720283508301,-14.516666412353516],[126.01944160461426,-13.919166564941406],[126.28777503967285,-14.233055114746094],[126.86276435852051,-13.749164581298828],[127.42082405090332,-13.949722290039062],[128.16943550109863,-14.702777862548828],[128.01361274719238,-15.5],[128.129243850708,-15.212888717651367],[128.28997993469238,-15.405279159545898],[128.19412422180176,-15.05666732788086],[128.31497383117676,-14.907777786254883],[128.3508014678955,-15.044723510742188],[128.45245552062988,-15.046388626098633],[128.38189888000488,-14.802499771118164],[128.53027534484863,-14.759166717529297],[129.73245429992676,-15.197221755981445],[129.64386177062988,-14.837221145629883],[129.944429397583,-14.767778396606445],[129.37024116516113,-14.333332061767578],[129.88611030578613,-13.44527816772461],[130.26443672180176,-13.325277328491211],[130.14081001281738,-12.92416763305664],[130.69525337219238,-12.702499389648438],[130.58304023742676,-12.395278930664062],[130.89636421203613,-12.640277862548828],[131.027193069458,-12.145553588867188],[132.38360786437988,-12.379999160766602],[132.75442695617676,-12.132776260375977],[132.62774848937988,-12.04194450378418],[132.69107246398926,-11.655000686645508],[132.4899616241455,-11.476943969726562],[132.09247016906738,-11.526390075683594],[131.766939163208,-11.316389083862305],[131.9799518585205,-11.125555038452148],[132.19970893859863,-11.412778854370117],[132.14331245422363,-11.133333206176758],[132.33746528625488,-11.129165649414062],[133.18304634094238,-11.716665267944336],[135.23135566711426,-12.294445037841797],[135.90802192687988,-11.763055801391602],[135.66971015930176,-12.196666717529297],[136.023042678833,-12.111944198608398],[136.03970527648926,-12.47166633605957],[136.56219673156738,-11.934444427490234],[136.9819049835205,-12.356943130493164],[136.49441719055176,-12.779167175292969],[136.45800971984863,-13.252500534057617],[136.35052680969238,-13.052499771118164],[135.92386054992676,-13.281389236450195],[136.02026557922363,-13.762500762939453],[135.456636428833,-14.941110610961914],[136.76581001281738,-15.90444564819336],[137.730806350708,-16.246109008789062],[138.19024848937988,-16.704998016357422],[139.01748847961426,-16.903053283691406],[139.26053047180176,-17.342498779296875],[140.494966506958,-17.64083480834961],[141.42691230773926,-16.079166412353516],[141.58386421203613,-12.989166259765625],[141.79858589172363,-12.685832977294922],[141.94079780578613,-12.875831604003906],[141.75247383117676,-12.467222213745117],[141.58941841125488,-12.546945571899414],[142.02887153625488,-12.06222152709961],[142.141939163208,-10.956666946411133],[142.51275825500488,-10.866943359375]]],[[[142.26581001281738,-10.683610916137695],[142.1833209991455,-10.770278930664062],[142.11523628234863,-10.66055679321289],[142.26581001281738,-10.683610916137695]]],[[[142.2780475616455,-10.643611907958984],[142.24969673156738,-10.587499618530273],[142.31414985656738,-10.584165573120117],[142.2780475616455,-10.643611907958984]]],[[[142.230806350708,-10.568889617919922],[142.19134712219238,-10.565834045410156],[142.22662544250488,-10.525278091430664],[142.230806350708,-10.568889617919922]]],[[[142.32107734680176,-10.54861068725586],[142.2922077178955,-10.533889770507812],[142.31802558898926,-10.51388931274414],[142.32107734680176,-10.54861068725586]]],[[[142.28552436828613,-10.26472282409668],[142.2258014678955,-10.146112442016602],[142.3305377960205,-10.171945571899414],[142.28552436828613,-10.26472282409668]]],[[[142.15774726867676,-10.189722061157227],[142.089693069458,-10.133890151977539],[142.14358711242676,-10.051666259765625],[142.15774726867676,-10.189722061157227]]]]}},{"type":"Feature","properties":{"name":"Bahrain","iso2":"BH","iso3":"BHR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[50.812492000000105,25.64222],[50.782219,25.65944300000011],[50.821388,25.651943],[50.812492000000105,25.64222]]],[[[50.813332,25.678608],[50.804161,25.680553],[50.807777,25.68972],[50.813332,25.678608]]],[[[50.76194000000012,25.595276],[50.741661000000164,25.683052],[50.796661,25.72833300000012],[50.76194000000012,25.595276]]],[[[50.769722,25.746944],[50.760551000000106,25.750275],[50.764717000000104,25.75471900000015],[50.769722,25.746944]]],[[[50.532219,26.234444],[50.57333,25.809723],[50.46166200000019,25.965275],[50.532219,26.234444]]],[[[50.6536100000001,26.247498],[50.604439,26.267776],[50.62722,26.288887],[50.6536100000001,26.247498]]]]}},{"type":"Feature","properties":{"name":"Barbados","iso2":"BB","iso3":"BRB"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-59.533058,13.050554],[-59.641113,13.331388],[-59.429169,13.164999],[-59.533058,13.050554]]]]}},{"type":"Feature","properties":{"name":"Bermuda","iso2":"BM","iso3":"BMU"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-64.855835,32.278610000000114],[-64.874451,32.293053],[-64.838058,32.314163000000136],[-64.855835,32.278610000000114]]],[[[-64.643341,32.35443900000014],[-64.685837,32.357216],[-64.6552889999999,32.370827],[-64.643341,32.35443900000014]]],[[[-64.78334,32.270554],[-64.858269,32.266796],[-64.671677,32.379997],[-64.78334,32.270554]]]]}},{"type":"Feature","properties":{"name":"Bahamas","iso2":"BS","iso3":"BHS"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-73.0372314453125,21.13944435119629],[-73.68583679199219,20.935556411743164],[-73.02444458007812,21.33249855041504],[-73.0372314453125,21.13944435119629]]],[[[-72.92472839355469,21.483610153198242],[-73.03807067871094,21.434999465942383],[-73.0675048828125,21.507776260375977],[-72.92472839355469,21.483610153198242]]],[[[-72.82917785644531,22.38222312927246],[-72.78140258789062,22.28416633605957],[-73.16473388671875,22.370832443237305],[-72.82917785644531,22.38222312927246]]],[[[-73.61029052734375,22.579721450805664],[-73.62055969238281,22.599721908569336],[-73.59834289550781,22.614721298217773],[-73.61029052734375,22.579721450805664]]],[[[-73.46278381347656,22.601945877075195],[-73.5513916015625,22.61222267150879],[-73.49778747558594,22.6188907623291],[-73.46278381347656,22.601945877075195]]],[[[-74.37779235839844,22.538888931274414],[-74.37945556640625,22.576387405395508],[-74.28001403808594,22.662500381469727],[-74.37779235839844,22.538888931274414]]],[[[-73.84722900390625,22.72361183166504],[-73.86750793457031,22.469446182250977],[-74.28140258789062,22.17305564880371],[-73.84722900390625,22.72361183166504]]],[[[-74.07362365722656,22.663331985473633],[-74.34390258789062,22.83500099182129],[-74.01779174804688,22.71639060974121],[-74.07362365722656,22.663331985473633]]],[[[-73.72889709472656,23.070554733276367],[-73.81361389160156,23.09694480895996],[-73.66500854492188,23.08888816833496],[-73.72889709472656,23.070554733276367]]],[[[-75.55111694335938,23.4313907623291],[-75.52500915527344,23.404443740844727],[-75.65084838867188,23.45583152770996],[-75.55111694335938,23.4313907623291]]],[[[-75.02139282226562,23.10638999938965],[-75.30751037597656,23.667776107788086],[-74.83056640625,22.8608341217041],[-75.02139282226562,23.10638999938965]]],[[[-75.77195739746094,23.499723434448242],[-75.99111938476562,23.599443435668945],[-76.02862358093262,23.67249870300293],[-75.77195739746094,23.499723434448242]]],[[[-74.78195190429688,23.683889389038086],[-74.81973266601562,23.63944435119629],[-74.94862365722656,23.685277938842773],[-74.78195190429688,23.683889389038086]]],[[[-76.3638916015625,24.072221755981445],[-76.32167053222656,23.972776412963867],[-76.39834594726562,24.113332748413086],[-76.3638916015625,24.072221755981445]]],[[[-74.49028015136719,23.954442977905273],[-74.52694702148438,24.100831985473633],[-74.46084594726562,24.142778396606445],[-74.49028015136719,23.954442977905273]]],[[[-77.94667053222656,24.149999618530273],[-77.9716796875,24.1936092376709],[-77.80029296875,24.253332138061523],[-77.94667053222656,24.149999618530273]]],[[[-77.93667602539062,24.225831985473633],[-78.01945495605469,24.25083351135254],[-77.93112182617188,24.279443740844727],[-77.93667602539062,24.225831985473633]]],[[[-76.46890258789062,24.21000099182129],[-76.50361633300781,24.2177791595459],[-76.5452880859375,24.2902774810791],[-76.46890258789062,24.21000099182129]]],[[[-77.73556518554688,24.02861213684082],[-77.60667419433594,24.21388816833496],[-77.56695556640625,23.739168167114258],[-77.87667846679688,24.073057174682617],[-77.6763916015625,24.296110153198242],[-77.73556518554688,24.02861213684082]]],[[[-77.68695068359375,24.337221145629883],[-77.80667114257812,24.31972312927246],[-77.70333862304688,24.369722366333008],[-77.68695068359375,24.337221145629883]]],[[[-75.31472778320312,24.21388816833496],[-75.5150146484375,24.13972282409668],[-75.73945617675781,24.69500160217285],[-75.31472778320312,24.21388816833496]]],[[[-77.4364013671875,25.008054733276367],[-77.5614013671875,25.027498245239258],[-77.25862121582031,25.0494441986084],[-77.4364013671875,25.008054733276367]]],[[[-78.19195556640625,25.203611373901367],[-77.7166748046875,24.50666618347168],[-78.02139282226562,24.27277946472168],[-78.44056701660156,24.613611221313477],[-78.19277954101562,24.597501754760742],[-78.19195556640625,25.203611373901367]]],[[[-76.53334045410156,25.398332595825195],[-76.34970092773438,25.34328269958496],[-76.11889457702637,25.1311092376709],[-76.1683349609375,24.690000534057617],[-76.17167663574219,25.140832901000977],[-76.3558349609375,25.318334579467773],[-76.71583557128906,25.441667556762695],[-76.73529052734375,25.559167861938477],[-76.53334045410156,25.398332595825195]]],[[[-77.82194519042969,25.70222282409668],[-77.8880615234375,25.785001754760742],[-77.85639953613281,25.775278091430664],[-77.82194519042969,25.70222282409668]]],[[[-77.56333923339844,26.268888473510742],[-77.572509765625,26.336111068725586],[-77.5372314453125,26.306943893432617],[-77.56333923339844,26.268888473510742]]],[[[-77.917236328125,26.74527931213379],[-78.7086181640625,26.489721298217773],[-78.97889709472656,26.695276260375977],[-77.917236328125,26.74527931213379]]],[[[-77.73500061035156,26.914445877075195],[-77.042236328125,26.50889015197754],[-77.20472717285156,25.880834579467773],[-77.39805603027344,26.02638816833496],[-77.14889526367188,26.548887252807617],[-77.95028686523438,26.89777946472168],[-77.73500061035156,26.914445877075195]]]]}},{"type":"Feature","properties":{"name":"Bangladesh","iso2":"BD","iso3":"BGD"},"geometry":{"type":"MultiPolygon","coordinates":[[[[91.89749336242676,21.47666358947754],[91.88109016418457,21.755277633666992],[91.98221015930176,21.62388801574707],[91.89749336242676,21.47666358947754]]],[[[90.49054145812988,21.80360984802246],[90.46748542785645,21.820554733276367],[90.49275398254395,21.814443588256836],[90.49054145812988,21.80360984802246]]],[[[90.43248176574707,21.819997787475586],[90.41276741027832,21.823610305786133],[90.4527759552002,21.85027503967285],[90.43248176574707,21.819997787475586]]],[[[89.12664985656738,21.714162826538086],[89.05053901672363,21.91472053527832],[89.1463794708252,21.748884201049805],[89.12664985656738,21.714162826538086]]],[[[90.75305366516113,21.891942977905273],[90.74443244934082,21.92249870300293],[90.76220893859863,21.90638542175293],[90.75305366516113,21.891942977905273]]],[[[91.83276557922363,21.722219467163086],[91.86303901672363,21.92805290222168],[91.88638496398926,21.842775344848633],[91.83276557922363,21.722219467163086]]],[[[90.64387702941895,21.90610694885254],[90.63333320617676,21.930551528930664],[90.6655445098877,21.95555305480957],[90.64387702941895,21.90610694885254]]],[[[90.69914436340332,21.9547176361084],[90.67526435852051,21.94999885559082],[90.69053840637207,21.9727725982666],[90.69914436340332,21.9547176361084]]],[[[90.52249336242676,21.855833053588867],[90.51971626281738,21.9355525970459],[90.58831977844238,21.981386184692383],[90.52249336242676,21.855833053588867]]],[[[90.41081428527832,21.899442672729492],[90.43026924133301,22.04222297668457],[90.48498725891113,21.964998245239258],[90.41081428527832,21.899442672729492]]],[[[90.37414741516113,22.010000228881836],[90.34166145324707,21.966386795043945],[90.3802661895752,22.050554275512695],[90.37414741516113,22.010000228881836]]],[[[90.52360725402832,21.991106033325195],[90.48692512512207,22.078886032104492],[90.6121997833252,22.16388511657715],[90.52360725402832,21.991106033325195]]],[[[90.51693916320801,22.16221809387207],[90.51220893859863,22.171110153198242],[90.52777290344238,22.179441452026367],[90.51693916320801,22.16221809387207]]],[[[90.93748664855957,22.112775802612305],[90.91470527648926,22.131940841674805],[90.95221138000488,22.209440231323242],[90.93748664855957,22.112775802612305]]],[[[90.98498725891113,22.182497024536133],[90.97192573547363,22.24083137512207],[90.99165534973145,22.259164810180664],[90.98498725891113,22.182497024536133]]],[[[90.94941902160645,22.221384048461914],[90.97638130187988,22.35777473449707],[90.98858833312988,22.286943435668945],[90.94941902160645,22.221384048461914]]],[[[91.00583076477051,22.36805534362793],[90.98526191711426,22.38527488708496],[90.98997688293457,22.41416358947754],[91.00583076477051,22.36805534362793]]],[[[90.66026496887207,22.356386184692383],[90.6402759552002,22.308332443237305],[90.61026191711426,22.451940536499023],[90.66026496887207,22.356386184692383]]],[[[91.03610420227051,22.404996871948242],[91.01805305480957,22.41472053527832],[91.0405445098877,22.4536075592041],[91.03610420227051,22.404996871948242]]],[[[91.21054267883301,22.41221809387207],[91.18553352355957,22.39249610900879],[91.1685962677002,22.46138572692871],[91.21054267883301,22.41221809387207]]],[[[91.00749397277832,22.424997329711914],[90.98776435852051,22.440832138061523],[91.00915718078613,22.47638511657715],[91.00749397277832,22.424997329711914]]],[[[90.66304206848145,22.434995651245117],[90.64749336242676,22.42777442932129],[90.65555000305176,22.478609085083008],[90.66304206848145,22.434995651245117]]],[[[91.03166389465332,22.084165573120117],[91.08804512023926,22.52583122253418],[91.1746997833252,22.21860694885254],[91.03166389465332,22.084165573120117]]],[[[91.52971076965332,22.347776412963867],[91.40832710266113,22.472219467163086],[91.4316577911377,22.62388801574707],[91.52971076965332,22.347776412963867]]],[[[91.33943367004395,22.6299991607666],[91.3177661895752,22.608888626098633],[91.3047046661377,22.628332138061523],[91.33943367004395,22.6299991607666]]],[[[90.76388740539551,22.064443588256836],[90.6010913848877,22.03416633605957],[90.6847095489502,22.39249610900879],[90.64276313781738,22.55305290222168],[90.55693244934082,22.605276107788086],[90.58777046203613,22.771944046020508],[90.87747383117676,22.45722007751465],[90.76388740539551,22.064443588256836]]],[[[90.54721260070801,22.71944236755371],[90.46971321105957,22.868886947631836],[90.69108772277832,22.84694480895996],[90.5416202545166,22.7831974029541],[90.54721260070801,22.71944236755371]]],[[[90.66220283508301,22.956384658813477],[90.63275337219238,22.94916343688965],[90.65609931945801,22.91221809387207],[90.50915718078613,22.951108932495117],[90.57083320617676,23.0402774810791],[90.66220283508301,22.956384658813477]]],[[[90.47747993469238,23.007776260375977],[90.46331977844238,23.05916404724121],[90.51082038879395,23.06194496154785],[90.47747993469238,23.007776260375977]]],[[[90.52971076965332,23.04722023010254],[90.52192878723145,23.054719924926758],[90.54498481750488,23.065275192260742],[90.52971076965332,23.04722023010254]]],[[[90.54081916809082,23.343889236450195],[90.59027290344238,23.302499771118164],[90.4216480255127,23.383054733276367],[90.54081916809082,23.343889236450195]]],[[[90.57361030578613,23.564722061157227],[90.56442451477051,23.57694435119629],[90.58415412902832,23.583887100219727],[90.57361030578613,23.564722061157227]]],[[[88.43304634094238,26.551389694213867],[89.34277534484863,26.017030715942383],[89.7391529083252,26.15638542175293],[89.84526252746582,25.288610458374023],[92.40637397766113,25.030553817749023],[92.12137031555176,24.39333152770996],[91.37329292297363,24.10194206237793],[91.15942573547363,23.640554428100586],[91.61360359191895,22.943052291870117],[91.94999885559082,23.73221778869629],[92.28332710266113,23.70527458190918],[92.60081672668457,21.98221778869629],[92.66934394836426,21.29698371887207],[92.26082038879395,21.41444206237793],[92.26193428039551,21.054311752319336],[92.32361030578613,20.73805046081543],[91.69999885559082,22.48832893371582],[91.4558277130127,22.78999900817871],[90.83360481262207,22.6855525970459],[90.59382820129395,23.59796714782715],[90.30887031555176,23.41444206237793],[90.61248970031738,23.222219467163086],[90.57859992980957,23.089998245239258],[90.44664192199707,23.065000534057617],[90.42440223693848,22.77018928527832],[90.61775398254395,22.3538875579834],[90.44053840637207,22.071664810180664],[90.4013843536377,22.260557174682617],[90.27249336242676,21.849164962768555],[90.02470588684082,21.85999870300293],[90.07304573059082,22.16277503967285],[89.93220710754395,21.997774124145508],[90.00000190734863,22.48375129699707],[89.58110237121582,21.701662063598633],[89.62082099914551,22.32444190979004],[89.24914741516113,21.64249610900879],[89.0630054473877,22.115476608276367],[88.9861011505127,23.208330154418945],[88.56387519836426,23.652219772338867],[88.75053596496582,24.220983505249023],[88.04332160949707,24.68416404724121],[88.4508228302002,25.187776565551758],[89.00943183898926,25.288331985473633],[88.11053657531738,25.835554122924805],[88.43304634094238,26.551389694213867]],[[90.23776435852051,22.192773818969727],[90.06137275695801,21.99177360534668],[90.21609687805176,22.114442825317383],[90.23776435852051,22.192773818969727]],[[90.68498420715332,23.48277473449707],[90.69192695617676,23.497217178344727],[90.65027046203613,23.504167556762695],[90.68498420715332,23.48277473449707]]]]}},{"type":"Feature","properties":{"name":"Belize","iso2":"BZ","iso3":"BLZ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-87.803345,17.294167000000144],[-87.825012,17.291664000000154],[-87.82695,17.400276],[-87.803345,17.294167000000144]]],[[[-87.820557,17.426941],[-87.926682,17.275555],[-87.81945799999988,17.549999],[-87.820557,17.426941]]],[[[-88.045013,17.552776],[-88.070282,17.638332],[-88.053619,17.613052],[-88.045013,17.552776]]],[[[-88.132507,17.667221],[-88.167511,17.66972],[-88.072784,17.73388700000011],[-88.132507,17.667221]]],[[[-87.892227,18.0425],[-88.006119,17.901943000000145],[-87.853058,18.164719],[-87.892227,18.0425]]],[[[-88.377792,18.482777000000127],[-88.2995,18.482929],[-88.077789,18.215553],[-88.281403,17.636108],[-88.208618,16.968609],[-88.910568,15.893610000000123],[-89.216171,15.88985100000015],[-89.141953,17.818886],[-88.377792,18.482777000000127]]]]}},{"type":"Feature","properties":{"name":"Bosnia and Herzegovina","iso2":"BA","iso3":"BIH"},"geometry":{"type":"MultiPolygon","coordinates":[[[[17.649841,42.889076],[17.578526000000124,42.943825],[16.143055,44.19944],[15.786665,45.171944],[18.251942,45.138885],[19.039719,44.861382],[19.371387,44.88916],[19.104443,44.355827],[19.620476,44.048454],[19.237019,44.011009],[19.51083,43.679718],[19.228809,43.513214],[18.699997,43.255554],[18.455555,42.565826],[17.649841,42.889076]]]]}},{"type":"Feature","properties":{"name":"Bolivia","iso2":"BO","iso3":"BOL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-65.190201,-22.09473],[-65.748062,-22.111668],[-66.22300699999988,-21.780521],[-67.183624,-22.821667],[-67.876404,-22.828056],[-68.188614,-21.296947],[-68.756958,-20.406948],[-68.4375,-19.430279],[-68.907791,-19.055279],[-69.071671,-18.038891],[-69.48361199999988,-17.635559],[-69.499725,-17.50528],[-69.618896,-17.214725],[-68.82251,-16.339725],[-69.421951,-15.618057],[-69.136948,-15.245834],[-69.366394,-14.802502],[-68.853058,-14.199167],[-68.974457,-12.869722],[-68.673904,-12.50115],[-69.568436,-10.951092],[-68.58344999999986,-11.106138],[-66.634445,-9.906946],[-65.381958,-9.697779],[-65.392792,-11.26639],[-64.991669,-12.008057],[-64.39418,-12.461668],[-63.07500499999989,-12.650002],[-61.833893,-13.544724],[-61.038979,-13.493118],[-60.470839999999896,-13.807222],[-60.258896,-15.093613],[-60.571396,-15.097502],[-60.160278,-16.263058],[-58.327507,-16.279167],[-58.397507,-17.249168],[-57.743057,-17.593056],[-57.521118,-18.203892],[-58.121117,-19.74139],[-57.84874699999989,-19.978794],[-58.15889,-20.168056],[-58.15139,-19.828056],[-59.09584,-19.348892],[-61.7425,-19.645],[-62.643768,-22.238903],[-62.811951,-21.996948],[-63.941116,-22.000835],[-64.324722,-22.873611],[-64.590561,-22.214725],[-65.190201,-22.09473]]]]}},{"type":"Feature","properties":{"name":"Burma","iso2":"MM","iso3":"MMR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[98.0358120000001,9.786386],[98.024994,9.838331],[98.060257,9.81361],[98.0358120000001,9.786386]]],[[[98.29332000000014,10.010277],[98.116089,9.852497],[98.17858900000013,10.017776],[98.29332000000014,10.010277]]],[[[98.186646,10.040276],[98.19859300000022,10.189999],[98.238876,10.165833],[98.186646,10.040276]]],[[[97.907486,10.396944000000133],[97.903595,10.490831],[97.942749,10.442776],[97.907486,10.396944000000133]]],[[[98.216385,10.481386],[98.1824800000002,10.5075],[98.238876,10.529999],[98.216385,10.481386]]],[[[98.52360500000012,10.781666],[98.486923,10.883053],[98.550812,10.850275],[98.52360500000012,10.781666]]],[[[97.919708,10.858332],[97.885818,10.843609],[97.91609200000019,10.929443],[97.919708,10.858332]]],[[[98.21220400000018,10.947777000000102],[98.264435,10.68972],[98.075546,10.88611],[98.21220400000018,10.947777000000102]]],[[[98.437195,10.961943000000161],[98.42997700000015,10.995831],[98.452774,11.007776],[98.437195,10.961943000000161]]],[[[98.533875,10.950554],[98.470535,10.983887],[98.524994,11.087219000000147],[98.533875,10.950554]]],[[[98.25610400000019,11.212498],[98.23109400000013,11.262499],[98.27777100000012,11.276388],[98.25610400000019,11.212498]]],[[[98.20748900000015,11.443609000000109],[98.289154,11.798609],[98.28082300000014,11.481665000000106],[98.20748900000015,11.443609000000109]]],[[[98.49832200000012,11.566109],[98.3713680000001,11.78611],[98.548874,11.788332],[98.49832200000012,11.566109]]],[[[97.48719800000012,11.774443000000133],[97.43775900000011,11.803331],[97.4616550000002,11.803053],[97.48719800000012,11.774443000000133]]],[[[98.089981,11.631109000000109],[98.033051,11.683054000000169],[98.007217,11.858332],[98.089981,11.631109000000109]]],[[[97.66832,11.836943],[97.633881,11.876108],[97.664429,11.901110000000102],[97.66832,11.836943]]],[[[98.271103,11.84972],[98.260269,11.907221],[98.28804,11.887499000000133],[98.271103,11.84972]]],[[[98.256378,11.92111],[98.226379,11.94972],[98.251663,11.980276],[98.256378,11.92111]]],[[[98.5,11.884443],[98.438583,12.111387],[98.664993,11.941942],[98.5,11.884443]]],[[[98.14193700000013,12.141943],[98.05554200000014,12.281111],[98.124695,12.27861],[98.14193700000013,12.141943]]],[[[98.64082300000021,12.372219],[98.619141,12.378885000000153],[98.639709,12.380552],[98.64082300000021,12.372219]]],[[[98.61780500000012,12.352951],[98.68248,12.340553],[98.55970800000014,12.328886],[98.540817,12.370552],[98.57193,12.409164],[98.61780500000012,12.352951]]],[[[98.09166,12.360554],[98.00555400000022,12.281942],[97.937485,12.337498],[98.09166,12.360554]]],[[[98.501099,12.402222],[98.471924,12.417776000000146],[98.49887100000015,12.513887],[98.501099,12.402222]]],[[[98.285812,12.502499000000114],[98.24331700000019,12.49222],[98.229706,12.548054000000107],[98.285812,12.502499000000114]]],[[[97.853592,12.539999000000122],[97.817764,12.583332000000112],[97.837494,12.598053],[97.853592,12.539999000000122]]],[[[98.349426,12.316942000000111],[98.32193000000015,12.67111],[98.46693400000018,12.570831],[98.349426,12.316942000000111]]],[[[97.872208,12.764166000000131],[97.83728,12.772419000000156],[97.84414700000016,12.819443],[97.872208,12.764166000000131]]],[[[98.304153,13.041666000000106],[98.29803500000017,12.941387],[98.23942600000012,13.213331],[98.304153,13.041666000000106]]],[[[97.92109700000012,13.783054],[97.921921,13.861664000000161],[97.934708,13.851664],[97.92109700000012,13.783054]]],[[[97.924423,13.905832],[97.92303500000017,13.894444],[97.91835,13.93908100000013],[97.924423,13.905832]]],[[[93.380539,14.064165],[93.38638300000017,14.151665],[93.4008180000001,14.096109],[93.380539,14.064165]]],[[[97.80636600000011,14.134443],[97.78915400000014,14.155277],[97.814148,14.179998000000126],[97.80636600000011,14.134443]]],[[[93.722488,14.904444],[93.679153,14.848331],[93.6922,14.890833],[93.722488,14.904444]]],[[[97.669708,15.521387],[97.66304,15.497219],[97.65416,15.578331],[97.669708,15.521387]]],[[[94.79776000000012,15.791666],[94.728043,15.815275],[94.82054100000013,15.948053],[94.79776000000012,15.791666]]],[[[94.583328,16.00972],[94.415817,15.868053000000103],[94.38665800000015,15.995831],[94.649429,16.245274],[94.583328,16.00972]]],[[[97.569153,16.233604],[97.515549,16.506107],[97.616653,16.465271000000158],[97.569153,16.233604]]],[[[93.67109700000017,18.867496000000145],[93.703049,18.668053],[93.48442100000014,18.869717],[93.67109700000017,18.867496000000145]]],[[[93.79092400000016,19.231342],[93.94220000000021,18.862495],[93.49054000000015,19.400829],[93.79092400000016,19.231342]]],[[[93.801651,19.268608],[93.682755,19.560555],[93.96832300000014,19.42083],[93.801651,19.268608]]],[[[93.51304600000017,19.744438],[93.395828,19.955273],[93.498596,19.88055],[93.51304600000017,19.744438]]],[[[93.024429,19.827774000000105],[92.912491,20.086662],[92.954437,20.06361],[93.024429,19.827774000000105]]],[[[97.806641,28.344162],[98.316376,27.541943],[98.699707,27.539165],[98.77832,26.636383],[98.710815,25.855553],[97.5524750000001,24.74305],[97.759995,24.257496],[97.535538,23.939716],[98.890732,24.16006900000015],[98.6772,23.968052],[98.927475,23.189163000000107],[99.566376,22.938049],[99.162766,22.159161],[99.964432,22.048885],[100.212753,21.432552],[101.10526300000018,21.771385],[101.14823900000013,21.572636],[100.09137,20.348606],[100.08132200000014,20.348841],[99.522766,20.352776000000134],[98.995529,19.780552],[98.049988,19.807499000000135],[97.774704,18.569996],[97.346375,18.562496000000138],[98.68969700000011,16.284996],[98.92804,16.38583],[98.201096,15.074999],[99.173965,13.727781],[99.112198,13.055832],[99.661652,11.826942],[98.742752,10.348608],[98.54664600000015,9.981665],[98.46026600000019,10.734442],[98.710815,10.918331],[98.743591,11.666943000000117],[98.890549,11.700275],[98.597488,11.751665],[98.72192400000014,11.976109],[98.705872,12.224465],[98.533165,12.245721],[98.70359000000022,12.340046],[98.583328,13.172775],[98.18553200000011,14.059164000000138],[98.13888500000016,13.539721],[97.797256,14.881962],[97.737488,16.563885],[97.378036,16.494995],[96.87803600000021,17.449997],[96.77777100000017,16.703884000000116],[96.3797,16.501389],[96.241928,16.803734],[96.268326,16.389717000000147],[95.42858900000013,15.729719],[95.3608090000001,16.144718],[95.216385,15.782776000000112],[95.13720700000013,16.137218],[94.848877,15.77972],[94.99081400000014,16.246662000000114],[94.650543,15.854164],[94.793045,16.153606],[94.560257,15.941942],[94.679703,16.115829],[94.631088,16.34277300000015],[94.24552900000018,15.959997],[94.6147,17.546387],[93.99192800000017,19.457218],[93.599152,19.719715],[93.728592,19.931664],[93.128311,20.085552],[93.12997400000015,19.835552000000106],[93.081665,20.548607],[92.860809,20.121109],[92.261932,21.05431],[92.26081800000011,21.41444000000014],[92.669342,21.296982],[92.600815,21.982216],[93.19664,22.256386],[93.33873,24.077915],[94.151093,23.855274],[94.734421,25.024719],[94.6255340000001,25.397774],[95.17804,26.058887],[95.141373,26.612495000000123],[96.194138,27.270832],[97.13665800000015,27.085831],[96.886658,27.60610600000011],[97.3488770000001,28.222771],[97.555252,28.548054000000107],[97.806641,28.344162]]]]}},{"type":"Feature","properties":{"name":"Benin","iso2":"BJ","iso3":"BEN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[2.484418,6.340486],[1.635404,6.218721],[1.398542,9.429901],[1.355,9.995277],[0.776667,10.376665],[0.91797,10.996399],[1.435278,11.458887],[2.014722,11.422499],[2.397925,11.896152],[2.378054,12.240274],[2.83862,12.396658],[3.604459,11.693274],[3.855,10.584999],[3.095,9.090555],[2.789444,9.043888],[2.719606,6.365505],[2.484418,6.340486]]]]}},{"type":"Feature","properties":{"name":"Solomon Islands","iso2":"SB","iso3":"SLB"},"geometry":{"type":"MultiPolygon","coordinates":[[[[166.85052680969238,-11.696945190429688],[166.76138496398926,-11.579444885253906],[166.93191719055176,-11.66722297668457],[166.85052680969238,-11.696945190429688]]],[[[160.08081245422363,-11.498054504394531],[160.52746772766113,-11.808055877685547],[159.960786819458,-11.521665573120117],[160.08081245422363,-11.498054504394531]]],[[[159.85330390930176,-11.324722290039062],[159.77664375305176,-11.288612365722656],[159.841646194458,-11.303888320922852],[159.85330390930176,-11.324722290039062]]],[[[166.535249710083,-11.363887786865234],[166.5180377960205,-11.271112442016602],[166.5805377960205,-11.324167251586914],[166.535249710083,-11.363887786865234]]],[[[162.47497749328613,-10.855554580688477],[162.48135566711426,-10.807500839233398],[162.50055122375488,-10.84000015258789],[162.47497749328613,-10.855554580688477]]],[[[166.139986038208,-10.761112213134766],[165.77746772766113,-10.805000305175781],[165.904146194458,-10.67361068725586],[166.139986038208,-10.761112213134766]]],[[[161.545259475708,-10.276666641235352],[162.39081001281738,-10.841943740844727],[161.28332710266113,-10.33194351196289],[161.545259475708,-10.276666641235352]]],[[[161.75137519836426,-10.294445037841797],[161.71997261047363,-10.2147216796875],[161.77191352844238,-10.254446029663086],[161.75137519836426,-10.294445037841797]]],[[[167.20385932922363,-9.963611602783203],[167.18829536437988,-9.942222595214844],[167.20800971984863,-9.95083236694336],[167.20385932922363,-9.963611602783203]]],[[[167.12774848937988,-9.88083267211914],[167.108003616333,-9.869165420532227],[167.12634468078613,-9.86722183227539],[167.12774848937988,-9.88083267211914]]],[[[167.10330390930176,-9.851663589477539],[167.08941841125488,-9.84749984741211],[167.10858345031738,-9.84083366394043],[167.10330390930176,-9.851663589477539]]],[[[161.97467231750488,-9.85305404663086],[161.94470405578613,-9.690277099609375],[161.97412300109863,-9.689722061157227],[161.97467231750488,-9.85305404663086]]],[[[161.56912422180176,-9.724166870117188],[161.39721870422363,-9.669445037841797],[161.34997749328613,-9.338888168334961],[161.56912422180176,-9.724166870117188]],[[161.38748359680176,-9.468610763549805],[161.38553047180176,-9.454444885253906],[161.38134956359863,-9.469444274902344],[161.38748359680176,-9.468610763549805]]],[[[159.93829536437988,-9.433610916137695],[160.38638496398926,-9.426666259765625],[160.83108711242676,-9.861944198608398],[159.82803535461426,-9.796945571899414],[159.601900100708,-9.317222595214844],[159.93829536437988,-9.433610916137695]]],[[[159.8285846710205,-9.172500610351562],[159.811372756958,-9.110832214355469],[159.845796585083,-9.138055801391602],[159.8285846710205,-9.172500610351562]]],[[[160.4111042022705,-9.136667251586914],[160.21246528625488,-9.170555114746094],[160.3185749053955,-9.060277938842773],[160.4111042022705,-9.136667251586914]]],[[[159.20440864562988,-9.133333206176758],[159.16803169250488,-9.102775573730469],[159.22830390930176,-9.025556564331055],[159.20440864562988,-9.133333206176758]]],[[[159.14749336242676,-9.108888626098633],[159.03247261047363,-9.060277938842773],[159.13720893859863,-8.994443893432617],[159.14749336242676,-9.108888626098633]]],[[[160.11218452453613,-8.997220993041992],[160.06579780578613,-9.017499923706055],[160.07330513000488,-8.947778701782227],[160.11218452453613,-8.997220993041992]]],[[[160.047212600708,-8.915275573730469],[160.00833320617676,-8.884723663330078],[160.02942085266113,-8.880277633666992],[160.047212600708,-8.915275573730469]]],[[[161.06079292297363,-8.748054504394531],[161.04443550109863,-8.772500991821289],[161.00943183898926,-8.754167556762695],[161.06079292297363,-8.748054504394531]]],[[[157.633882522583,-8.748054504394531],[157.619966506958,-8.800832748413086],[157.44384956359863,-8.71500015258789],[157.633882522583,-8.748054504394531]]],[[[158.20523262023926,-8.833332061767578],[158.14972114562988,-8.781389236450195],[158.2135944366455,-8.681112289428711],[158.20523262023926,-8.833332061767578]]],[[[158.00305366516113,-8.771112442016602],[157.87552070617676,-8.60999870300293],[158.1169147491455,-8.533332824707031],[158.00305366516113,-8.771112442016602]]],[[[157.40832710266113,-8.500833511352539],[157.38443183898926,-8.734443664550781],[157.19912910461426,-8.565834045410156],[157.40832710266113,-8.500833511352539]]],[[[159.6833209991455,-8.546945571899414],[159.53747749328613,-8.468332290649414],[159.56884956359863,-8.378887176513672],[159.6833209991455,-8.546945571899414]]],[[[162.741060256958,-8.37388801574707],[162.76165962219238,-8.378055572509766],[162.72525215148926,-8.381387710571289],[162.741060256958,-8.37388801574707]]],[[[160.97439765930176,-8.84749984741211],[161.378023147583,-9.635000228881836],[160.58026313781738,-8.329999923706055],[160.97439765930176,-8.84749984741211]]],[[[157.12466621398926,-8.255279541015625],[157.15136909484863,-8.342777252197266],[157.023042678833,-8.190834045410156],[157.12466621398926,-8.255279541015625]]],[[[157.20746040344238,-8.270278930664062],[157.09247016906738,-8.165834426879883],[157.18081855773926,-8.170555114746094],[157.20746040344238,-8.270278930664062]]],[[[156.84497261047363,-8.118331909179688],[156.78332710266113,-8.098054885864258],[156.78274726867676,-8.055278778076172],[156.84497261047363,-8.118331909179688]]],[[[157.63162422180176,-8.236387252807617],[157.81192207336426,-8.620832443237305],[157.21441841125488,-8.24305534362793],[157.49746894836426,-7.965555191040039],[157.63162422180176,-8.236387252807617]]],[[[156.5988483428955,-8.203054428100586],[156.53192329406738,-8.091943740844727],[156.5422077178955,-7.944721221923828],[156.5988483428955,-8.203054428100586]]],[[[157.156099319458,-8.150278091430664],[156.9677448272705,-8.046388626098633],[157.027193069458,-7.865276336669922],[157.156099319458,-8.150278091430664]]],[[[158.57190132141113,-7.703611373901367],[158.5321979522705,-7.691387176513672],[158.54998970031738,-7.664165496826172],[158.57190132141113,-7.703611373901367]]],[[[158.53082466125488,-7.654167175292969],[158.35940742492676,-7.640556335449219],[158.31274604797363,-7.580833435058594],[158.53082466125488,-7.654167175292969]]],[[[156.706636428833,-7.897222518920898],[156.5544147491455,-7.578611373901367],[156.80859565734863,-7.726665496826172],[156.706636428833,-7.897222518920898]]],[[[159.85244941711426,-8.33388900756836],[159.8869342803955,-8.566389083862305],[158.48745918273926,-7.554166793823242],[159.85244941711426,-8.33388900756836]]],[[[158.4294147491455,-7.529722213745117],[158.37051582336426,-7.552776336669922],[158.26275825500488,-7.477499008178711],[158.4294147491455,-7.529722213745117]]],[[[157.78164863586426,-7.476110458374023],[157.68359565734863,-7.415555953979492],[157.74939155578613,-7.393888473510742],[157.78164863586426,-7.476110458374023]]],[[[155.58746528625488,-7.390556335449219],[155.51080513000488,-7.351110458374023],[155.5846881866455,-7.331943511962891],[155.58746528625488,-7.390556335449219]]],[[[155.8588581085205,-7.100276947021484],[155.66971015930176,-7.088054656982422],[155.74023628234863,-6.967498779296875],[155.8588581085205,-7.100276947021484]]],[[[156.11023139953613,-6.941110610961914],[156.08496284484863,-6.989442825317383],[156.0746784210205,-6.81916618347168],[156.11023139953613,-6.941110610961914]]],[[[156.0199909210205,-6.824722290039063],[156.00000190734863,-6.803609848022461],[156.045259475708,-6.788610458374023],[156.0199909210205,-6.824722290039063]]],[[[157.42886543273926,-7.324443817138672],[156.93609809875488,-7.219165802001953],[156.438570022583,-6.643611907958984],[157.42886543273926,-7.324443817138672]]],[[[159.712739944458,-5.516666412353516],[159.71414375305176,-5.483888626098633],[159.7238483428955,-5.489999771118164],[159.712739944458,-5.516666412353516]]],[[[159.52859687805176,-5.49888801574707],[159.49633979797363,-5.466943740844727],[159.5099811553955,-5.470832824707031],[159.52859687805176,-5.49888801574707]]],[[[159.40387153625488,-5.448331832885742],[159.37161445617676,-5.440832138061523],[159.3488483428955,-5.41583251953125],[159.40387153625488,-5.448331832885742]]],[[[159.25219917297363,-5.312778472900391],[159.25027656555176,-5.324167251586914],[159.24884223937988,-5.293054580688477],[159.25219917297363,-5.312778472900391]]]]}},{"type":"Feature","properties":{"name":"Brazil","iso2":"BR","iso3":"BRA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-48.550559997558594,-27.821392059326172],[-48.51722717285156,-27.430835723876953],[-48.4183349609375,-27.38888931274414],[-48.550559997558594,-27.821392059326172]]],[[[-48.58111572265625,-26.39167022705078],[-48.70777893066406,-26.309722900390625],[-48.53778076171875,-26.167224884033203],[-48.58111572265625,-26.39167022705078]]],[[[-48.282501220703125,-25.486114501953125],[-48.33306121826172,-25.41305923461914],[-48.25666809082031,-25.338890075683594],[-48.282501220703125,-25.486114501953125]]],[[[-47.877784729003906,-25.026947021484375],[-47.816673278808594,-24.900001525878906],[-47.60667419433594,-24.783611297607422],[-47.877784729003906,-25.026947021484375]]],[[[-46.28278350830078,-23.98917007446289],[-46.41638946533203,-23.950279235839844],[-46.32361602783203,-23.93000030517578],[-46.28278350830078,-23.98917007446289]]],[[[-45.12639617919922,-23.821392059326172],[-45.136390686035156,-23.797779083251953],[-45.105003356933594,-23.806392669677734],[-45.12639617919922,-23.821392059326172]]],[[[-45.22084045410156,-23.77944564819336],[-45.21833801269531,-23.955833435058594],[-45.44139099121094,-23.928890228271484],[-45.22084045410156,-23.77944564819336]]],[[[-44.088890075683594,-23.17444610595703],[-44.369171142578125,-23.172225952148438],[-44.228614807128906,-23.07111358642578],[-44.088890075683594,-23.17444610595703]]],[[[-29.84000015258789,-20.49639129638672],[-29.848892211914062,-20.500835418701172],[-29.852222442626953,-20.491111755371094],[-29.84000015258789,-20.49639129638672]]],[[[-30.29528045654297,-20.505834579467773],[-30.319446563720703,-20.520000457763672],[-30.334165573120117,-20.482223510742188],[-30.29528045654297,-20.505834579467773]]],[[[-38.91166687011719,-13.67527961730957],[-38.99195098876953,-13.593055725097656],[-38.91278076171875,-13.587501525878906],[-38.91166687011719,-13.67527961730957]]],[[[-38.93695068359375,-13.5625],[-38.98445129394531,-13.5625],[-38.96444320678711,-13.498844146728516],[-39.041114807128906,-13.462223052978516],[-39.038612365722656,-13.39777946472168],[-38.908058166503906,-13.385557174682617],[-38.93695068359375,-13.5625]]],[[[-38.754722595214844,-13.113056182861328],[-38.643333435058594,-12.892223358154297],[-38.59166717529297,-12.98750114440918],[-38.754722595214844,-13.113056182861328]]],[[[-37.13250732421875,-11.129446029663086],[-37.146392822265625,-11.108612060546875],[-37.036949157714844,-10.95250129699707],[-37.13250732421875,-11.129446029663086]]],[[[-34.87389373779297,-7.073333740234375],[-34.888893127441406,-7.071945190429688],[-34.866668701171875,-7.048610687255859],[-34.87389373779297,-7.073333740234375]]],[[[-34.85417175292969,-7.005277633666992],[-34.863059997558594,-7.013889312744141],[-34.85972595214844,-6.994443893432617],[-34.85417175292969,-7.005277633666992]]],[[[-32.450836181640625,-3.883609771728516],[-32.424171447753906,-3.845832824707031],[-32.38667297363281,-3.840276718139648],[-32.450836181640625,-3.883609771728516]]],[[[-44.61028289794922,-3.008054733276367],[-44.65611267089844,-2.973609924316406],[-44.611671447753906,-2.887222290039063],[-44.61028289794922,-3.008054733276367]]],[[[-44.586395263671875,-3.052499771118164],[-44.57750701904297,-2.801944732666016],[-44.48389434814453,-2.709999084472656],[-44.586395263671875,-3.052499771118164]]],[[[-42.05083465576172,-2.761667251586914],[-42.1844482421875,-2.677499771118164],[-42.06945037841797,-2.685832977294922],[-42.05083465576172,-2.761667251586914]]],[[[-43.69333457946777,-2.326944351196289],[-43.739173889160156,-2.350276947021484],[-43.61528015136719,-2.26249885559082],[-43.69333457946777,-2.326944351196289]]],[[[-50.8638916015625,-1.910833358764648],[-50.988059997558594,-1.993610382080078],[-51.148338317871094,-1.828611373901367],[-50.8638916015625,-1.910833358764648]]],[[[-49.024169921875,-1.829166412353516],[-49.156951904296875,-1.858055114746094],[-49.05555725097656,-1.721111297607422],[-49.024169921875,-1.829166412353516]]],[[[-48.96111297607422,-1.795831680297852],[-49.046112060546875,-1.705278396606445],[-48.90277862548828,-1.577220916748047],[-48.96111297607422,-1.795831680297852]]],[[[-44.65277862548828,-1.62388801574707],[-44.66222381591797,-1.661945343017578],[-44.778892517089844,-1.668054580688477],[-44.78334045410156,-1.619167327880859],[-44.71305847167969,-1.561111450195313],[-44.65277862548828,-1.62388801574707]]],[[[-52.02472686767578,-1.580278396606445],[-52.200836181640625,-1.646665573120117],[-52.029449462890625,-1.439722061157227],[-51.914451599121094,-1.516387939453125],[-52.02472686767578,-1.580278396606445]]],[[[-52.4183349609375,-1.527500152587891],[-52.431114196777344,-1.466388702392578],[-52.168617248535156,-1.408332824707031],[-52.4183349609375,-1.527500152587891]]],[[[-48.63361358642578,-1.484722137451172],[-48.69667053222656,-1.449167251586914],[-48.657501220703125,-1.375833511352539],[-48.63361358642578,-1.484722137451172]]],[[[-48.525840759277344,-1.524999618530273],[-48.592506408691406,-1.442220687866211],[-48.55333709716797,-1.366109848022461],[-48.525840759277344,-1.524999618530273]]],[[[-44.98750305175781,-1.401945114135742],[-44.975563049316406,-1.261667251586914],[-44.88111114501953,-1.283056259155273],[-44.98750305175781,-1.401945114135742]]],[[[-45.63417053222656,-1.34638786315918],[-45.689443588256836,-1.360832214355469],[-45.626943588256836,-1.126943588256836],[-45.63417053222656,-1.34638786315918]]],[[[-48.34027862548828,-1.212778091430664],[-48.46556091308594,-1.162776947021484],[-48.41222381591797,-1.07499885559082],[-48.32250213623047,-1.076944351196289],[-48.34027862548828,-1.212778091430664]]],[[[-46.49889373779297,-1.02027702331543],[-46.53334045410156,-1.017499923706055],[-46.54833984375,-0.972221374511719],[-46.45667266845703,-0.88861083984375],[-46.44000244140625,-1.006387710571289],[-46.49889373779297,-1.02027702331543]]],[[[-50.98722839355469,-0.866388320922852],[-50.92083740234375,-0.869722366333008],[-51.01261901855469,-0.919502258300781],[-51.019447326660156,-0.991666793823242],[-51.070037841796875,-1.03779411315918],[-51.18250274658203,-1.091667175292969],[-50.98722839355469,-0.866388320922852]]],[[[-51.375282287597656,-1.21360969543457],[-51.40028381347656,-1.201944351196289],[-51.363616943359375,-1.129444122314453],[-51.24889373779297,-1.024721145629883],[-51.20305633544922,-0.841667175292969],[-51.23944854736328,-1.143888473510742],[-51.375282287597656,-1.21360969543457]]],[[[-50.92028045654297,-0.844999313354492],[-50.92278289794922,-0.729166030883789],[-50.84278106689453,-0.727777481079102],[-50.92028045654297,-0.844999313354492]]],[[[-47.93500518798828,-0.727222442626953],[-47.95166778564453,-0.731945037841797],[-47.97084045410156,-0.680000305175781],[-47.93250274658203,-0.636667251586914],[-47.87611389160156,-0.673055648803711],[-47.93500518798828,-0.727222442626953]]],[[[-47.668060302734375,-0.709165573120117],[-47.69667053222656,-0.7147216796875],[-47.718894958496094,-0.640556335449219],[-47.665283203125,-0.573610305786133],[-47.63722229003906,-0.620832443237305],[-47.668060302734375,-0.709165573120117]]],[[[-51.13195037841797,-0.959444046020508],[-51.070281982421875,-0.69444465637207],[-50.815834045410156,-0.572221755981445],[-51.13195037841797,-0.959444046020508]]],[[[-51.051116943359375,-0.65916633605957],[-51.09833526611328,-0.633888244628906],[-51.02528381347656,-0.560556411743164],[-51.051116943359375,-0.65916633605957]]],[[[-51.901390075683594,-1.476667404174805],[-51.95222473144531,-1.430831909179688],[-51.88500213623047,-1.178888320922852],[-51.66222381591797,-1.083332061767578],[-51.60972595214844,-0.733888626098633],[-51.38195037841797,-0.541389465332031],[-51.19972229003906,-0.529167175292969],[-51.148338317871094,-0.669721603393555],[-51.27166557312012,-1.014165878295898],[-51.48333740234375,-1.240278244018555],[-51.901390075683594,-1.476667404174805]]],[[[-51.40333557128906,-0.54083251953125],[-51.41139221191406,-0.499721527099609],[-51.23944854736328,-0.454442977905273],[-51.40333557128906,-0.54083251953125]]],[[[-50.9586181640625,-0.567499160766602],[-50.878334045410156,-0.385276794433594],[-50.776947021484375,-0.383888244628906],[-50.9586181640625,-0.567499160766602]]],[[[-51.10778045654297,-0.539999008178711],[-51.03472900390625,-0.283056259155273],[-50.94667053222656,-0.353889465332031],[-51.10778045654297,-0.539999008178711]]],[[[-50.9072265625,-0.335832595825195],[-51.025001525878906,-0.24888801574707],[-50.88861846923828,-0.291389465332031],[-50.9072265625,-0.335832595825195]]],[[[-49.713340759277344,-0.227777481079102],[-48.37306213378906,-0.289167404174805],[-48.627227783203125,-1.064443588256836],[-49.16638946533203,-1.613887786865234],[-50.57805633544922,-1.800832748413086],[-50.803611755371094,-1.440555572509766],[-50.78111267089844,-1.151945114135742],[-50.55000305175781,-1.06916618347168],[-50.79695129394531,-0.971942901611328],[-50.65778350830078,-0.279167175292969],[-49.713340759277344,-0.227777481079102]]],[[[-50.80333709716797,-0.358888626098633],[-50.908058166503906,-0.358331680297852],[-50.74889373779297,-0.226667404174805],[-50.80333709716797,-0.358888626098633]]],[[[-51.38056182861328,-0.484722137451172],[-51.103057861328125,-0.121389389038086],[-51.13750457763672,-0.2852783203125],[-51.38056182861328,-0.484722137451172]]],[[[-50.55694580078125,-0.0625],[-50.85778045654297,-0.283056259155273],[-51.02722930908203,-0.224166870117188],[-50.55694580078125,-0.0625]]],[[[-50.90167236328125,-0.04749870300293],[-50.82972717285156,0.060834884643555],[-50.69750213623047,0.023889541625977],[-50.90167236328125,-0.04749870300293]]],[[[-49.52555847167969,-0.134443283081055],[-49.852500915527344,-0.064443588256836],[-49.501670837402344,0.070558547973633],[-49.52555847167969,-0.134443283081055]]],[[[-50.45555877685547,-0.022777557373047],[-50.643333435058594,0.171110153198242],[-50.465003967285156,0.146669387817383],[-50.45555877685547,-0.022777557373047]]],[[[-49.63611602783203,0.227502822875977],[-49.98472595214844,-0.072221755981445],[-50.39250183105469,0.109445571899414],[-49.63611602783203,0.227502822875977]]],[[[-50.24305725097656,0.22944450378418],[-50.184173583984375,0.324167251586914],[-50.0836181640625,0.320001602172852],[-50.24305725097656,0.22944450378418]]],[[[-50.41638946533203,0.210832595825195],[-50.53639221191406,0.226110458374023],[-50.37389373779297,0.621389389038086],[-50.41638946533203,0.210832595825195]]],[[[-50.23750305175781,0.350835800170898],[-50.30805969238281,0.506391525268555],[-50.06361389160156,0.646112442016602],[-50.23750305175781,0.350835800170898]]],[[[-50.007225036621094,0.88166618347168],[-50.267784118652344,0.751668930053711],[-50.2005615234375,0.879167556762695],[-50.007225036621094,0.88166618347168]]],[[[-50.037506103515625,0.884443283081055],[-50.093894958496094,0.920835494995117],[-50.04222869873047,0.918058395385742],[-50.037506103515625,0.884443283081055]]],[[[-50.00944519042969,0.935277938842773],[-50.07444763183594,0.981111526489258],[-49.947784423828125,1.054445266723633],[-50.00944519042969,0.935277938842773]]],[[[-50.39666557312012,1.881391525268555],[-50.5050048828125,2.024999618530273],[-50.356117248535156,2.116945266723633],[-50.39666557312012,1.881391525268555]]],[[[-50.47528076171875,2.119722366333008],[-50.51722717285156,2.203054428100586],[-50.405555725097656,2.193613052368164],[-50.47528076171875,2.119722366333008]]],[[[-60.09833526611328,5.217222213745117],[-60.14750671386719,4.517499923706055],[-59.67583465576172,4.388887405395508],[-59.56861114501953,3.899446487426758],[-59.98944854736328,2.693613052368164],[-59.642784118652344,1.731111526489258],[-58.80694580078125,1.185556411743164],[-57.32472229003906,1.975278854370117],[-56.47063446044922,1.944498062133789],[-55.90416717529297,1.893056869506836],[-55.96583557128906,2.532777786254883],[-54.603782653808594,2.329195022583008],[-52.90972900390625,2.195833206176758],[-51.68406677246094,4.034162521362305],[-51.447784423828125,3.972501754760742],[-51.537506103515625,4.391389846801758],[-51.08861541748047,3.91166877746582],[-50.679725646972656,2.164724349975586],[-50.445281982421875,1.825834274291992],[-49.93000030517578,1.70805549621582],[-50.1219482421875,1.214166641235352],[-49.903892517089844,1.170278549194336],[-51.25861358642578,-0.142778396606445],[-51.70000457763672,-0.752498626708984],[-51.712501525878906,-1.026666641235352],[-51.920005798339844,-1.166389465332031],[-51.92833709716797,-1.337778091430664],[-52.0675048828125,-1.420000076293945],[-52.232505798339844,-1.345277786254883],[-52.71278381347656,-1.60333251953125],[-52.20846939086914,-1.69207763671875],[-51.257225036621094,-1.218332290649414],[-50.99278259277344,-0.998611450195313],[-51.00917053222656,-0.949167251586914],[-50.992225646972656,-0.925277709960938],[-50.85833740234375,-0.913610458374023],[-50.816673278808594,-1.439722061157227],[-50.66389465332031,-1.767778396606445],[-51.336944580078125,-1.646944046020508],[-51.45195007324219,-2.273611068725586],[-51.30750274658203,-1.76361083984375],[-50.84611511230469,-2.508609771728516],[-50.98389434814453,-2.066110610961914],[-50.706390380859375,-2.220556259155273],[-50.677955627441406,-1.810443878173828],[-49.28972625732422,-1.708332061767578],[-49.49000358581543,-2.564998626708984],[-48.69722557067871,-1.469165802001953],[-48.43055725097656,-1.661666870117188],[-48.413612365722656,-1.499443054199219],[-48.1844482421875,-1.471944808959961],[-48.50305938720703,-1.458332061767578],[-48.47917175292969,-1.301942825317383],[-48.33167266845703,-1.308332443237305],[-48.29222869873047,-0.944999694824219],[-48.06056213378906,-0.710832595825195],[-47.956947326660156,-0.775278091430664],[-47.74945068359375,-0.635276794433594],[-47.726951599121094,-0.758054733276367],[-47.542503356933594,-0.636667251586914],[-47.393890380859375,-0.812778472900391],[-47.43139457702637,-0.582500457763672],[-46.95472717285156,-0.704444885253906],[-46.95111846923828,-0.908056259155273],[-46.82167053222656,-0.712778091430664],[-46.60417175292969,-1.029443740844727],[-46.55778503417969,-0.999166488647461],[-46.53583526611328,-1.032220840454102],[-46.448333740234375,-1.043054580688477],[-46.19194793701172,-0.957500457763672],[-46.25972557067871,-1.183610916137695],[-46.0433349609375,-1.210277557373047],[-45.97472381591797,-1.07499885559082],[-45.851951599121094,-1.271944046020508],[-45.735557556152344,-1.180000305175781],[-45.69611358642578,-1.370277404785156],[-45.44694519042969,-1.310832977294922],[-45.46222686767578,-1.545555114746094],[-45.32666778564453,-1.313333511352539],[-45.347503662109375,-1.740278244018555],[-44.86028289794922,-1.425277709960938],[-44.951393127441406,-1.601667404174805],[-44.820556640625,-1.578332901000977],[-44.799171447753906,-1.704999923706055],[-44.69500732421875,-1.817777633666992],[-44.53889465332031,-1.832221984863281],[-44.490562438964844,-1.980833053588867],[-44.656394958496094,-2.331110000610352],[-44.36000061035156,-2.338888168334961],[-44.58222961425781,-2.556943893432617],[-44.78639221191406,-3.29749870300293],[-44.420562744140625,-2.930000305175781],[-44.35694885253906,-2.526666641235352],[-44.06333923339844,-2.405834197998047],[-44.33972930908203,-2.830278396606445],[-43.347503662109375,-2.365833282470703],[-41.248069763183594,-3.023553848266602],[-39.9969482421875,-2.84638786315918],[-37.17444610595703,-4.918611526489258],[-35.417503356933594,-5.2147216796875],[-34.80083465576172,-7.631111145019531],[-35.29277801513672,-9.180000305175781],[-36.393333435058594,-10.492500305175781],[-37.02166557312012,-10.935834884643555],[-37.15333557128906,-10.748611450195312],[-38.04138946533203,-12.633056640625],[-38.488616943359375,-13.020000457763672],[-38.691673278808594,-12.577777862548828],[-38.90111541748047,-12.705556869506836],[-38.72528076171875,-12.874444961547852],[-38.95667266845703,-13.380001068115234],[-39.05639457702637,-13.377500534057617],[-39.080284118652344,-13.538333892822266],[-38.96305847167969,-13.681390762329102],[-39.03889465332031,-14.175834655761719],[-38.920562744140625,-13.915555953979492],[-39.06694793701172,-14.643890380859375],[-38.8719482421875,-15.874168395996094],[-39.20667266845703,-17.147502899169922],[-39.13083457946777,-17.68389129638672],[-39.64361572265625,-18.22333526611328],[-39.8013916015625,-19.632503509521484],[-40.96055603027344,-21.235836029052734],[-40.97167205810547,-21.988056182861328],[-41.7630615234375,-22.346111297607422],[-42.034446716308594,-22.919170379638672],[-43.091949462890625,-22.954723358154297],[-43.075836181640625,-22.6683349609375],[-43.21833801269531,-22.9969482421875],[-44.662506103515625,-23.048057556152344],[-44.57722473144531,-23.35611343383789],[-45.4183349609375,-23.830833435058594],[-46.382781982421875,-23.868335723876953],[-48.02611541748047,-25.015003204345703],[-48.2086181640625,-25.461669921875],[-48.13139343261719,-25.27222442626953],[-48.71861267089844,-25.424724578857422],[-48.36138916015625,-25.57638931274414],[-48.77056121826172,-25.880001068115234],[-48.581947326660156,-26.18000030517578],[-48.80250358581543,-26.067222595214844],[-48.48528289794922,-27.21139144897461],[-48.77472686767578,-28.52222442626953],[-49.75250244140625,-29.36972427368164],[-50.74945068359375,-31.081111907958984],[-52.07250213623047,-32.174171447753906],[-52.086395263671875,-31.823612213134766],[-51.25139617919922,-31.471668243408203],[-50.567222595214844,-30.457225799560547],[-50.60889434814453,-30.190555572509766],[-50.92833709716797,-30.419445037841797],[-51.28166961669922,-30.01000213623047],[-51.2711181640625,-30.79555892944336],[-51.96527862548828,-31.339447021484375],[-52.63667297363281,-33.12944793701172],[-53.374298095703125,-33.74066925048828],[-53.52278137207031,-33.14778137207031],[-53.093055725097656,-32.72972869873047],[-53.879722595214844,-31.96778106689453],[-55.581947326660156,-30.845836639404297],[-56.0089225769043,-31.07979393005371],[-56.81139373779297,-30.10527801513672],[-57.608001708984375,-30.184925079345703],[-55.765281677246094,-28.226112365722656],[-53.80778503417969,-27.129169464111328],[-53.86333465576172,-25.681114196777344],[-54.598915100097656,-25.573223114013672],[-54.33055877685547,-24.6794490814209],[-54.4072265625,-23.916667938232422],[-55.41166687011719,-23.956390380859375],[-55.84972381591797,-22.288890838623047],[-57.985107421875,-22.091827392578125],[-57.814443588256836,-20.971946716308594],[-58.15888977050781,-20.168054580688477],[-57.84874725341797,-19.97879409790039],[-58.121116638183594,-19.741390228271484],[-57.5211181640625,-18.20389175415039],[-57.74305725097656,-17.593055725097656],[-58.39750671386719,-17.249168395996094],[-58.32750701904297,-16.27916717529297],[-60.1602783203125,-16.263057708740234],[-60.57139587402344,-15.097501754760742],[-60.25889587402344,-15.093612670898438],[-60.47084045410156,-13.807222366333008],[-61.038978576660156,-13.493118286132812],[-61.833892822265625,-13.544723510742188],[-63.07500457763672,-12.650001525878906],[-64.39418029785156,-12.461668014526367],[-64.99166870117188,-12.008056640625],[-65.39279174804688,-11.266389846801758],[-65.3819580078125,-9.697778701782227],[-66.63444519042969,-9.906946182250977],[-68.58345031738281,-11.106138229370117],[-69.56843566894531,-10.951091766357422],[-70.63139343261719,-11.009166717529297],[-70.51466369628906,-9.428001403808594],[-71.29888916015625,-9.996389389038086],[-72.14389038085938,-10.004722595214844],[-72.36639404296875,-9.49444580078125],[-73.20529174804688,-9.407222747802734],[-72.96417236328125,-8.983333587646484],[-74.01055908203125,-7.541389465332031],[-73.74417114257812,-6.876943588256836],[-73.1239013671875,-6.447221755981445],[-72.85195922851562,-5.124721527099609],[-70.76583862304688,-4.146389007568359],[-69.95692443847656,-4.236873626708984],[-69.37806701660156,-1.338054656982422],[-69.60751342773438,-0.517499923706055],[-70.05805969238281,-0.157499313354492],[-70.04417419433594,0.59083366394043],[-69.12472534179688,0.645002365112305],[-69.27000427246094,1.038335800170898],[-69.84222412109375,1.072221755981445],[-69.84609985351562,1.710454940795898],[-68.15306091308594,1.72416877746582],[-68.19639587402344,1.977502822875977],[-67.91473388671875,1.745279312133789],[-67.42417907714844,2.143888473510742],[-67.07667541503906,1.173334121704102],[-66.87188720703125,1.221643447875977],[-66.31195068359375,0.750558853149414],[-65.58973693847656,0.989168167114258],[-65.51889038085938,0.649721145629883],[-63.39305877685547,2.151388168334961],[-63.361114501953125,2.419168472290039],[-64.04501342773438,2.482500076293945],[-64.19111633300781,3.594446182250977],[-64.7952880859375,4.281389236450195],[-64.01779174804688,3.886110305786133],[-63.343055725097656,3.961111068725586],[-62.875,3.560277938842773],[-62.74583435058594,4.032499313354492],[-60.98500061035156,4.52055549621582],[-60.57972717285156,4.94666862487793],[-60.730369567871094,5.204801559448242],[-60.09833526611328,5.217222213745117]]]]}},{"type":"Feature","properties":{"name":"Bulgaria","iso2":"BG","iso3":"BGR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[27.879166,42.841103],[27.44833,42.469994],[28.013054,41.982216],[27.394997,42.008041],[26.361095,41.711052],[26.294167,41.708054],[26.066109,41.69749500000013],[26.139996,41.354713],[25.28500000000014,41.24305],[24.263885,41.570549],[22.935604,41.342125],[23.014721,41.762215],[22.365276,42.323883],[22.442219,42.821663],[23.004997,43.192772],[22.367222,43.826942],[22.681435,44.224701],[23.044167,44.076111],[22.875275,43.842499],[24.179996,43.684715],[25.430229,43.626778],[27.036427,44.147339],[28.583244,43.747765],[27.879166,42.841103]]]]}},{"type":"Feature","properties":{"name":"Brunei Darussalam","iso2":"BN","iso3":"BRN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[115.223038,4.804998000000126],[115.343323,4.311943],[115.029129,4.82021],[115.145782,4.90324],[115.223038,4.804998000000126]]],[[[114.981369,4.892499],[115.018433,4.895795000000135],[114.641098,4.018888],[114.095078,4.590538],[114.981369,4.892499]]]]}},{"type":"Feature","properties":{"name":"Canada","iso2":"CA","iso3":"CAN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-65.61361694335938,43.42027473449707],[-65.633056640625,43.47471046447754],[-65.56610107421875,43.50833320617676],[-65.61361694335938,43.42027473449707]]],[[[-59.81694793701172,43.92833137512207],[-60.12999725341797,43.94193458557129],[-59.72471618652344,43.991106033325195],[-59.81694793701172,43.92833137512207]]],[[[-66.28277587890625,44.28972053527832],[-66.32223510742188,44.25277900695801],[-66.20639038085938,44.395273208618164],[-66.28277587890625,44.28972053527832]]],[[[-66.88612365722656,44.61444282531738],[-66.77250671386719,44.809160232543945],[-66.74028015136719,44.707773208618164],[-66.88612365722656,44.61444282531738]]],[[[-60.99388885498047,45.457773208618164],[-61.10444641113281,45.54638862609863],[-60.87999725341797,45.56054878234863],[-60.99388885498047,45.457773208618164]]],[[[-61.19999694824219,45.55832862854004],[-61.22416687011719,45.564157485961914],[-61.21416473388672,45.56888771057129],[-61.19999694824219,45.55832862854004]]],[[[-63.24639129638672,46.43554878234863],[-63.285003662109375,46.45083045959473],[-63.24583435058594,46.442766189575195],[-63.24639129638672,46.43554878234863]]],[[[-60.445274353027344,46.86166572570801],[-60.609169006347656,46.20193672180176],[-60.41999816894531,46.27999305725098],[-61.149169921875,45.699716567993164],[-60.40916442871094,45.979990005493164],[-60.78972625732422,45.93443489074707],[-60.3477783203125,46.31054878234863],[-59.840553283691406,45.93832588195801],[-61.336944580078125,45.57332801818848],[-61.447776794433594,46.14943885803223],[-60.609169006347656,47.02443885803223],[-60.445274353027344,46.86166572570801]]],[[[-64.03971862792969,46.74332618713379],[-63.742225646972656,46.43943214416504],[-63.64722442626953,46.567216873168945],[-63.216392517089844,46.41221046447754],[-61.965003967285156,46.453325271606445],[-62.76111602783203,45.95416450500488],[-62.96277618408203,46.31999397277832],[-63.591941833496094,46.21193885803223],[-64.41555786132812,46.670549392700195],[-64.02084350585938,47.03860664367676],[-64.03971862792969,46.74332618713379]]],[[[-55.87610626220703,47.26055335998535],[-55.96833038330078,47.25777626037598],[-55.88111114501953,47.2933292388916],[-55.87610626220703,47.26055335998535]]],[[[-61.38055419921875,47.62027168273926],[-62.0130615234375,47.2258243560791],[-61.92805480957031,47.40721321105957],[-61.38055419921875,47.62027168273926]]],[[[-54.261390686035156,47.390275955200195],[-54.36555480957031,47.41166114807129],[-54.128883361816406,47.670549392700195],[-54.261390686035156,47.390275955200195]]],[[[-54.07749938964844,47.47943305969238],[-54.10194396972656,47.50139045715332],[-54.071388244628906,47.68554878234863],[-54.07749938964844,47.47943305969238]]],[[[-55.901939392089844,47.602495193481445],[-56.113616943359375,47.64471626281738],[-55.93388366699219,47.68832588195801],[-55.901939392089844,47.602495193481445]]],[[[-64.48277282714844,47.91777229309082],[-64.6905517578125,47.75305366516113],[-64.66749572753906,47.8669376373291],[-64.48277282714844,47.91777229309082]]],[[[-64.5675048828125,47.89943885803223],[-64.50111389160156,48.02749061584473],[-64.47055053710938,47.953325271606445],[-64.5675048828125,47.89943885803223]]],[[[-53.71277618408203,48.148881912231445],[-53.935829162597656,48.18249702453613],[-53.50972557067871,48.19832801818848],[-53.71277618408203,48.148881912231445]]],[[[-123.47444152832031,48.70916175842285],[-123.5966567993164,48.94693946838379],[-123.37026977539062,48.768327713012695],[-123.47444152832031,48.70916175842285]]],[[[-123.3227767944336,48.86110877990723],[-123.54055786132812,48.94499397277832],[-123.70249938964844,49.10555458068848],[-123.3227767944336,48.86110877990723]]],[[[-125.81610107421875,49.12582588195801],[-125.93305969238281,49.21805000305176],[-125.79915618896484,49.208330154418945],[-125.81610107421875,49.12582588195801]]],[[[-126.13194274902344,49.393327713012695],[-126.06471252441406,49.25083351135254],[-126.23916625976562,49.28972053527832],[-126.13194274902344,49.393327713012695]]],[[[-123.37944030761719,49.32694435119629],[-123.42027282714844,49.381662368774414],[-123.31221008300781,49.414995193481445],[-123.37944030761719,49.32694435119629]]],[[[-54.70527458190918,49.40054512023926],[-54.75917053222656,49.43776893615723],[-54.673057556152344,49.49249458312988],[-54.640838623046875,49.463884353637695],[-54.70527458190918,49.40054512023926]]],[[[-124.17916870117188,49.44110298156738],[-124.381103515625,49.51194190979004],[-124.24472045898438,49.50139045715332],[-124.17916870117188,49.44110298156738]]],[[[-123.33277893066406,49.44110298156738],[-123.45944213867188,49.46721076965332],[-123.43666076660156,49.52221870422363],[-123.3550033569336,49.531938552856445],[-123.33277893066406,49.44110298156738]]],[[[-55.69554901123047,49.50694465637207],[-55.72277069091797,49.55777168273926],[-55.653053283691406,49.55526924133301],[-55.69554901123047,49.50694465637207]]],[[[-124.68943786621094,49.48027229309082],[-124.82362365722656,49.539438247680664],[-124.83168029785156,49.610551834106445],[-124.68943786621094,49.48027229309082]]],[[[-55.69305419921875,49.5674991607666],[-55.65972137451172,49.63555335998535],[-55.5675048828125,49.60000038146973],[-55.69305419921875,49.5674991607666]]],[[[-54.57666778564453,49.558603286743164],[-54.894447326660156,49.58526802062988],[-54.53611755371094,49.66415596008301],[-54.57666778564453,49.558603286743164]]],[[[-54.00444793701172,49.64749336242676],[-54.29888916015625,49.609994888305664],[-54.141944885253906,49.75000190734863],[-54.00444793701172,49.64749336242676]]],[[[-124.12970733642578,49.650827407836914],[-124.19943237304688,49.70610237121582],[-124.01611328125,49.77555274963379],[-124.12970733642578,49.650827407836914]]],[[[-124.44611358642578,49.72332191467285],[-124.12277221679688,49.493608474731445],[-124.65666198730469,49.796945571899414],[-124.44611358642578,49.72332191467285]]],[[[-62.0897216796875,49.38638496398926],[-61.66166687011719,49.14444160461426],[-63.089996337890625,49.228044509887695],[-64.51390075683594,49.86361122131348],[-62.0897216796875,49.38638496398926]]],[[[-126.67610168457031,49.58360481262207],[-126.9405517578125,49.83138465881348],[-126.77749633789062,49.879716873168945],[-126.67804718017578,49.825273513793945],[-126.61332702636719,49.648332595825195],[-126.67610168457031,49.58360481262207]]],[[[-124.92415618896484,50.058603286743164],[-125.06696319580078,50.107500076293945],[-124.98332214355469,50.22554969787598],[-124.92415618896484,50.058603286743164]]],[[[-63.85944366455078,50.197771072387695],[-63.93055725097656,50.22943305969238],[-63.88972473144531,50.24221992492676],[-63.85944366455078,50.197771072387695]]],[[[-125.16777038574219,49.98082160949707],[-125.33999633789062,50.26888465881348],[-125.25473022460938,50.29361152648926],[-125.16722106933594,50.21360969543457],[-125.16777038574219,49.98082160949707]]],[[[-124.8125,50.11138343811035],[-124.91832733154297,50.29972267150879],[-124.75666809082031,50.17833137512207],[-124.8125,50.11138343811035]]],[[[-124.73082733154297,50.30221748352051],[-124.65943908691406,50.25833320617676],[-124.69583129882812,50.15749549865723],[-124.79499816894531,50.2288761138916],[-124.73082733154297,50.30221748352051]]],[[[-125.16555786132812,50.37443733215332],[-125.14028930664062,50.121660232543945],[-125.15611267089844,50.23916053771973],[-125.213623046875,50.316667556762695],[-125.40028381347656,50.32083320617676],[-125.16555786132812,50.37443733215332]]],[[[-125.80722045898438,50.41360664367676],[-125.95111083984375,50.43387794494629],[-125.73805236816406,50.428049087524414],[-125.80722045898438,50.41360664367676]]],[[[-125.54387664794922,50.39388465881348],[-125.76363372802734,50.39749336242676],[-125.5239028930664,50.43443489074707],[-125.54387664794922,50.39388465881348]]],[[[-125.42610168457031,50.35555458068848],[-125.52806091308594,50.381662368774414],[-125.33194732666016,50.43554878234863],[-125.42610168457031,50.35555458068848]]],[[[-126.225830078125,50.55526924133301],[-126.62389373779297,50.533884048461914],[-126.28611755371094,50.59832954406738],[-126.225830078125,50.55526924133301]]],[[[-126.46640014648438,50.57583045959473],[-126.55416870117188,50.6027774810791],[-126.36138916015625,50.61583137512207],[-126.46640014648438,50.57583045959473]]],[[[-59.34583282470703,50.533884048461914],[-59.37194061279297,50.65277290344238],[-59.30027770996094,50.58194160461426],[-59.34583282470703,50.533884048461914]]],[[[-126.87332153320312,50.6633243560791],[-126.83112335205078,50.629159927368164],[-127.14472961425781,50.63388252258301],[-126.87332153320312,50.6633243560791]]],[[[-126.64389038085938,50.69193458557129],[-126.685546875,50.75889015197754],[-126.53639221191406,50.76361274719238],[-126.64389038085938,50.69193458557129]]],[[[-127.22693634033203,50.63611030578613],[-125.44972229003906,50.32361030578613],[-124.78943634033203,49.46415901184082],[-123.69943237304688,49.14388465881348],[-123.8505630493164,49.14554786682129],[-123.28971862792969,48.4133243560791],[-125.1138916015625,48.73110389709473],[-124.80776977539062,49.240549087524414],[-125.48361206054688,48.91582679748535],[-125.90471458435059,49.43582344055176],[-126.54222106933594,49.37443733215332],[-126.08750915527344,49.66221046447754],[-126.58500671386719,49.70110511779785],[-126.67971801757812,49.87887763977051],[-126.804443359375,49.90915870666504],[-127.1211166381836,49.8522891998291],[-127.24137878417969,49.96193885803223],[-127.15834045410156,50.096384048461914],[-127.89584350585938,50.10888862609863],[-127.92388916015625,50.46277046203613],[-127.44695281982422,50.37276649475098],[-127.41139221191406,50.58749580383301],[-128.05142211914062,50.44669532775879],[-128.416654586792,50.7691593170166],[-127.22693634033203,50.63611030578613]]],[[[-55.564720153808594,50.699716567993164],[-55.624717712402344,50.78721809387207],[-55.45055389404297,50.7983341217041],[-55.564720153808594,50.699716567993164]]],[[[-126.73137664794922,50.77193641662598],[-126.90583801269531,50.822771072387695],[-126.56304931640625,50.799997329711914],[-126.73137664794922,50.77193641662598]]],[[[-126.27306365966797,50.65277290344238],[-126.61749267578125,50.66777229309082],[-126.26640319824219,50.827775955200195],[-126.27306365966797,50.65277290344238]]],[[[-127.65471458435059,50.83777046203613],[-127.83860778808594,50.881662368774414],[-127.72638702392578,50.90860176086426],[-127.65471458435059,50.83777046203613]]],[[[-55.55555725097656,50.88638496398926],[-55.635276794433594,50.961381912231445],[-55.5352783203125,50.98137855529785],[-55.55555725097656,50.88638496398926]]],[[[-58.413330078125,51.2388858795166],[-58.56500244140625,51.23333168029785],[-58.41944885253906,51.27471351623535],[-58.413330078125,51.2388858795166]]],[[[-53.75636672973633,48.50326347351074],[-54.094444274902344,48.42582893371582],[-54.13805389404297,48.35916328430176],[-53.75636672973633,48.50326347351074],[-52.978050231933594,48.604440689086914],[-53.945274353027344,48.17888069152832],[-53.60778045654297,48.051103591918945],[-53.850555419921875,47.76055335998535],[-53.55055236816406,47.52916145324707],[-53.274444580078125,48.01333045959473],[-52.831390380859375,48.10166358947754],[-53.26721954345703,47.60610389709473],[-53.12194061279297,47.4133243560791],[-52.779441833496094,47.803049087524414],[-52.61444854736328,47.51666450500488],[-53.102500915527344,46.63665962219238],[-53.617774963378906,46.6441593170166],[-53.59138488769531,47.15609931945801],[-54.187774658203125,46.819162368774414],[-53.86750030517578,47.40277290344238],[-54.195274353027344,47.857500076293945],[-54.48277282714844,47.39166450500488],[-54.4183349609375,47.60360908508301],[-55.689720153808594,46.85833168029785],[-55.983055114746094,46.95249366760254],[-54.84583282470703,47.55694007873535],[-54.93611145019531,47.78166389465332],[-55.58777618408203,47.39860725402832],[-56.17250061035156,47.49721717834473],[-55.628334045410156,47.67471504211426],[-55.917503356933594,47.65749549865723],[-55.77361297607422,47.95694160461426],[-56.84083557128906,47.521379470825195],[-59.13555908203125,47.55638313293457],[-59.406944274902344,47.889719009399414],[-58.4183349609375,48.48665809631348],[-59.26111602783203,48.47665596008301],[-58.77471923828125,48.778879165649414],[-58.95861053466797,48.6138858795166],[-58.709442138671875,48.57083320617676],[-58.39611053466797,49.13138008117676],[-57.88166809082031,48.968881607055664],[-58.22332763671875,49.390275955200195],[-57.696388244628906,49.46360969543457],[-57.948333740234375,49.67416572570801],[-57.14805603027344,50.62193489074707],[-57.37860870361328,50.68776893615723],[-55.89805603027344,51.62860298156738],[-55.4052734375,51.561662673950195],[-56.08555603027344,51.36832618713379],[-55.73249816894531,51.07999610900879],[-56.1552734375,50.88555335998535],[-56.84888458251953,49.544443130493164],[-56.15388488769531,50.15054512023926],[-55.49169921875,50.00731086730957],[-56.12916564941406,49.425554275512695],[-55.315277099609375,49.31443977355957],[-55.14111328125,49.54527473449707],[-55.383331298828125,49.04083442687988],[-55.07805633544922,49.356943130493164],[-54.82444763183594,49.2691593170166],[-54.52888488769531,49.533334732055664],[-54.48694610595703,49.259721755981445],[-53.775001525878906,49.39610481262207],[-53.488609313964844,49.22054481506348],[-54.09610557556152,48.812211990356445],[-53.60194396972656,48.689714431762695],[-53.95610809326172,48.54388618469238],[-53.75636672973633,48.50326347351074]],[[-56.803611755371094,49.76333045959473],[-56.78221893310547,49.786943435668945],[-56.838050842285156,49.76749610900879],[-56.803611755371094,49.76333045959473]],[[-55.99388885498047,51.200273513793945],[-55.9677734375,51.22665596008301],[-55.99805450439453,51.20749855041504],[-55.99388885498047,51.200273513793945]],[[-58.34222412109375,49.06610298156738],[-58.33361053466797,49.077775955200195],[-58.356109619140625,49.06582832336426],[-58.34222412109375,49.06610298156738]]],[[[-127.91443634033203,51.41082191467285],[-128.14556884765625,51.65360450744629],[-128,51.72054481506348],[-127.91443634033203,51.41082191467285]]],[[[-55.36750030517578,51.874162673950195],[-55.43055725097656,51.89666175842285],[-55.269996643066406,52.00055122375488],[-55.36750030517578,51.874162673950195]]],[[[-128.05389404296875,51.753610610961914],[-128.25308227539062,51.87221717834473],[-127.98332214355469,52.06193733215332],[-128.05389404296875,51.753610610961914]]],[[[-79.25279235839844,52.07138252258301],[-79.37666320800781,51.936105728149414],[-79.6541748046875,51.98665809631348],[-79.25279235839844,52.07138252258301]]],[[[-131.01889038085938,51.94610023498535],[-131.11026000976562,52.15110206604004],[-131.00946044921875,52.1027774810791],[-131.01889038085938,51.94610023498535]]],[[[-127.96278381347656,52.074716567993164],[-128.12081909179688,52.14193916320801],[-127.881103515625,52.17222023010254],[-127.96278381347656,52.074716567993164]]],[[[-128.21194458007812,52.01555061340332],[-128.29415893554688,52.11361122131348],[-128.153076171875,52.195268630981445],[-128.21194458007812,52.01555061340332]]],[[[-128.29998779296875,52.13360786437988],[-128.377197265625,52.22387886047363],[-128.22720336914062,52.218881607055664],[-128.29998779296875,52.13360786437988]]],[[[-128.4283447265625,52.13749885559082],[-128.51113891601562,52.169992446899414],[-128.41641235351562,52.22638130187988],[-128.4283447265625,52.13749885559082]]],[[[-127.92471313476562,52.17416572570801],[-128.17001342773438,52.24971961975098],[-127.9727783203125,52.29527473449707],[-127.92471313476562,52.17416572570801]]],[[[-81.47694396972656,52.249162673950195],[-81.71000671386719,52.26249885559082],[-81.55166625976562,52.298051834106445],[-81.47694396972656,52.249162673950195]]],[[[-127.72444152832031,51.976938247680664],[-127.78916931152344,52.221933364868164],[-127.23473358154297,52.416940689086914],[-127.72444152832031,51.976938247680664]]],[[[-128.1844482421875,52.27860450744629],[-128.10443115234375,52.4213809967041],[-128.05667114257812,52.32888221740723],[-128.1844482421875,52.27860450744629]]],[[[-128.66860961914062,52.26638984680176],[-128.74722290039062,52.47165870666504],[-128.61581420898438,52.4536075592041],[-128.66860961914062,52.26638984680176]]],[[[-128.471923828125,52.49276924133301],[-128.81390380859375,52.52499580383301],[-128.73248291015625,52.59054756164551],[-128.57818603515625,52.593645095825195],[-128.5352783203125,52.64721870422363],[-128.471923828125,52.49276924133301]]],[[[-131.46444702148438,52.62748908996582],[-131.709716796875,52.705270767211914],[-131.47528076171875,52.73665809631348],[-131.46444702148438,52.62748908996582]]],[[[-128.4302978515625,52.368051528930664],[-128.38333129882812,52.797494888305664],[-128.2750244140625,52.48999214172363],[-128.4302978515625,52.368051528930664]]],[[[-128.97442626953125,52.453325271606445],[-129.2772216796875,52.82305335998535],[-128.92333984375,52.60666084289551],[-128.97442626953125,52.453325271606445]]],[[[-128.26974487304688,52.596940994262695],[-128.32501220703125,52.77610206604004],[-128.17779541015625,52.82610511779785],[-128.26974487304688,52.596940994262695]]],[[[-131.63973999023438,52.82805061340332],[-131.73306274414062,52.808603286743164],[-131.83139038085938,52.841936111450195],[-131.63973999023438,52.82805061340332]]],[[[-128.50527954101562,52.6411075592041],[-128.50613403320312,52.87304878234863],[-128.45083618164062,52.80526924133301],[-128.50527954101562,52.6411075592041]]],[[[-129.61053466796875,52.95499610900879],[-129.65084838867188,53.01888465881348],[-129.5574951171875,53.006662368774414],[-129.61053466796875,52.95499610900879]]],[[[-129.53167724609375,53.01055335998535],[-129.6400146484375,53.04416084289551],[-129.56277465820312,53.053049087524414],[-129.53167724609375,53.01055335998535]]],[[[-55.7630615234375,53.029436111450195],[-55.87638854980469,53.02749061584473],[-55.80055236816406,53.09360694885254],[-55.7630615234375,53.029436111450195]]],[[[-129.60247802734375,53.05721473693848],[-129.73831176757812,53.127214431762695],[-129.65444946289062,53.132768630981445],[-129.60247802734375,53.05721473693848]]],[[[-129.4324951171875,53.151384353637695],[-129.28945922851562,52.971933364868164],[-129.5472412109375,53.1330509185791],[-129.4324951171875,53.151384353637695]]],[[[-79.90916442871094,53.08194160461426],[-79.89778137207031,53.17444038391113],[-79.78721618652344,53.101938247680664],[-79.90916442871094,53.08194160461426]]],[[[-81.10610961914062,53.199716567993164],[-80.69972229003906,52.69610023498535],[-82.06332397460938,53.02665901184082],[-81.10610961914062,53.199716567993164]]],[[[-131.76223754882812,53.19665718078613],[-131.5947265625,53.0352725982666],[-131.9647216796875,53.04638862609863],[-131.61553955078125,52.92027473449707],[-131.98248291015625,52.879716873168945],[-131.03030395507812,52.17388343811035],[-132.56362915039062,53.13916206359863],[-132.54916381835938,53.15110206604004],[-132.41363525390625,53.12748908996582],[-132.07083129882812,53.153879165649414],[-131.81112670898438,53.253610610961914],[-131.76223754882812,53.19665718078613]]],[[[-128.689453125,53.164438247680664],[-128.51834106445312,52.91110420227051],[-128.59222412109375,52.6138858795166],[-128.74887084960938,52.59721565246582],[-128.64697265625,52.963327407836914],[-128.88446044921875,52.64805030822754],[-129.12191772460938,52.863054275512695],[-128.84359741210938,53.04416084289551],[-129.19137573242188,53.01333045959473],[-129.07528686523438,53.10305213928223],[-129.066650390625,53.30082893371582],[-128.689453125,53.164438247680664]]],[[[-55.778053283691406,53.28972053527832],[-55.79722595214844,53.295549392700195],[-55.785003662109375,53.303606033325195],[-55.778053283691406,53.28972053527832]]],[[[-129.153076171875,53.09832954406738],[-129.33248901367188,53.13749885559082],[-129.26806640625,53.33194160461426],[-129.16860961914062,53.29610633850098],[-129.153076171875,53.09832954406738]]],[[[-79.94276428222656,53.26693916320801],[-80.08528137207031,53.32694435119629],[-79.94471740722656,53.368051528930664],[-79.94276428222656,53.26693916320801]]],[[[-129.35833740234375,53.30416297912598],[-129.39501953125,53.41082191467285],[-129.3033447265625,53.33111000061035],[-129.35833740234375,53.30416297912598]]],[[[-55.787506103515625,53.3941593170166],[-55.979164123535156,53.45916175842285],[-55.729164123535156,53.455270767211914],[-55.787506103515625,53.3941593170166]]],[[[-128.9425048828125,53.3174991607666],[-129.14334106445312,53.34971809387207],[-128.99942016601562,53.539438247680664],[-128.901123046875,53.38665962219238],[-128.9425048828125,53.3174991607666]]],[[[-79.70973205566406,53.5080509185791],[-79.77362060546875,53.53166389465332],[-79.76139831542969,53.54610633850098],[-79.70973205566406,53.5080509185791]]],[[[-129.93472290039062,53.48416328430176],[-130.0211181640625,53.50527381896973],[-129.94195556640625,53.551103591918945],[-129.88668823242188,53.54222297668457],[-129.93472290039062,53.48416328430176]]],[[[-129.87942504882812,53.392770767211914],[-129.76223754882812,53.158884048461914],[-130.52029418945312,53.624711990356445],[-129.87942504882812,53.392770767211914]]],[[[-129.08639526367188,53.44610023498535],[-129.153076171875,53.63860511779785],[-128.81887817382812,53.70916175842285],[-129.08554077148438,53.5049991607666],[-129.08639526367188,53.44610023498535]]],[[[-56.867218017578125,53.76500129699707],[-57.01445007324219,53.78555488586426],[-56.844444274902344,53.792497634887695],[-56.867218017578125,53.76500129699707]]],[[[-130.09109497070312,53.56944465637207],[-130.40335083007812,53.68249702453613],[-130.26168823242188,53.79638862609863],[-130.09109497070312,53.56944465637207]]],[[[-129.82611083984375,53.72416114807129],[-129.50668334960938,53.21666145324707],[-129.80722045898438,53.384164810180664],[-129.8839111328125,53.579721450805664],[-130.05639457702637,53.60388374328613],[-129.92820739746094,53.639604568481445],[-130.28640747070312,53.83749580383301],[-129.82611083984375,53.72416114807129]]],[[[-79.86416625976562,53.906381607055664],[-79.90611267089844,53.91388130187988],[-79.9263916015625,53.93526649475098],[-79.86416625976562,53.906381607055664]]],[[[-130.14974975585938,53.98916053771973],[-130.193603515625,54.079721450805664],[-130.13247680664062,54.049997329711914],[-130.14974975585938,53.98916053771973]]],[[[-130.25918579101562,54.004716873168945],[-130.7127685546875,53.86110877990723],[-130.4111328125,54.10083198547363],[-130.25918579101562,54.004716873168945]]],[[[-58.518333435058594,54.05166053771973],[-58.56138610839844,54.06388282775879],[-58.37388610839844,54.10416603088379],[-58.518333435058594,54.05166053771973]]],[[[-132.80804443359375,54.12027168273926],[-132.15029907226562,53.99276924133301],[-132.663330078125,53.6794376373291],[-132.41806030273438,53.60610389709473],[-131.66305541992188,54.1522159576416],[-131.98220825195312,53.251665115356445],[-132.27279663085938,53.210275650024414],[-132.12191772460938,53.18943214416504],[-132.18695068359375,53.16054725646973],[-132.45748901367188,53.145273208618164],[-132.53668212890625,53.17888069152832],[-132.59664916992188,53.24749183654785],[-132.68362426757812,53.256662368774414],[-132.5433349609375,53.33055305480957],[-132.73388671875,53.33721351623535],[-132.40667724609375,53.3397159576416],[-132.97250366210938,53.55582618713379],[-133.0716552734375,54.16888618469238],[-132.80804443359375,54.12027168273926]]],[[[-130.195556640625,54.118051528930664],[-130.2528076171875,54.18554878234863],[-130.15194702148438,54.154436111450195],[-130.195556640625,54.118051528930664]]],[[[-79.4697265625,54.167497634887695],[-79.47555541992188,54.19137763977051],[-79.41305541992188,54.191659927368164],[-79.4697265625,54.167497634887695]]],[[[-130.64862060546875,54.11444282531738],[-130.78500366210938,54.14999580383301],[-130.78167724609375,54.2116641998291],[-130.64862060546875,54.11444282531738]]],[[[-130.35556030273438,54.25777626037598],[-130.46722412109375,54.308603286743164],[-130.41778564453125,54.32638740539551],[-130.35556030273438,54.25777626037598]]],[[[-130.26641845703125,54.26055335998535],[-130.35028076171875,54.305551528930664],[-130.27279663085938,54.329721450805664],[-130.26641845703125,54.26055335998535]]],[[[-130.70416259765625,54.35666084289551],[-130.76779174804688,54.38499641418457],[-130.69943237304688,54.40665626525879],[-130.70416259765625,54.35666084289551]]],[[[-57.32472229003906,54.49888038635254],[-57.26721954345703,54.58555030822754],[-57.24028015136719,54.517770767211914],[-57.32472229003906,54.49888038635254]]],[[[-130.95166015625,54.45471382141113],[-130.92556762695312,54.61944007873535],[-130.74777221679688,54.62610054016113],[-130.95166015625,54.45471382141113]]],[[[-79.66722106933594,54.76388740539551],[-79.72694396972656,54.75249671936035],[-79.58721923828125,54.79916572570801],[-79.66722106933594,54.76388740539551]]],[[[-130.51834106445312,54.70249366760254],[-130.61166381835938,54.7580509185791],[-130.46945190429688,54.80777168273926],[-130.51834106445312,54.70249366760254]]],[[[-130.26834106445312,54.71499824523926],[-130.37887573242188,54.695268630981445],[-130.20944213867188,54.80777168273926],[-130.26834106445312,54.71499824523926]]],[[[-57.940834045410156,54.911935806274414],[-57.84166717529297,54.8124942779541],[-58.22471618652344,54.83526802062988],[-57.940834045410156,54.911935806274414]]],[[[-79.12582397460938,54.89721870422363],[-79.77694702148438,54.77804756164551],[-79.0150146484375,54.93832588195801],[-79.12582397460938,54.89721870422363]]],[[[-58.67527770996094,54.91415596008301],[-58.76055908203125,54.920549392700195],[-58.6602783203125,55.00860786437988],[-58.67527770996094,54.91415596008301]]],[[[-130.38528442382812,54.76999092102051],[-130.45999145507812,54.82833290100098],[-130.1683349609375,55.01971626281738],[-130.38528442382812,54.76999092102051]]],[[[-82.9647216796875,55.26361274719238],[-83.0352783203125,55.278879165649414],[-82.9808349609375,55.278879165649414],[-82.9647216796875,55.26361274719238]]],[[[-77.5927734375,55.43526649475098],[-77.6441650390625,55.42582893371582],[-77.19999694824219,55.65027046203613],[-77.5927734375,55.43526649475098]]],[[[-60.97083282470703,55.86944007873535],[-61.070556640625,55.93860054016113],[-60.90833282470703,55.898332595825195],[-60.97083282470703,55.86944007873535]]],[[[-60.858612060546875,55.86471748352051],[-60.86500358581543,55.952775955200195],[-60.68638610839844,55.92193794250488],[-60.858612060546875,55.86471748352051]]],[[[-79.123046875,55.789995193481445],[-78.95750427246094,56.08360481262207],[-78.93971252441406,56.02527046203613],[-79.123046875,55.789995193481445]]],[[[-60.943328857421875,56.006662368774414],[-61.23277282714844,56.09110450744629],[-61.08916473388672,56.169992446899414],[-60.943328857421875,56.006662368774414]]],[[[-61.62361145019531,56.39999580383301],[-61.41221618652344,56.32666206359863],[-61.796112060546875,56.41304969787598],[-61.62361145019531,56.39999580383301]]],[[[-78.83999633789062,56.12999153137207],[-78.66722106933594,56.439714431762695],[-78.6763916015625,56.181108474731445],[-78.83999633789062,56.12999153137207]]],[[[-79.6199951171875,56.385271072387695],[-80.10972595214844,56.197771072387695],[-79.5433349609375,56.52777290344238],[-79.6199951171875,56.385271072387695]]],[[[-61.435829162597656,56.54138374328613],[-61.148887634277344,56.44110298156738],[-61.64222717285156,56.48638343811035],[-61.435829162597656,56.54138374328613]]],[[[-79.02166557312012,56.42694282531738],[-78.92471313476562,56.419443130493164],[-78.94332885742188,56.28499794006348],[-79.19526672363281,55.89193916320801],[-78.97721862792969,56.38860511779785],[-79.2833251953125,55.86444282531738],[-79.15055847167969,56.233049392700195],[-79.47999572753906,55.8638858795166],[-79.78195190429688,55.78804969787598],[-79.5130615234375,56.13499641418457],[-79.98582458496094,55.89805030822754],[-79.46611022949219,56.5483341217041],[-79.51445007324219,56.18638038635254],[-79.28639221191406,56.57027626037598],[-79.02166557312012,56.42694282531738]],[[-79.62693786621094,56.265275955200195],[-79.56111145019531,56.29916572570801],[-79.49221801757812,56.44693946838379],[-79.62693786621094,56.265275955200195]]],[[[-79.14195251464844,56.61666297912598],[-79.28028869628906,56.65499305725098],[-79.20889282226562,56.68387794494629],[-79.14195251464844,56.61666297912598]]],[[[-61.1875,56.58610725402832],[-61.16583251953125,56.68443489074707],[-61.077781677246094,56.674997329711914],[-61.1875,56.58610725402832]]],[[[-79.56082153320312,56.61776924133301],[-79.5675048828125,56.81777381896973],[-79.47471618652344,56.689157485961914],[-79.56082153320312,56.61776924133301]]],[[[-79.88194274902344,56.743608474731445],[-79.9586181640625,56.81138038635254],[-79.8194580078125,56.84027290344238],[-79.88194274902344,56.743608474731445]]],[[[-79.75056457519531,56.90582466125488],[-79.75750732421875,56.781938552856445],[-79.82376861572266,56.89500617980957],[-79.89750671386719,56.88499641418457],[-79.75056457519531,56.90582466125488]]],[[[-61.4292106628418,56.92970848083496],[-61.40913772583008,56.615610122680664],[-61.64439392089844,56.73477745056152],[-61.4292106628418,56.92970848083496]]],[[[-76.62110900878906,57.0755558013916],[-76.7086181640625,57.18832588195801],[-76.66999816894531,57.20249366760254],[-76.62110900878906,57.0755558013916]]],[[[-61.621665954589844,57.33555030822754],[-61.76860809326172,57.32499885559082],[-61.72694396972656,57.37443733215332],[-61.621665954589844,57.33555030822754]]],[[[-76.71501159667969,57.29277229309082],[-76.82167053222656,57.4294376373291],[-76.73110961914062,57.38193702697754],[-76.71501159667969,57.29277229309082]]],[[[-61.6552734375,57.39138221740723],[-61.90027618408203,57.4374942779541],[-61.64805603027344,57.53027534484863],[-61.6552734375,57.39138221740723]]],[[[-61.878334045410156,57.46305274963379],[-62.02027893066406,57.5402774810791],[-61.78361511230469,57.550546646118164],[-61.878334045410156,57.46305274963379]]],[[[-79.79750061035156,57.41888618469238],[-79.82695007324219,57.53804969787598],[-79.727783203125,57.61721229553223],[-79.79750061035156,57.41888618469238]]],[[[-61.68860626220703,57.71305274963379],[-61.89611053466797,57.76971626281738],[-61.71111297607422,57.83416175842285],[-61.68860626220703,57.71305274963379]]],[[[-61.94749450683594,57.78721809387207],[-62.10833740234375,57.824716567993164],[-62.00917053222656,57.904436111450195],[-61.92833709716797,57.90860176086426],[-61.94749450683594,57.78721809387207]]],[[[-67.59611511230469,58.28416633605957],[-67.67666625976562,58.3013858795166],[-67.6199951171875,58.37221717834473],[-67.51750183105469,58.33526802062988],[-67.59611511230469,58.28416633605957]]],[[[-78.45388793945312,58.539995193481445],[-78.67250061035156,58.610551834106445],[-78.6986083984375,58.68860054016113],[-78.45388793945312,58.539995193481445]]],[[[-69.19444274902344,59.064714431762695],[-69.35556030273438,58.949716567993164],[-69.35722351074219,59.139719009399414],[-69.19444274902344,59.064714431762695]]],[[[-80.53443908691406,59.36944007873535],[-80.5494384765625,59.44693946838379],[-80.47555541992188,59.48110389709473],[-80.53443908691406,59.36944007873535]]],[[[-80.27749633789062,59.618600845336914],[-80.34388732910156,59.619157791137695],[-80.14527893066406,59.70555305480957],[-80.27749633789062,59.618600845336914]]],[[[-80.0897216796875,59.75193977355957],[-80.18472290039062,59.75277900695801],[-79.87887573242188,59.85471534729004],[-80.0897216796875,59.75193977355957]]],[[[-64.01972961425781,59.7147159576416],[-64.20445251464844,59.73443794250488],[-64.06138610839844,59.86444282531738],[-64.01972961425781,59.7147159576416]]],[[[-64.42767333984375,60.372934341430664],[-64.4486083984375,60.28416633605957],[-64.86805725097656,60.45888710021973],[-64.42767333984375,60.372934341430664]]],[[[-68.25140380859375,60.23082160949707],[-68.11915588378906,60.577219009399414],[-67.79861450195312,60.45749855041504],[-68.25140380859375,60.23082160949707]]],[[[-64.68998718261719,60.58443641662598],[-64.71083068847656,60.6027774810791],[-64.5927734375,60.68554878234863],[-64.68998718261719,60.58443641662598]]],[[[-78.65638732910156,60.702775955200195],[-78.57362365722656,60.78416633605957],[-78.21945190429688,60.82388496398926],[-78.65638732910156,60.702775955200195]]],[[[-69.97721862792969,60.933053970336914],[-70.02500915527344,61.00193977355957],[-69.943603515625,61.031381607055664],[-69.97721862792969,60.933053970336914]]],[[[-64.72389221191406,61.53833198547363],[-64.87527465820312,61.32249641418457],[-65.4869384765625,61.61082649230957],[-64.72389221191406,61.53833198547363]]],[[[-65.69526672363281,61.77665901184082],[-65.94804382324219,61.7902774810791],[-65.77806091308594,61.865549087524414],[-65.69526672363281,61.77665901184082]]],[[[-64.91610717773438,61.719438552856445],[-65.2550048828125,61.90165901184082],[-64.9808349609375,61.88582801818848],[-64.91610717773438,61.719438552856445]]],[[[-92.96389770507812,61.879159927368164],[-93.07028198242188,61.825273513793945],[-93.22610473632812,61.90832710266113],[-92.96389770507812,61.879159927368164]]],[[[-65.85249328613281,62.08471870422363],[-66.02027893066406,62.12443733215332],[-65.90444946289062,62.15277290344238],[-65.85249328613281,62.08471870422363]]],[[[-92.22361755371094,62.35555458068848],[-92.37249755859375,62.39193916320801],[-92.13972473144531,62.39972114562988],[-92.22361755371094,62.35555458068848]]],[[[-79.54055786132812,62.41110420227051],[-79.26139831542969,62.16360664367676],[-79.65695190429688,61.64249610900879],[-80.27528381347656,61.806657791137695],[-80.01750183105469,62.35860633850098],[-79.54055786132812,62.41110420227051]]],[[[-92.41111755371094,62.39388465881348],[-92.60055541992188,62.38694190979004],[-92.53111267089844,62.43138313293457],[-92.41111755371094,62.39388465881348]]],[[[-64.65388488769531,62.54083442687988],[-64.38276672363281,62.51138496398926],[-64.96583557128906,62.465829849243164],[-64.65388488769531,62.54083442687988]]],[[[-64.98306274414062,62.52804756164551],[-65.14167785644531,62.546945571899414],[-64.83944702148438,62.577775955200195],[-64.98306274414062,62.52804756164551]]],[[[-77.80526733398438,62.59249305725098],[-77.62138366699219,62.58443641662598],[-77.74526977539062,62.53416633605957],[-77.80526733398438,62.59249305725098]]],[[[-78.00834655761719,62.59360694885254],[-77.83778381347656,62.55694007873535],[-78.11305236816406,62.562211990356445],[-78.00834655761719,62.59360694885254]]],[[[-91.57278442382812,62.62748908996582],[-91.66806030273438,62.6491641998291],[-91.685546875,62.666940689086914],[-91.57278442382812,62.62748908996582]]],[[[-90.97999572753906,62.65777015686035],[-91.2711181640625,62.67999458312988],[-91.08029174804688,62.68693733215332],[-90.97999572753906,62.65777015686035]]],[[[-74.3477783203125,62.6794376373291],[-73.95805358886719,62.612497329711914],[-74.65139770507812,62.716936111450195],[-74.3477783203125,62.6794376373291]]],[[[-70.711669921875,62.81499671936035],[-70.21112060546875,62.57916450500488],[-71.24137878417969,62.88138008117676],[-70.711669921875,62.81499671936035]]],[[[-66.36833190917969,62.83526802062988],[-66.60166931152344,62.90665626525879],[-66.54777526855469,62.91054725646973],[-66.36833190917969,62.83526802062988]]],[[[-81.87110900878906,62.92833137512207],[-83.08778381347656,62.17888069152832],[-83.70388793945312,62.14166450500488],[-83.94526672363281,62.42721748352051],[-83.31082153320312,62.92444038391113],[-81.87110900878906,62.92833137512207]]],[[[-66.8255615234375,62.98416328430176],[-67.0694580078125,63.107500076293945],[-66.94610595703125,63.07499885559082],[-66.8255615234375,62.98416328430176]]],[[[-67.76445007324219,63.162492752075195],[-67.875,63.22304725646973],[-67.83195495605469,63.244157791137695],[-67.76445007324219,63.162492752075195]]],[[[-67.92500305175781,63.18332862854004],[-67.96694946289062,63.18387794494629],[-68.11221313476562,63.313608169555664],[-67.92500305175781,63.18332862854004]]],[[[-78.07972717285156,63.469438552856445],[-77.4949951171875,63.26583290100098],[-77.9466552734375,63.09110450744629],[-78.57278442382812,63.44027137756348],[-78.07972717285156,63.469438552856445]]],[[[-90.65388488769531,63.44110298156738],[-90.75723266601562,63.49444007873535],[-90.59805297851562,63.45443916320801],[-90.65388488769531,63.44110298156738]]],[[[-78.5574951171875,63.45749855041504],[-78.51583862304688,63.53166389465332],[-78.461669921875,63.50750160217285],[-78.5574951171875,63.45749855041504]]],[[[-90.79360961914062,63.494157791137695],[-90.96833801269531,63.55027198791504],[-90.67471313476562,63.51388740539551],[-90.79360961914062,63.494157791137695]]],[[[-72.1824951171875,63.51999092102051],[-72.28666687011719,63.583330154418945],[-72.12916564941406,63.55888557434082],[-72.1824951171875,63.51999092102051]]],[[[-64.09249877929688,63.48166084289551],[-64.21278381347656,63.623605728149414],[-64.09333801269531,63.56833076477051],[-64.09249877929688,63.48166084289551]]],[[[-76.810546875,63.60110664367676],[-76.54194641113281,63.46249580383301],[-77.45722961425781,63.643327713012695],[-76.810546875,63.60110664367676]]],[[[-64.06111145019531,63.27054786682129],[-64.47917175292969,63.63694190979004],[-64.32888793945312,63.64444160461426],[-64.06111145019531,63.27054786682129]]],[[[-68.65638732910156,63.62638282775879],[-68.82167053222656,63.65249061584473],[-68.67694091796875,63.6713809967041],[-68.65638732910156,63.62638282775879]]],[[[-72.5947265625,63.64249610900879],[-72.7833251953125,63.664438247680664],[-72.45973205566406,63.67916297912598],[-72.5947265625,63.64249610900879]]],[[[-71.79916381835938,63.615549087524414],[-71.86332702636719,63.61944007873535],[-71.86416625976562,63.669443130493164],[-71.77944946289062,63.68832588195801],[-71.79916381835938,63.615549087524414]]],[[[-64.03250122070312,63.689714431762695],[-64.21250915527344,63.71221351623535],[-64.07528686523438,63.7580509185791],[-64.03250122070312,63.689714431762695]]],[[[-72.66777038574219,63.69582557678223],[-72.7197265625,63.76388740539551],[-72.62666320800781,63.73221015930176],[-72.66777038574219,63.69582557678223]]],[[[-64.28443908691406,63.70860481262207],[-64.381103515625,63.80749702453613],[-64.27861022949219,63.770830154418945],[-64.28443908691406,63.70860481262207]]],[[[-64.57611083984375,63.78082466125488],[-64.38612365722656,63.70166206359863],[-64.92027282714844,63.824716567993164],[-64.57611083984375,63.78082466125488]]],[[[-64.17027282714844,63.85638618469238],[-64.23443603515625,63.771379470825195],[-64.399169921875,63.849435806274414],[-64.17027282714844,63.85638618469238]]],[[[-77.74388122558594,63.92666053771973],[-77.98249816894531,63.983049392700195],[-77.54444885253906,64.02192878723145],[-77.74388122558594,63.92666053771973]]],[[[-89.80888366699219,64.05636787414551],[-89.86111450195312,64.07165718078613],[-89.86776733398438,64.09582710266113],[-89.80888366699219,64.05636787414551]]],[[[-64.96278381347656,64.11081123352051],[-64.8699951171875,64.09332466125488],[-65.0574951171875,64.11303901672363],[-64.96278381347656,64.11081123352051]]],[[[-64.49110412597656,64.1091480255127],[-64.59584045410156,64.15664863586426],[-64.45333862304688,64.14694404602051],[-64.49110412597656,64.1091480255127]]],[[[-73.17694091796875,64.20027351379395],[-73.28277587890625,64.1433277130127],[-73.40167236328125,64.1655445098877],[-73.17694091796875,64.20027351379395]]],[[[-81.47138977050781,64.18887519836426],[-81.53805541992188,64.21805000305176],[-81.37582397460938,64.22082710266113],[-81.47138977050781,64.18887519836426]]],[[[-64.52027893066406,64.22026252746582],[-64.64778137207031,64.25000190734863],[-64.46221923828125,64.23748970031738],[-64.52027893066406,64.22026252746582]]],[[[-64.9385986328125,64.23553657531738],[-65.11250305175781,64.33970832824707],[-64.88473510742188,64.28776741027832],[-64.9385986328125,64.23553657531738]]],[[[-75.5513916015625,64.30386543273926],[-75.70584106445312,64.3419361114502],[-75.49360656738281,64.31637763977051],[-75.5513916015625,64.30386543273926]]],[[[-73.87638854980469,64.30137825012207],[-73.97250366210938,64.3097095489502],[-73.9566650390625,64.36831855773926],[-73.87638854980469,64.30137825012207]]],[[[-73.69776916503906,64.26999092102051],[-73.8336181640625,64.33166694641113],[-73.78138732910156,64.40555000305176],[-73.69776916503906,64.26999092102051]]],[[[-64.8497314453125,64.30748176574707],[-64.9586181640625,64.40582466125488],[-64.77194213867188,64.34887886047363],[-64.8497314453125,64.30748176574707]]],[[[-74.27194213867188,64.41360664367676],[-74.43943786621094,64.45332527160645],[-74.17332458496094,64.43914985656738],[-74.27194213867188,64.41360664367676]]],[[[-73.7449951171875,64.42608833312988],[-73.78138732910156,64.43193244934082],[-73.77333068847656,64.50332832336426],[-73.66860961914062,64.46443367004395],[-73.7449951171875,64.42608833312988]]],[[[-74.21278381347656,64.4830493927002],[-74.35777282714844,64.55108833312988],[-74.16972351074219,64.52388191223145],[-74.21278381347656,64.4830493927002]]],[[[-73.5574951171875,64.3127613067627],[-73.6824951171875,64.50972175598145],[-73.52778625488281,64.56694221496582],[-73.5574951171875,64.3127613067627]]],[[[-65.49276733398438,64.51776313781738],[-65.69027709960938,64.52415657043457],[-65.20805358886719,64.63971138000488],[-65.49276733398438,64.51776313781738]]],[[[-63.35333251953125,64.99498176574707],[-63.25889587402344,64.92109870910645],[-63.42028045654297,64.9760913848877],[-63.35333251953125,64.99498176574707]]],[[[-63.243614196777344,65.25499153137207],[-63.311668395996094,65.29803657531738],[-63.16638946533203,65.28610420227051],[-63.243614196777344,65.25499153137207]]],[[[-66.92471313476562,65.28442573547363],[-67.01055908203125,65.33333015441895],[-66.91082763671875,65.35693550109863],[-66.92471313476562,65.28442573547363]]],[[[-88.43028259277344,65.45526313781738],[-88.51222229003906,65.46971321105957],[-88.3941650390625,65.46582221984863],[-88.43028259277344,65.45526313781738]]],[[[-62.795005798339844,65.51999092102051],[-62.88444519042969,65.60554695129395],[-62.75083923339844,65.55137825012207],[-62.795005798339844,65.51999092102051]]],[[[-83.88276672363281,65.66693305969238],[-83.94221496582031,65.68692207336426],[-83.87277221679688,65.71220588684082],[-83.88276672363281,65.66693305969238]]],[[[-62.268333435058594,65.70166206359863],[-62.13194274902344,65.65721321105957],[-62.48444366455078,65.72693061828613],[-62.268333435058594,65.70166206359863]]],[[[-67.47250366210938,65.70526313781738],[-67.71583557128906,65.70166206359863],[-67.4244384765625,65.73526191711426],[-67.47250366210938,65.70526313781738]]],[[[-85.48056030273438,65.79193305969238],[-85.15638732910156,65.77665901184082],[-85.31193542480469,65.53776741027832],[-84.92471313476562,65.20971870422363],[-84.44027709960938,65.45665168762207],[-81.7630615234375,64.50110054016113],[-81.60249328613281,64.12997627258301],[-81.9869384765625,63.994157791137695],[-80.89083862304688,64.11554145812988],[-80.17166137695312,63.77110481262207],[-81.07640075683594,63.45138740539551],[-82.47222900390625,63.68027687072754],[-82.36138916015625,63.9052677154541],[-83.09889221191406,63.95916175842285],[-83.07278442382812,64.18664741516113],[-85.26640319824219,63.11749458312988],[-85.58917236328125,63.17471504211426],[-85.71749877929688,63.71610450744629],[-87.18804931640625,63.58999061584473],[-86.18943786621094,64.10165596008301],[-86.40167236328125,64.43664741516113],[-86.0977783203125,65.52916145324707],[-85.48056030273438,65.79193305969238]]],[[[-83.28388977050781,65.83415412902832],[-83.48527526855469,65.80081367492676],[-83.58612060546875,65.85415840148926],[-83.28388977050781,65.83415412902832]]],[[[-65.64584350585938,65.81303596496582],[-65.64778137207031,65.87997627258301],[-65.51139831542969,65.90304756164551],[-65.64584350585938,65.81303596496582]]],[[[-62.13666534423828,65.85138130187988],[-62.296669006347656,65.93858528137207],[-62.137779235839844,65.92581367492676],[-62.13666534423828,65.85138130187988]]],[[[-67.13833618164062,65.92692756652832],[-67.21194458007812,65.98275947570801],[-67.15388488769531,65.97859382629395],[-67.13833618164062,65.92692756652832]]],[[[-84.7227783203125,65.54609870910645],[-85.17304992675781,65.99470710754395],[-84.586669921875,65.69220161437988],[-84.7227783203125,65.54609870910645]]],[[[-83.57695007324219,65.9830493927002],[-83.60444641113281,65.98776435852051],[-83.49305725097656,66.01277351379395],[-83.57695007324219,65.9830493927002]]],[[[-83.60861206054688,66.04414558410645],[-83.65361022949219,66.04136848449707],[-83.60722351074219,66.07748603820801],[-83.57084655761719,66.05636787414551],[-83.60861206054688,66.04414558410645]]],[[[-85.0191650390625,66.05720710754395],[-85.149169921875,66.05053901672363],[-85.0997314453125,66.08970832824707],[-85.0191650390625,66.05720710754395]]],[[[-83.64944458007812,66.08360481262207],[-83.68527221679688,66.12109565734863],[-83.58778381347656,66.1172046661377],[-83.64944458007812,66.08360481262207]]],[[[-83.92138671875,66.00972175598145],[-83.69415283203125,65.9246997833252],[-83.72749328613281,65.79971504211426],[-83.21083068847656,65.7058277130127],[-83.8427734375,65.64915657043457],[-83.68276977539062,65.74942207336426],[-84.14361572265625,65.76416206359863],[-84.12361145019531,65.90027046203613],[-84.47027587890625,66.13333320617676],[-83.92138671875,66.00972175598145]]],[[[-84.57972717285156,66.1413745880127],[-84.63999938964844,66.14055061340332],[-84.67860412597656,66.18248176574707],[-84.57972717285156,66.1413745880127]]],[[[-84.26528930664062,66.17776679992676],[-84.36361694335938,66.20942878723145],[-84.27305603027344,66.19664192199707],[-84.26528930664062,66.17776679992676]]],[[[-62.18388366699219,66.2371997833252],[-62.43000030517578,66.22915840148926],[-62.26167297363281,66.28027534484863],[-62.18388366699219,66.2371997833252]]],[[[-83.06723022460938,66.25555610656738],[-83.29833984375,66.31387519836426],[-82.90249633789062,66.27165412902832],[-83.06723022460938,66.25555610656738]]],[[[-66.62332153320312,66.28082466125488],[-66.95834350585938,66.41192817687988],[-66.57501220703125,66.31387519836426],[-66.62332153320312,66.28082466125488]]],[[[-66.99833679199219,66.49304389953613],[-66.86888122558594,66.46443367004395],[-67.03666687011719,66.45610237121582],[-66.99833679199219,66.49304389953613]]],[[[-107.92304992675781,66.85054206848145],[-107.79499816894531,66.9972095489502],[-107.82389831542969,66.90109443664551],[-107.92304992675781,66.85054206848145]]],[[[-63.059165954589844,66.95776557922363],[-63.166107177734375,67.00499153137207],[-63,66.98442268371582],[-63.059165954589844,66.95776557922363]]],[[[-108.01445007324219,66.89776802062988],[-108.10659790039062,67.02600288391113],[-107.93831634521484,66.94693183898926],[-108.01445007324219,66.89776802062988]]],[[[-62.9183349609375,67.00972175598145],[-63.13805389404297,67.06526374816895],[-63.002227783203125,67.06944465637207],[-62.9183349609375,67.00972175598145]]],[[[-62.6441650390625,67.05748176574707],[-62.899444580078125,67.05832099914551],[-62.375274658203125,67.16581916809082],[-62.6441650390625,67.05748176574707]]],[[[-107.40778350830078,67.08305549621582],[-107.52778625488281,67.07805061340332],[-107.62666320800781,67.20027351379395],[-107.40778350830078,67.08305549621582]]],[[[-95.36166381835938,67.19775581359863],[-95.55278015136719,67.23526191711426],[-95.30722045898438,67.25248908996582],[-95.36166381835938,67.19775581359863]]],[[[-107.66278076171875,67.22026252746582],[-107.72501373291016,67.31303596496582],[-107.66000366210938,67.29887580871582],[-107.66278076171875,67.22026252746582]]],[[[-63.36639404296875,67.28776741027832],[-63.82972717285156,67.28415107727051],[-63.58583068847656,67.35331916809082],[-63.36639404296875,67.28776741027832]]],[[[-107.91082763671875,67.31053352355957],[-108.07389831542969,67.43081855773926],[-107.89472961425781,67.48553657531738],[-107.91082763671875,67.31053352355957]]],[[[-108.36833190917969,67.46721076965332],[-108.49137878417969,67.56303596496582],[-108.29750061035156,67.55720710754395],[-108.36833190917969,67.46721076965332]]],[[[-108.14111328125,67.44999885559082],[-108.27194213867188,67.47137641906738],[-108.21916198730469,67.57110786437988],[-108.14111328125,67.44999885559082]]],[[[-108.3227767944336,67.5899829864502],[-108.48388671875,67.63665962219238],[-108.39028930664062,67.63109016418457],[-108.3227767944336,67.5899829864502]]],[[[-63.88194274902344,67.50332832336426],[-64.02972412109375,67.51388740539551],[-63.97694396972656,67.6494312286377],[-63.758056640625,67.52054023742676],[-63.88194274902344,67.50332832336426]]],[[[-108.05999755859375,67.47526741027832],[-108.11361694335938,67.67526435852051],[-107.92138671875,67.5466480255127],[-108.05999755859375,67.47526741027832]]],[[[-97.50279235839844,67.62442207336426],[-97.560546875,67.69275093078613],[-97.33778381347656,67.72415351867676],[-97.50279235839844,67.62442207336426]]],[[[-109.11221313476562,67.7633228302002],[-109.20777893066406,67.78387641906738],[-109.03916931152344,67.79332160949707],[-109.11221313476562,67.7633228302002]]],[[[-96.17054557800293,67.77304267883301],[-96.07722473144531,67.8388843536377],[-95.99749755859375,67.82083320617676],[-96.17054557800293,67.77304267883301]]],[[[-114.1150131225586,67.88388252258301],[-114.29695129394531,67.89526557922363],[-113.92138671875,67.87803840637207],[-114.1150131225586,67.88388252258301]]],[[[-113.39028930664062,67.89776802062988],[-113.60333251953125,67.90304756164551],[-113.2469482421875,67.91443061828613],[-113.39028930664062,67.89776802062988]]],[[[-112.93055725097656,67.91665840148926],[-113.14750671386719,67.91220283508301],[-112.88722229003906,67.92720222473145],[-112.93055725097656,67.91665840148926]]],[[[-108.64695739746094,67.86943244934082],[-108.54472351074219,67.92831611633301],[-108.35944366455078,67.89999580383301],[-108.64695739746094,67.86943244934082]]],[[[-114.21916198730469,67.94525337219238],[-114.31723022460938,67.94970893859863],[-114.12110900878906,67.9619312286377],[-114.21916198730469,67.94525337219238]]],[[[-108.1380615234375,67.87248420715332],[-108.25556945800781,67.88720893859863],[-108.054443359375,67.96331977844238],[-108.1380615234375,67.87248420715332]]],[[[-113.72000122070312,67.97331428527832],[-113.99305725097656,67.96110725402832],[-113.77223205566406,67.98027229309082],[-113.72000122070312,67.97331428527832]]],[[[-109.19526672363281,67.98997688293457],[-108.95111083984375,67.97331428527832],[-108.8660945892334,67.90027046203613],[-109.19526672363281,67.98997688293457]]],[[[-110.33444213867188,68.01165962219238],[-110.42083740234375,68.02083015441895],[-110.31749725341797,68.04971504211426],[-110.33444213867188,68.01165962219238]]],[[[-98.95140075683594,67.97998237609863],[-99.07861328125,68.04559516906738],[-98.97555541992188,68.07721138000488],[-98.95140075683594,67.97998237609863]]],[[[-108.50611877441406,68.03471565246582],[-108.540283203125,68.03997993469238],[-108.4474868774414,68.08777046203613],[-108.50611877441406,68.03471565246582]]],[[[-65.39723205566406,68.03997993469238],[-65.51972961425781,68.06749153137207],[-65.38639831542969,68.08831977844238],[-65.39723205566406,68.03997993469238]]],[[[-109.32167053222656,67.9810962677002],[-109.54306030273438,68.05220222473145],[-109.44721984863281,68.09221076965332],[-109.32167053222656,67.9810962677002]]],[[[-108.36054992675781,68.04971504211426],[-108.40805053710938,68.0697193145752],[-108.29444885253906,68.09721565246582],[-108.36054992675781,68.04971504211426]]],[[[-74.21556091308594,68.11775398254395],[-73.34861755371094,67.82805061340332],[-74.7772216796875,67.97387886047363],[-74.21556091308594,68.11775398254395]]],[[[-110.213623046875,68.03804206848145],[-110.25862121582031,68.04193305969238],[-109.87721252441406,68.12692451477051],[-110.213623046875,68.03804206848145]]],[[[-65.64222717285156,68.15942573547363],[-65.49554443359375,68.1283130645752],[-65.70973205566406,68.1060962677002],[-65.64222717285156,68.15942573547363]]],[[[-112.78056335449219,68.13109016418457],[-112.92223358154297,68.14665412902832],[-112.75167846679688,68.16470527648926],[-112.78056335449219,68.13109016418457]]],[[[-107.47361755371094,68.14471626281738],[-107.55416870117188,68.16609382629395],[-107.46806335449219,68.18858528137207],[-107.47361755371094,68.14471626281738]]],[[[-104.45305633544922,68.10220527648926],[-104.55387878417969,68.16165351867676],[-104.37721252441406,68.19970893859863],[-104.45305633544922,68.10220527648926]]],[[[-107.38890075683594,68.17221260070801],[-107.44526672363281,68.20166206359863],[-107.29167175292969,68.2027759552002],[-107.38890075683594,68.17221260070801]]],[[[-98.65028381347656,68.18026924133301],[-98.70445251464844,68.17608833312988],[-98.69332885742188,68.21360969543457],[-98.65028381347656,68.18026924133301]]],[[[-111.83332824707031,68.18193244934082],[-111.86554718017578,68.18803596496582],[-111.75499725341797,68.21582221984863],[-111.83332824707031,68.18193244934082]]],[[[-96.38417053222656,68.2008228302002],[-96.46278381347656,68.21609687805176],[-96.3175048828125,68.23193550109863],[-96.38417053222656,68.2008228302002]]],[[[-74.06277465820312,68.15165901184082],[-74.1763916015625,68.20416450500488],[-74.07972717285156,68.23248481750488],[-74.06277465820312,68.15165901184082]]],[[[-108.59028625488281,68.21443367004395],[-108.677490234375,68.16887092590332],[-108.55972290039062,68.2361011505127],[-108.59028625488281,68.21443367004395]]],[[[-66.31361389160156,68.14776802062988],[-66.60722351074219,68.21721076965332],[-66.22193908691406,68.24109077453613],[-66.31361389160156,68.14776802062988]]],[[[-109.78388977050781,68.13749885559082],[-109.85665893554688,68.14776802062988],[-109.56806945800781,68.2472095489502],[-109.78388977050781,68.13749885559082]]],[[[-78.57167053222656,68.20027351379395],[-78.66221618652344,68.18914985656738],[-78.54804992675781,68.26304817199707],[-78.57167053222656,68.20027351379395]]],[[[-111.71028137207031,68.22053718566895],[-111.7772216796875,68.25305366516113],[-111.49944305419922,68.29693794250488],[-111.71028137207031,68.22053718566895]]],[[[-75.58277893066406,68.30026435852051],[-75.00306701660156,68.13220405578613],[-75.1986083984375,67.44331550598145],[-76.66361999511719,67.2199878692627],[-77.2469482421875,67.45193672180176],[-77.251953125,67.82638740539551],[-76.72610473632812,68.23887825012207],[-75.58277893066406,68.30026435852051]]],[[[-86.4263916015625,68.06915473937988],[-86.5836181640625,67.72526741027832],[-86.99276733398438,68.0666675567627],[-86.67500305175781,68.30609321594238],[-86.4263916015625,68.06915473937988]]],[[[-79.02055358886719,68.16914558410645],[-79.19110107421875,68.31944465637207],[-78.80166625976562,68.27916145324707],[-79.02055358886719,68.16914558410645]]],[[[-100.07472229003906,68.34971809387207],[-100.09944152832031,68.27859687805176],[-100.23082733154297,68.3197193145752],[-100.07472229003906,68.34971809387207]]],[[[-82.05999755859375,68.30609321594238],[-82.34555053710938,68.36775398254395],[-81.99722290039062,68.34137153625488],[-82.05999755859375,68.30609321594238]]],[[[-111.11444091796875,68.40582466125488],[-111.149169921875,68.43997383117676],[-111.0824966430664,68.44470405578613],[-111.11444091796875,68.40582466125488]]],[[[-74.16221618652344,68.24609565734863],[-74.39306640625,68.44525337219238],[-74.07945251464844,68.33859443664551],[-74.16221618652344,68.24609565734863]]],[[[-99.04527282714844,68.42387580871582],[-99.05499267578125,68.40832710266113],[-99.15916442871094,68.45109748840332],[-99.04527282714844,68.42387580871582]]],[[[-100.71056365966797,68.4024829864502],[-100.88971710205078,68.4527759552002],[-100.79332733154297,68.46887397766113],[-100.71056365966797,68.4024829864502]]],[[[-110.86250305175781,68.47415351867676],[-111.09750366210938,68.48275947570801],[-110.69611358642578,68.48637580871582],[-110.86250305175781,68.47415351867676]]],[[[-110.5869369506836,68.52415657043457],[-110.76194763183594,68.56164741516113],[-110.51834106445312,68.53915596008301],[-110.5869369506836,68.52415657043457]]],[[[-104.54527282714844,68.39610481262207],[-105.08168029785156,68.54637336730957],[-104.68250274658203,68.57388496398926],[-104.54527282714844,68.39610481262207]]],[[[-105.1391830444336,68.53637886047363],[-105.05888366699219,68.5041675567627],[-105.29222106933594,68.58221626281738],[-105.1391830444336,68.53637886047363]]],[[[-113.78611755371094,68.58276557922363],[-113.96611022949219,68.6111011505127],[-113.76194763183594,68.59221076965332],[-113.78611755371094,68.58276557922363]]],[[[-100.74054718017578,68.59637641906738],[-100.88249206542969,68.61137580871582],[-100.81388854980469,68.61914253234863],[-100.74054718017578,68.59637641906738]]],[[[-78.46888732910156,68.56387519836426],[-78.95973205566406,68.47470283508301],[-78.8638916015625,68.65971565246582],[-78.46888732910156,68.56387519836426]]],[[[-74.81138610839844,68.32054328918457],[-75.39695739746094,68.6111011505127],[-75,68.67224311828613],[-74.81138610839844,68.32054328918457]]],[[[-74.76889038085938,68.67387580871582],[-74.51834106445312,68.55859565734863],[-74.89028930664062,68.62498664855957],[-74.76889038085938,68.67387580871582]]],[[[-114.04723358154297,68.61360359191895],[-114.18998718261719,68.68026924133301],[-114.14195251464844,68.67692756652832],[-114.04723358154297,68.61360359191895]]],[[[-101.83112335205078,68.56694221496582],[-102.31639099121094,68.67221260070801],[-101.69387817382812,68.76805305480957],[-101.83112335205078,68.56694221496582]]],[[[-68.11027526855469,68.78276252746582],[-67.66139221191406,68.70193672180176],[-68.45944213867188,68.79109382629395],[-68.11027526855469,68.78276252746582]]],[[[-102.600830078125,68.81331062316895],[-102.70722961425781,68.8166675567627],[-102.61277770996094,68.84305000305176],[-102.600830078125,68.81331062316895]]],[[[-89.94444274902344,68.66220283508301],[-89.94444274902344,68.84749031066895],[-89.78167724609375,68.76666450500488],[-89.94444274902344,68.66220283508301]]],[[[-114.350830078125,68.87164497375488],[-114.4716567993164,68.89248847961426],[-114.32333374023438,68.88304328918457],[-114.350830078125,68.87164497375488]]],[[[-67.8477783203125,68.85193061828613],[-67.96055603027344,68.92997932434082],[-67.87638854980469,68.94941902160645],[-67.8477783203125,68.85193061828613]]],[[[-100.17555236816406,68.79471015930176],[-100.623046875,68.76193428039551],[-100.59999084472656,69.00055122375488],[-100.17555236816406,68.79471015930176]]],[[[-85.3416748046875,68.98359870910645],[-85.45306396484375,69.00583076477051],[-85.3699951171875,69.00193977355957],[-85.3416748046875,68.98359870910645]]],[[[-89.90834045410156,68.91775703430176],[-90.070556640625,68.98193550109863],[-89.92083740234375,69.0102710723877],[-89.90834045410156,68.91775703430176]]],[[[-85.11944580078125,69.01471138000488],[-85.17027282714844,69.03581428527832],[-85.06138610839844,69.03665351867676],[-85.11944580078125,69.01471138000488]]],[[[-85.26528930664062,69.07249641418457],[-85.39889526367188,69.08610725402832],[-85.241943359375,69.09137153625488],[-85.26528930664062,69.07249641418457]]],[[[-99.99943542480469,68.94359016418457],[-100.25862121582031,69.04193305969238],[-100.05304718017578,69.10247993469238],[-99.99943542480469,68.94359016418457]]],[[[-90.12471008300781,69.04942512512207],[-90.27639770507812,69.12581062316895],[-90.14723205566406,69.10359382629395],[-90.12471008300781,69.04942512512207]]],[[[-101.66416931152344,69.08360481262207],[-101.69526672363281,69.20694160461426],[-101.49500274658203,69.1655445098877],[-101.66416931152344,69.08360481262207]]],[[[-90.51251220703125,69.20248603820801],[-90.77583312988281,69.32998847961426],[-90.58250427246094,69.35971260070801],[-90.51251220703125,69.20248603820801]]],[[[-78.41221618652344,69.37970161437988],[-78.21083068847656,69.29443550109863],[-78.83029174804688,68.91304206848145],[-79.40028381347656,68.87191963195801],[-78.41221618652344,69.37970161437988]]],[[[-135.28890991210938,69.30941963195801],[-135.5655517578125,69.39055061340332],[-135.3377685546875,69.38859748840332],[-135.28890991210938,69.30941963195801]]],[[[-76.95083618164062,69.39526557922363],[-76.64666557312012,69.3369312286377],[-77.38194274902344,69.24748420715332],[-76.95083618164062,69.39526557922363]]],[[[-90.32945251464844,69.23581123352051],[-90.51445007324219,69.36387825012207],[-90.20083618164062,69.44442939758301],[-90.32945251464844,69.23581123352051]]],[[[-135.59222412109375,69.48221015930176],[-135.57443237304688,69.44664192199707],[-135.8155517578125,69.50248908996582],[-135.59222412109375,69.48221015930176]]],[[[-101.05304718017578,69.50444221496582],[-101.23029327392578,69.36859321594238],[-101.38722229003906,69.53776741027832],[-101.05304718017578,69.50444221496582]]],[[[-96.66305541992188,69.5697193145752],[-96.09611511230469,69.46805000305176],[-96.23388671875,69.35971260070801],[-96.66305541992188,69.5697193145752]]],[[[-67.310546875,69.54915046691895],[-67.74972534179688,69.52110481262207],[-67.48443603515625,69.59027290344238],[-67.310546875,69.54915046691895]]],[[[-95.4888916015625,69.56553840637207],[-95.51583862304688,69.3308277130127],[-95.7369384765625,69.32443428039551],[-95.66915893554688,69.50749397277832],[-95.81582641601562,69.5627613067627],[-95.99082946777344,69.35331916809082],[-95.91999816894531,69.59526252746582],[-95.4888916015625,69.56553840637207]]],[[[-96.76055908203125,69.54553413391113],[-96.88389587402344,69.55914497375488],[-96.9022216796875,69.59776496887207],[-96.76055908203125,69.54553413391113]]],[[[-91.11000061035156,69.54942512512207],[-91.10888671875,69.60220527648926],[-90.91915893554688,69.6060962677002],[-91.11000061035156,69.54942512512207]]],[[[-133.93222045898438,69.56025886535645],[-134.01666259765625,69.57609748840332],[-133.93362426757812,69.61609077453613],[-133.8447265625,69.60081672668457],[-133.93222045898438,69.56025886535645]]],[[[-135.51724243164062,69.56915473937988],[-135.58944702148438,69.59610176086426],[-135.39779663085938,69.64694404602051],[-135.51724243164062,69.56915473937988]]],[[[-138.86721801757812,69.58831977844238],[-139.33248901367188,69.56608772277832],[-139.12026977539062,69.64999580383301],[-138.86721801757812,69.58831977844238]]],[[[-67.92027282714844,69.52192878723145],[-68.24888610839844,69.59665107727051],[-67.88972473144531,69.70833015441895],[-67.92027282714844,69.52192878723145]]],[[[-134.26058959960938,68.7335376739502],[-134.49554443359375,68.7522144317627],[-134.82583618164062,68.97886848449707],[-134.91473388671875,68.96666145324707],[-134.96112060546875,68.89248847961426],[-135.1419677734375,68.9013843536377],[-135.20166015625,68.9327564239502],[-135.3919677734375,68.9266529083252],[-135.4608154296875,68.94275093078613],[-135.90585327148438,68.91137886047363],[-135.97833251953125,69.04081916809082],[-135.51779174804688,69.02388191223145],[-135.96722412109375,69.21470832824707],[-135.4869384765625,69.11331367492676],[-135.854154586792,69.29081916809082],[-135.17056274414062,69.25776863098145],[-135.2872314453125,69.41914558410645],[-135.15084838867188,69.47693061828613],[-134.43832397460938,69.45471382141113],[-134.4910888671875,69.72221565246582],[-134.11331176757812,69.53888130187988],[-133.77835083007812,69.57638740539551],[-134.67361450195312,69.01776313781738],[-134.26058959960938,68.7335376739502]]],[[[-102.14527893066406,69.64860725402832],[-102.24137878417969,69.71026802062988],[-102.1347427368164,69.72470283508301],[-102.14527893066406,69.64860725402832]]],[[[-77.9466552734375,69.64665412902832],[-78.88027954101562,69.47693061828613],[-78.18055725097656,69.7522144317627],[-77.9466552734375,69.64665412902832]]],[[[-82.50778198242188,69.70498847961426],[-82.87944030761719,69.77859687805176],[-82.46028137207031,69.76165962219238],[-82.50778198242188,69.70498847961426]]],[[[-79.42304992675781,69.78499031066895],[-80.01194763183594,69.49165534973145],[-80.80943298339844,69.68304634094238],[-79.42304992675781,69.78499031066895]]],[[[-83.6744384765625,69.7199878692627],[-83.91722106933594,69.77859687805176],[-83.5291748046875,69.78665351867676],[-83.7086181640625,69.75943183898926],[-83.6744384765625,69.7199878692627]]],[[[-82.429443359375,69.78221321105957],[-82.6885986328125,69.85081672668457],[-82.51722717285156,69.85415840148926],[-82.429443359375,69.78221321105957]]],[[[-91.81916809082031,69.82165718078613],[-91.86416625976562,69.84414863586426],[-91.63972473144531,69.85498237609863],[-91.81916809082031,69.82165718078613]]],[[[-91.52000427246094,69.73137092590332],[-91.73554992675781,69.78915596008301],[-91.40916442871094,69.87498664855957],[-91.52000427246094,69.73137092590332]]],[[[-97.39778137207031,69.68553352355957],[-95.20695495605469,68.85026741027832],[-96.53056335449219,68.44497871398926],[-99.59638977050781,69.02054023742676],[-98.39334106445312,69.30803108215332],[-98.55665588378906,69.5808277130127],[-98.00389099121094,69.4358081817627],[-98.36776733398438,69.6010913848877],[-98.01222229003906,69.88582038879395],[-97.39778137207031,69.68553352355957]]],[[[-97.32501220703125,69.88916206359863],[-97.48860168457031,69.9438648223877],[-97.22694396972656,69.87359809875488],[-97.32501220703125,69.88916206359863]]],[[[-100.8497314453125,69.92553901672363],[-100.85861206054688,69.97776985168457],[-100.80695343017578,69.98581123352051],[-100.8497314453125,69.92553901672363]]],[[[-87.09138488769531,70.15027046203613],[-86.4566650390625,70.00749397277832],[-87.37832641601562,70.09610176086426],[-87.09138488769531,70.15027046203613]]],[[[-125.05695343017578,70.11831855773926],[-125.12332153320312,70.13546943664551],[-124.95500183105469,70.16415596008301],[-125.05695343017578,70.11831855773926]]],[[[-124.679443359375,70.16165351867676],[-124.76194763183594,70.19192695617676],[-124.50527954101562,70.19832038879395],[-124.679443359375,70.16165351867676]]],[[[-112.9697265625,70.28137397766113],[-113.20361328125,70.29248237609863],[-112.94554138183594,70.28665351867676],[-112.9697265625,70.28137397766113]]],[[[-112.6552734375,70.26609992980957],[-112.76139831542969,70.2986011505127],[-112.6875,70.30636787414551],[-112.6552734375,70.26609992980957]]],[[[-100.76528930664062,70.25000190734863],[-100.85193634033203,70.32388496398926],[-100.748046875,70.31694221496582],[-100.76528930664062,70.25000190734863]]],[[[-116.80526733398438,70.50943183898926],[-116.56833457946777,70.47387886047363],[-116.71916198730469,70.47026252746582],[-116.80526733398438,70.50943183898926]]],[[[-116.28778076171875,70.55331611633301],[-116.12748718261719,70.53581428527832],[-116.4958267211914,70.52276802062988],[-116.28778076171875,70.55331611633301]]],[[[-116.56304931640625,70.53442573547363],[-116.7744369506836,70.54525947570801],[-116.50945281982422,70.55609321594238],[-116.56304931640625,70.53442573547363]]],[[[-115.92054557800293,70.54136848449707],[-116.06111145019531,70.54832649230957],[-115.80803680419922,70.57054328918457],[-115.92054557800293,70.54136848449707]]],[[[-116.87944030761719,70.54748725891113],[-117.30166625976562,70.56192207336426],[-117.19943237304688,70.59166145324707],[-116.87944030761719,70.54748725891113]]],[[[-128.08612060546875,70.60554695129395],[-128.3416748046875,70.54220771789551],[-128.23416137695312,70.65609931945801],[-128.08612060546875,70.60554695129395]]],[[[-100.23082733154297,70.45166206359863],[-100.67083740234375,70.55887031555176],[-100.65194702148438,70.66971015930176],[-100.23082733154297,70.45166206359863]]],[[[-103.17778015136719,70.62248420715332],[-103.28138732910156,70.63804817199707],[-103.21000671386719,70.6766529083252],[-103.17778015136719,70.62248420715332]]],[[[-103.350830078125,70.68719673156738],[-103.46278381347656,70.73221015930176],[-103.34111022949219,70.72026252746582],[-103.350830078125,70.68719673156738]]],[[[-71.47166442871094,71.01277351379395],[-71.95556640625,70.81833076477051],[-72.22639465332031,70.93054389953613],[-71.47166442871094,71.01277351379395]]],[[[-96.56332397460938,71.29220771789551],[-96.47250366210938,71.23221015930176],[-96.4808349609375,71.2088794708252],[-96.63861083984375,71.2260913848877],[-96.56332397460938,71.29220771789551]]],[[[-98.89555358886719,71.27777290344238],[-99.00889587402344,71.31387519836426],[-98.95584106445312,71.35220527648926],[-98.89555358886719,71.27777290344238]]],[[[-73.12054443359375,71.47970771789551],[-73.37998962402344,71.51971626281738],[-72.8175048828125,71.44497871398926],[-73.12054443359375,71.47970771789551]]],[[[-72.76083374023438,71.53193855285645],[-73.03999328613281,71.57998847961426],[-72.69583129882812,71.65109443664551],[-72.76083374023438,71.53193855285645]]],[[[-73.37026977539062,71.55443000793457],[-73.44804382324219,71.59414863586426],[-73.14889526367188,71.67997932434082],[-73.37026977539062,71.55443000793457]]],[[[-96.95889282226562,71.70443916320801],[-97.05027770996094,71.70416450500488],[-96.84445190429688,71.74414253234863],[-96.95889282226562,71.70443916320801]]],[[[-95.33999633789062,71.73137092590332],[-95.48805236816406,71.74553108215332],[-95.26583862304688,71.83665657043457],[-95.33999633789062,71.73137092590332]]],[[[-134.49554443359375,68.7522144317627],[-134.33999633789062,68.67886543273926],[-134.2269287109375,68.69413948059082],[-134.26058959960938,68.7335376739502],[-134.56222534179688,69.08276557922363],[-130.54306030273438,70.16832160949707],[-129.40335083007812,70.11775398254395],[-130.92861938476562,69.56331062316895],[-131.05307006835938,69.63720893859863],[-131.99722290039062,69.53137397766113],[-133.49081420898438,68.82165718078613],[-132.47027587890625,68.80693244934082],[-132.86944580078125,69.0627613067627],[-131.6522216796875,69.47192573547363],[-131.32470703125,69.31999397277832],[-131.16650390625,69.40493202209473],[-131.2538604736328,69.57184791564941],[-131.11053466796875,69.48533058166504],[-131.13583374023438,69.35998725891113],[-131.06394958496094,69.51239204406738],[-131.19610595703125,69.5899829864502],[-131.08306884765625,69.60054206848145],[-131.02780151367188,69.4638843536377],[-131.10888671875,69.32165718078613],[-130.95278930664062,69.54332160949707],[-130.93722534179688,69.13443183898926],[-130.3660888671875,69.68637275695801],[-128.90084838867188,69.97192573547363],[-129.16946411132812,69.82470893859863],[-128.92501831054688,69.68081855773926],[-127.51500701904297,70.22165107727051],[-128.1966552734375,70.39193916320801],[-127.99665832519531,70.59054756164551],[-125.4263916015625,69.31218147277832],[-125.08944702148438,69.44970893859863],[-125.62249755859375,69.4185962677002],[-125.11805725097656,69.48579597473145],[-125.36554718017578,69.69026374816895],[-124.82195281982422,69.71499824523926],[-125.27639770507812,69.8082447052002],[-124.79527282714844,70.00888252258301],[-125.1974868774414,70.00450325012207],[-124.43611145019531,70.15109443664551],[-124.50055694580078,69.72581672668457],[-124.04083251953125,69.70138740539551],[-124.44666290283203,69.3672046661377],[-123.46611022949219,69.38388252258301],[-122.95916557312012,69.83360481262207],[-121.68388366699219,69.7935962677002],[-117.15387725830078,68.88554573059082],[-115.59306335449219,68.97165107727051],[-114.070556640625,68.47747993469238],[-114.02333068847656,68.24136543273926],[-115.5425033569336,67.9216480255127],[-115.10360717773438,67.7966480255127],[-112.39584350585938,67.67915534973145],[-111.00583457946777,67.76500129699707],[-110.08389282226562,68.00694465637207],[-109.06582641601562,67.71415901184082],[-108.82501220703125,67.34942817687988],[-108.6552734375,67.6283130645752],[-108.48416137695312,67.34942817687988],[-108.366943359375,67.44497871398926],[-108.01528930664062,67.29304695129395],[-107.88054656982422,67.04832649230957],[-108.62277221679688,67.14999580383301],[-107.248046875,66.3499927520752],[-107.74665832519531,66.92276191711426],[-107.0836181640625,66.82054328918457],[-108.0069580078125,67.70749092102051],[-107.65110778808594,67.94053840637207],[-107.89055633544922,68.08166694641113],[-106.43195343017578,68.15304756164551],[-106.46501159667969,68.33581733703613],[-105.7397232055664,68.41526985168457],[-105.6449966430664,68.63388252258301],[-106.54387664794922,68.51193428039551],[-106.54332733154297,68.29136848449707],[-106.80278015136719,68.41443061828613],[-107.8852767944336,68.26887702941895],[-107.60305786132812,68.16526985168457],[-108.81916809082031,68.26666450500488],[-108.31416320800781,68.61137580871582],[-106.22917175292969,68.9408130645752],[-105.4869384765625,68.72943305969238],[-105.38082885742188,68.48665046691895],[-105.54110717773438,68.41276741027832],[-104.60973358154297,68.24136543273926],[-104.67027282714844,68.13859748840332],[-104.5,68.03193855285645],[-103.42166137695312,68.16665840148926],[-102.25110626220703,67.72526741027832],[-98.35444641113281,67.79609870910645],[-98.61555480957031,68.07470893859863],[-98.09445190429688,67.76609992980957],[-97.50973510742188,67.59915351867676],[-97.11915588378906,67.79248237609863],[-97.68305969238281,68.01860237121582],[-98.02999877929688,67.94192695617676],[-98.07861328125,67.83027839660645],[-98.58750915527344,68.1494312286377],[-98.32611083984375,68.17137336730957],[-98.71444702148438,68.3722095489502],[-96.4041748046875,68.31137275695801],[-96.70834350585938,68.00860786437988],[-95.98028564453125,68.25471687316895],[-96.4647216796875,67.4780445098877],[-96.09722900390625,67.46470832824707],[-96.11444091796875,67.21331977844238],[-95.56582641601562,67.37664985656738],[-95.83332824707031,67.16276741027832],[-95.32611083984375,67.02720832824707],[-95.90249633789062,66.94664192199707],[-96.46055603027344,67.06219673156738],[-95.62971496582031,66.67553901672363],[-95.90249633789062,66.94664192199707],[-95.22084045410156,66.96832466125488],[-95.163330078125,67.28720283508301],[-95.70916557312012,67.72776985168457],[-95.4727783203125,68.06053352355957],[-94.72222900390625,68.05497932434082],[-93.55332946777344,68.58638191223145],[-93.66694641113281,68.97221565246582],[-94.625,68.76138496398926],[-94.07278442382812,69.12664985656738],[-94.30332946777344,69.30497932434082],[-93.36277770996094,69.37164497375488],[-95.96083068847656,69.77804756164551],[-96.53167724609375,70.13109016418457],[-96.23277282714844,70.56219673156738],[-95.78944396972656,70.53665351867676],[-96.6119384765625,70.79443550109863],[-96.3699951171875,71.0899829864502],[-96.560546875,71.12637519836426],[-96.46722412109375,71.16526985168457],[-96.46220397949219,71.25550270080566],[-96.50389099121094,71.27720832824707],[-95.5352783203125,71.29081916809082],[-95.94305419921875,71.55359077453613],[-94.60665893554688,71.86331367492676],[-95.21749877929688,71.94497871398926],[-93.711669921875,71.76138496398926],[-92.97389221191406,71.34082221984863],[-93.02749633789062,70.85276985168457],[-91.51362609863281,70.16720771789551],[-92.26834106445312,70.2088794708252],[-92.45028686523438,70.07110786437988],[-91.93971252441406,70.02026557922363],[-92.92027282714844,69.66971015930176],[-90.30776977539062,69.45027351379395],[-91.44721984863281,69.35276985168457],[-90.43638610839844,68.87442207336426],[-90.60665893554688,68.44609260559082],[-90.27139282226562,68.23887825012207],[-89.30665588378906,69.25139045715332],[-88.05221557617188,68.82304573059082],[-87.79222106933594,68.33442878723145],[-88.39222717285156,68.2874927520752],[-88.37083435058594,67.95915412902832],[-87.35777282714844,67.26220893859863],[-87.51028442382812,67.1121997833252],[-86.52362060546875,67.35220527648926],[-85.66361999511719,68.72693061828613],[-84.78721618652344,68.73359870910645],[-85.19444274902344,68.8672046661377],[-84.52833557128906,69.01748847961426],[-85.47332763671875,69.27192878723145],[-85.33195495605469,69.77916145324707],[-85.57194519042969,69.8560962677002],[-85.06443786621094,69.76999092102051],[-84.37582397460938,69.85748481750488],[-83.70500183105469,69.70359992980957],[-82.26333618164062,69.63804817199707],[-83.22805786132812,69.5385913848877],[-81.33250427246094,69.18248176574707],[-82.05722045898438,68.87387275695801],[-81.26750183105469,68.63304328918457],[-82.63890075683594,68.4972095489502],[-81.24305725097656,67.4749927520752],[-81.50306701660156,66.99971199035645],[-83.4022216796875,66.34749031066895],[-83.97749328613281,66.58221626281738],[-83.91639709472656,66.88109016418457],[-84.14028930664062,66.70193672180176],[-84.43638610839844,66.81833076477051],[-84.37083435058594,66.97137641906738],[-84.91500854492188,67.0608081817627],[-84.63972473144531,66.9780445098877],[-85.22833251953125,66.8783130645752],[-84.60221862792969,66.9358081817627],[-84.74638366699219,66.89749336242676],[-84.50584411621094,66.8277759552002],[-84.6905517578125,66.8399829864502],[-84.46694946289062,66.78776741027832],[-84.44248962402344,66.71081733703613],[-84.14445495605469,66.68136787414551],[-83.69305419921875,66.1908130645752],[-86.77528381347656,66.52609443664551],[-85.89723205566406,66.16832160949707],[-87.39584350585938,65.32138252258301],[-89.67166137695312,65.93942451477051],[-91.42916870117188,65.95109748840332],[-86.93331909179688,65.13804817199707],[-88.11332702636719,64.13611030578613],[-90.12416076660156,64.12858772277832],[-89.81361389160156,63.937211990356445],[-90.2791748046875,64.00360298156738],[-89.96417236328125,63.81193733215332],[-90.20527458190918,63.61221504211426],[-92.48277282714844,63.81193733215332],[-92.10166931152344,63.69693946838379],[-92.4808349609375,63.5272159576416],[-91.76333618164062,63.713327407836914],[-90.741943359375,63.36082649230957],[-90.62748718261719,63.05943489074707],[-92.42083740234375,62.83138465881348],[-91.885009765625,62.59916114807129],[-92.71000671386719,62.465829849243164],[-92.47001457214355,62.146615982055664],[-93.12222290039062,62.33499336242676],[-92.76472473144531,62.219438552856445],[-93.61610412597656,61.93998908996582],[-93.23777770996094,61.7772159576416],[-93.98472595214844,61.45610237121582],[-94.67332458496094,60.52249336242676],[-94.81916809082031,59.63638496398926],[-94.78971862792969,59.09221839904785],[-94.2288818359375,58.78499794006348],[-94.36332702636719,58.218881607055664],[-94.14389038085938,58.76361274719238],[-93.1522216796875,58.73777198791504],[-92.41888427734375,57.33749580383301],[-92.8760986328125,56.90749549865723],[-90.81527709960938,57.25583076477051],[-85.71444702148438,55.631662368774414],[-85.12193298339844,55.33777046203613],[-85.42388916015625,54.990549087524414],[-85.001953125,55.29666328430176],[-82.30776977539062,55.148881912231445],[-82.29666137695312,53.01860237121582],[-81.54998779296875,52.44110298156738],[-81.88362121582031,52.1874942779541],[-80.99444580078125,52.01138496398926],[-80.43638610839844,51.46415901184082],[-81.0150146484375,51.028329849243164],[-80.12026977539062,51.29638862609863],[-79.33222961425781,50.72387886047363],[-79.75222778320312,51.18443489074707],[-79.32223510742188,51.66276741027832],[-78.85333251953125,51.165544509887695],[-79.03555297851562,51.770273208618164],[-78.5069580078125,52.46055030822754],[-79.11027526855469,53.50249671936035],[-79.04888916015625,54.18332862854004],[-79.76445007324219,54.6522159576416],[-77.74861145019531,55.30082893371582],[-77.13722229003906,55.65416145324707],[-76.538330078125,56.29777717590332],[-76.52972412109375,57.1058292388916],[-76.8619384765625,57.71915626525879],[-78.57472229003906,58.635271072387695],[-78.570556640625,58.961381912231445],[-77.67721557617188,59.39999580383301],[-77.9102783203125,59.40555000305176],[-77.77389526367188,59.70971870422363],[-77.31388854980469,59.56499671936035],[-77.427490234375,59.91471290588379],[-76.75889587402344,60.15915870666504],[-77.59222412109375,60.064157485961914],[-77.74775695800781,60.40813636779785],[-77.413330078125,60.54416084289551],[-77.83389282226562,60.63943672180176],[-77.51167297363281,60.836381912231445],[-78.19276428222656,60.79083442687988],[-77.47471618652344,61.54166603088379],[-77.99249267578125,61.7147159576416],[-78.15583801269531,62.278329849243164],[-77.50834655761719,62.561662673950195],[-74.57167053222656,62.10305213928223],[-74.75973510742188,62.20638465881348],[-73.67887878417969,62.479990005493164],[-72.01005554199219,61.67527198791504],[-72.30332946777344,61.567216873168945],[-71.57501220703125,61.60860633850098],[-71.88751220703125,61.428049087524414],[-71.38999938964844,61.137773513793945],[-70.1461181640625,61.08471870422363],[-69.927490234375,60.80777168273926],[-69.51972961425781,61.07332801818848],[-69.37193298339844,60.8044376373291],[-69.82611083984375,60.52555274963379],[-69.62471008300781,60.0674991607666],[-70.94583129882812,60.06305122375488],[-69.60055541992188,59.83305549621582],[-69.75834655761719,59.32027626037598],[-69.23472595214844,59.2338809967041],[-69.53056335449219,59.18221473693848],[-69.54750061035156,58.80804634094238],[-69.86915588378906,59.053049087524414],[-69.81582641601562,58.82388496398926],[-70.15361022949219,58.77749061584473],[-69.81889343261719,58.58860206604004],[-69.2791748046875,58.88804817199707],[-68.36054992675781,58.781938552856445],[-68.34416198730469,58.12748908996582],[-69.36904907226562,57.7652530670166],[-68.4041748046875,58.03972053527832],[-68.00334167480469,58.57638740539551],[-67.89389038085938,58.496660232543945],[-67.85749816894531,58.32027626037598],[-68.12832641601562,58.07361030578613],[-67.8013916015625,58.29666328430176],[-67.81332397460938,58.41610145568848],[-67.72389221191406,58.45888710021973],[-67.71389770507812,57.923051834106445],[-66.38861083984375,58.85054969787598],[-65.93582153320312,58.60972023010254],[-66.05888366699219,58.32027626037598],[-65.87998962402344,58.627214431762695],[-66.1038818359375,58.77360725402832],[-65.78944396972656,58.86194038391113],[-65.98860168457031,58.90360450744629],[-65.3175048828125,59.04138374328613],[-65.71806335449219,59.15304756164551],[-65.35722351074219,59.2772159576416],[-65.56138610839844,59.48610877990723],[-64.98332214355469,59.37638282775879],[-65.52778625488281,59.716936111450195],[-64.98388671875,59.762773513793945],[-65.23194885253906,59.88582801818848],[-64.85444641113281,60.36110877990723],[-64.4669189453125,60.27860450744629],[-64.82749938964844,59.98638343811035],[-64.16694641113281,60.02499580383301],[-64.26666259765625,59.77916145324707],[-64.05776977539062,59.62526893615723],[-64.116943359375,59.51749610900879],[-63.722496032714844,59.51388740539551],[-64.06221008300781,59.38249397277832],[-63.35639190673828,59.20499610900879],[-64.04388427734375,59.015275955200195],[-63.13417053222656,59.05832862854004],[-63.32500457763672,58.8558292388916],[-62.847496032714844,58.6905460357666],[-63.589439392089844,58.30082893371582],[-62.55750274658203,58.482492446899414],[-62.82805633544922,58.25222206115723],[-62.584442138671875,58.21444129943848],[-63.34083557128906,57.979990005493164],[-62.452781677246094,58.17527198791504],[-62.30694580078125,58.03110694885254],[-62.67277526855469,57.92999458312988],[-62.12749481201172,57.96805000305176],[-62.059722900390625,57.897775650024414],[-62.13805389404297,57.835824966430664],[-62.125274658203125,57.80694007873535],[-61.88444519042969,57.62693977355957],[-62.54528045654297,57.501108169555664],[-61.35833740234375,57.08749580383301],[-61.90638732910156,56.79527473449707],[-61.67250061035156,56.6199893951416],[-62.573890686035156,56.79277229309082],[-61.65833282470703,56.53750038146973],[-62.14305877685547,56.44915962219238],[-61.66138458251953,56.270273208618164],[-62.01167297363281,56.23582649230957],[-61.35083770751953,56.22221565246582],[-61.45222473144531,56.05694007873535],[-61.23750305175781,56.04277229309082],[-61.50361633300781,56.00694465637207],[-61.117774963378906,55.96610450744629],[-61.07666778564453,55.906938552856445],[-61.20166778564453,55.884164810180664],[-61.10444641113281,55.84554481506348],[-60.72972106933594,55.82943916320801],[-60.87944030761719,55.73276710510254],[-60.60194396972656,55.814714431762695],[-60.668060302734375,55.589433670043945],[-60.328887939453125,55.78166389465332],[-60.47833251953125,55.347490310668945],[-60.19554901123047,55.43138313293457],[-60.683326721191406,54.99499702453613],[-59.77916717529297,55.329721450805664],[-59.96361541748047,55.11027717590332],[-59.42778015136719,55.13582801818848],[-59.93860626220703,54.74638557434082],[-59.16138458251953,55.23694038391113],[-59.38861083984375,54.97665596008301],[-59.02361297607422,55.15665626525879],[-58.90416717529297,54.84471321105957],[-57.347496032714844,54.57943916320801],[-59.5755615234375,54.04944038391113],[-58.37194061279297,54.228044509887695],[-60.133888244628906,53.528329849243164],[-60.85694885253906,53.79277229309082],[-60.103614807128906,53.50055122375488],[-60.4183349609375,53.26944160461426],[-57.78639221191406,54.071664810180664],[-58.4183349609375,54.139719009399414],[-58.17778015136719,54.23694038391113],[-57.38417053222656,54.15054512023926],[-57.076393127441406,53.82305335998535],[-57.54999542236328,53.591936111450195],[-57.336944580078125,53.44027137756348],[-56.464691162109375,53.78227424621582],[-56.68028259277344,53.67276954650879],[-55.80805206298828,53.34054756164551],[-56.16694641113281,53.029436111450195],[-55.75750732421875,52.61444282531738],[-56.49687194824219,52.59414863586426],[-55.64861297607422,52.439714431762695],[-56.19694519042969,52.43998908996582],[-55.70166778564453,52.08221626281738],[-56.94972229003906,51.42471504211426],[-58.6280517578125,51.27555274963379],[-60.0050048828125,50.24888038635254],[-66.4697265625,50.26194190979004],[-67.375,49.327219009399414],[-69.06082153320312,48.76749610900879],[-71.29916381835938,46.74221992492676],[-68.21112060546875,48.63665962219238],[-66.30610656738281,49.18693733215332],[-64.9969482421875,49.22027015686035],[-64.22166442871094,48.898332595825195],[-64.54888916015625,48.87832832336426],[-64.24638366699219,48.488046646118164],[-65.30583190917969,48.00555610656738],[-65.9041748046875,48.205827713012695],[-66.84249877929688,47.99221992492676],[-66.35665893554688,48.07332801818848],[-65.63473510742188,47.62082862854004],[-64.79722595214844,47.80638313293457],[-65.3699951171875,47.08665657043457],[-64.79861450195312,47.07999610900879],[-64.50418090820312,46.24027442932129],[-62.461944580078125,45.612497329711914],[-61.917503356933594,45.88555335998535],[-61.26000213623047,45.51027870178223],[-61.463890075683594,45.346940994262695],[-60.9647216796875,45.31305122375488],[-63.65833282470703,44.71499824523926],[-63.63111114501953,44.43582344055176],[-64.20083618164062,44.57638740539551],[-65.48138427734375,43.46444129943848],[-66.16694641113281,43.85860633850098],[-65.84445190429688,44.57833290100098],[-66.19110107421875,44.42332649230957],[-64.48916625976562,45.33526802062988],[-64.15638732910156,44.97832679748535],[-63.36083221435547,45.36082649230957],[-64.93721008300781,45.32694435119629],[-64.27555847167969,45.799997329711914],[-64.74749755859375,46.09054756164551],[-64.77833557128906,45.60721778869629],[-65.90361022949219,45.20555305480957],[-66.00250244140625,45.4616641998291],[-66.42778015136719,45.08499336242676],[-67.20654296875,45.18303871154785],[-67.79916381835938,45.70110511779785],[-67.79499816894531,47.06999397277832],[-69.23249816894531,47.47137641906738],[-70.87860107421875,45.238603591918945],[-74.99082946777344,44.98665809631348],[-76.80194091796875,43.63360786437988],[-78.72471618652344,43.62943458557129],[-79.18472290039062,43.46554756164551],[-78.9869384765625,42.81999397277832],[-82.6966552734375,41.68387794494629],[-83.16860961914062,42.04610633850098],[-82.52139282226562,42.61888313293457],[-82.13027954101562,43.58526802062988],[-82.54306030273438,45.3558292388916],[-83.5977783203125,45.827219009399414],[-83.57749938964844,46.10527229309082],[-83.95889282226562,46.071664810180664],[-84.12638854980469,46.531938552856445],[-84.56500244140625,46.466386795043945],[-84.85694885253906,46.9022159576416],[-88.36805725097656,48.312211990356445],[-89.35665893554688,47.97971534729004],[-90.86860656738281,48.237497329711914],[-91.4183349609375,48.04110908508301],[-92.95306396484375,48.62332344055176],[-94.6058349609375,48.724435806274414],[-95.07806396484375,49.35916328430176],[-95.1541748046875,48.99943733215332],[-122.76029968261719,48.99943733215332],[-123.03431701660156,48.99943733215332],[-123.09375,48.99943733215332],[-123.24889373779297,49.27360725402832],[-122.852783203125,49.436105728149414],[-123.23638916015625,49.338884353637695],[-123.15972900390625,49.69915962219238],[-123.49249267578125,49.509721755981445],[-123.53555297851562,49.38138008117676],[-124.06806945800781,49.63388252258301],[-123.53362274169922,49.689714431762695],[-123.93499755859375,49.768327713012695],[-123.82140350341797,50.1522159576416],[-123.9263916015625,49.82583045959473],[-124.41361999511719,49.76361274719238],[-124.82972717285156,50.06193733215332],[-124.70333862304688,49.99554634094238],[-124.60138702392578,50.2388858795166],[-124.71501159667969,50.32749366760254],[-124.3477783203125,50.50249671936035],[-125.07833862304688,50.32249641418457],[-124.80583190917969,50.92083168029785],[-125.11945343017578,50.43277168273926],[-125.54811096191406,50.49205207824707],[-125.443603515625,50.71415901184082],[-125.70584106445312,50.42777442932129],[-126.27471923828125,50.631662368774414],[-125.62249755859375,50.75000190734863],[-125.63390350341797,51.096940994262695],[-125.73110961914062,50.735551834106445],[-126.1310043334961,50.678659439086914],[-126.19888305664062,50.8558292388916],[-126.55972290039062,50.843881607055664],[-126.17778015136719,50.95138740539551],[-127.538330078125,51.00555610656738],[-126.66251373291016,51.19499397277832],[-127.78999328613281,51.165544509887695],[-127.133056640625,51.3255558013916],[-127.77887725830078,51.324716567993164],[-127.48805236816406,51.61944007873535],[-126.62000274658203,51.67999458312988],[-127.43222045898438,51.6683292388916],[-127.3510971069336,51.86361122131348],[-127.70639038085938,51.45638465881348],[-127.8780517578125,51.67388343811035],[-127.17166137695312,52.3124942779541],[-126.66944885253906,51.98360633850098],[-126.94082641601562,52.30388069152832],[-126.73249816894531,52.37388038635254],[-127.18639373779297,52.38082313537598],[-127.01777458190918,52.84554481506348],[-127.61833190917969,52.291940689086914],[-128.01251220703125,52.34110450744629],[-127.87970733642578,52.579721450805664],[-128.39389038085938,52.29138374328613],[-128.221923828125,52.46527290344238],[-128.13165283203125,52.87638282775879],[-128.44110107421875,52.822771072387695],[-128.53973388671875,53.13193702697754],[-128.85888671875,53.28360939025879],[-128.8879852294922,53.42496681213379],[-128.9727783203125,53.553049087524414],[-127.86776733398438,53.23971748352051],[-128.81304931640625,53.619157791137695],[-128.47137451171875,53.83249855041504],[-128.60055541992188,54.03166389465332],[-129.23248291015625,53.62582588195801],[-129.27279663085938,53.379159927368164],[-130.05029296875,53.88694190979004],[-130.04666137695312,54.15332221984863],[-129.47000122070312,54.23721504211426],[-130.48110961914062,54.36471748352051],[-130.416654586792,54.63027381896973],[-129.95916557312012,54.31610298156738],[-130.3741455078125,54.65499305725098],[-129.9102783203125,54.60555458068848],[-130.17388916015625,54.84665870666504],[-129.62249755859375,54.99777412414551],[-129.99636840820312,55.0241641998291],[-129.47164916992188,55.46721076965332],[-129.78695678710938,55.566667556762695],[-129.8175048828125,55.283334732055664],[-130.11361694335938,54.99638557434082],[-129.94387817382812,55.28221321105957],[-130.12887573242188,55.72221565246582],[-130.01507568359375,55.90918159484863],[-131.82415771484375,56.596940994262695],[-133.42999267578125,58.45916175842285],[-135.47360229492188,59.80193519592285],[-137.47805786132812,58.90721321105957],[-137.5908203125,59.238603591918945],[-139.18890380859375,60.088884353637695],[-139.06805419921875,60.35222053527832],[-140.99554443359375,60.30721473693848],[-141.00299072265625,69.64236640930176],[-139.14306640625,69.51082038879395],[-138.60498046875,69.24748420715332],[-135.40695190429688,68.67997932434082],[-135.14639282226562,68.66388130187988],[-135.50613403320312,68.83249092102051],[-135.33804321289062,68.83499336242676],[-135.62359619140625,68.88611030578613],[-135.24166870117188,68.92692756652832],[-135.18695068359375,68.90027046203613],[-134.97747802734375,68.8783130645752],[-134.84555053710938,68.92943000793457],[-134.49554443359375,68.7522144317627]],[[-89.00556945800781,65.38554573059082],[-89.03195190429688,65.40721321105957],[-89.09999084472656,65.40582466125488],[-89.00556945800781,65.38554573059082]],[[-93.51972961425781,63.839433670043945],[-92.50750732421875,63.81638526916504],[-93.77972412109375,64.18969917297363],[-93.51972961425781,63.839433670043945]],[[-70.78306579589844,48.38054847717285],[-69.82833862304688,48.16638374328613],[-71.04861450195312,48.445268630981445],[-70.78306579589844,48.38054847717285]],[[-71.11111450195312,46.85054969787598],[-70.9041748046875,46.91360664367676],[-70.80915832519531,47.015275955200195],[-71.11111450195312,46.85054969787598]],[[-77.67832946777344,58.235551834106445],[-77.8074951171875,58.30526924133301],[-77.95083618164062,58.324167251586914],[-77.67832946777344,58.235551834106445]],[[-91.32917785644531,63.55971717834473],[-91.54055786132812,63.60666084289551],[-91.43638610839844,63.55193519592285],[-91.32917785644531,63.55971717834473]],[[-84.80804443359375,68.76388740539551],[-84.8558349609375,68.8108081817627],[-84.93916320800781,68.7935962677002],[-84.80804443359375,68.76388740539551]]],[[[-108.13890075683594,71.98166084289551],[-108.19972229003906,72.05053901672363],[-108.06416320800781,72.03027534484863],[-108.13890075683594,71.98166084289551]]],[[[-85.84722900390625,72.29414558410645],[-85.88917541503906,72.21805000305176],[-86.11000061035156,72.28970527648926],[-85.84722900390625,72.29414558410645]]],[[[-78.73500061035156,72.36554145812988],[-78.95028686523438,72.33499336242676],[-79.07501220703125,72.40971565246582],[-78.73500061035156,72.36554145812988]]],[[[-79.508056640625,72.34860420227051],[-79.68331909179688,72.43054389953613],[-79.42971801757812,72.41165351867676],[-79.508056640625,72.34860420227051]]],[[[-79.99360656738281,72.41331672668457],[-80.13333129882812,72.51944160461426],[-79.91639709472656,72.45804023742676],[-79.99360656738281,72.41331672668457]]],[[[-110.46916198730469,72.56915473937988],[-110.54415893554688,72.56915473937988],[-110.59388732910156,72.59414863586426],[-110.46916198730469,72.56915473937988]]],[[[-110.35582733154297,72.60193061828613],[-110.49472045898438,72.61914253234863],[-110.34500122070312,72.61192512512207],[-110.35582733154297,72.60193061828613]]],[[[-108.51055908203125,72.60276985168457],[-108.61361694335938,72.63665962219238],[-108.49665832519531,72.6413745880127],[-108.51055908203125,72.60276985168457]]],[[[-110.30722045898438,72.63081550598145],[-110.41082763671875,72.63943672180176],[-110.28083801269531,72.64221382141113],[-110.30722045898438,72.63081550598145]]],[[[-95.73500061035156,72.79887580871582],[-95.85417175292969,72.85359382629395],[-95.7691650390625,72.87803840637207],[-95.73500061035156,72.79887580871582]]],[[[-96.75418090820312,72.72137641906738],[-97.01112365722656,72.77581977844238],[-96.71333312988281,72.8933277130127],[-96.75418090820312,72.72137641906738]]],[[[-95.7569580078125,72.89248847961426],[-95.78666687011719,73.01249885559082],[-95.70249938964844,72.93359565734863],[-95.7569580078125,72.89248847961426]]],[[[-96.80833435058594,72.92637825012207],[-97.14111328125,73.08554267883301],[-96.57501220703125,73.07499885559082],[-96.80833435058594,72.92637825012207]]],[[[-95.73388671875,73.12886238098145],[-95.74554443359375,73.04942512512207],[-95.89334106445312,73.09582710266113],[-95.73388671875,73.12886238098145]]],[[[-96.90583801269531,73.22082710266113],[-97.11776733398438,73.24914741516113],[-96.9677734375,73.27331733703613],[-96.90583801269531,73.22082710266113]]],[[[-113.99749755859375,72.79942512512207],[-114.60472106933594,72.60165596008301],[-113.65750122070312,72.61137580871582],[-113.02806091308594,73.00943183898926],[-111.22000122070312,72.71832466125488],[-111.90556335449219,72.34971809387207],[-111.66388702392578,72.2763843536377],[-110.70140075683594,72.57554817199707],[-109.78278350830078,72.42943000793457],[-110.29110717773438,72.67109870910645],[-109.77027893066406,72.72221565246582],[-110.75666809082031,72.97137641906738],[-109.65943908691406,72.92498970031738],[-109.75473022460938,72.87858772277832],[-109.227783203125,72.76165962219238],[-109.04332733154297,72.56749153137207],[-108.62138366699219,72.54998970031738],[-108.24276733398438,71.71859931945801],[-107.82888793945312,71.60443305969238],[-107.25250244140625,71.89554023742676],[-107.77887725830078,72.13665962219238],[-108.29194641113281,73.15359687805176],[-106.76139831542969,73.29304695129395],[-105.32611083984375,72.74637031555176],[-104.35527038574219,71.57443428039551],[-104.58583068847656,71.0666675567627],[-103.55638122558594,70.60081672668457],[-100.9997329711914,70.17276191711426],[-100.87000274658203,69.78831672668457],[-103.47693634033203,69.69359016418457],[-103.02333068847656,69.49386787414551],[-103.19499206542969,69.11442756652832],[-102.31304931640625,69.49832344055176],[-101.75473022460938,69.17581367492676],[-102.89472961425781,68.79998970031738],[-105.14472961425781,68.89915657043457],[-104.91500854492188,69.07054328918457],[-106.40611267089844,69.18054389953613],[-106.60221862792969,69.49887275695801],[-107.34221458435059,69.01887702941895],[-109.10472106933594,68.71054267883301],[-113.26944732666016,68.4538745880127],[-113.03388977050781,68.49498176574707],[-113.67694091796875,68.81109809875488],[-113.5211181640625,69.17859077453613],[-116.52583312988281,69.4074878692627],[-117.43611145019531,69.99304389953613],[-115.1675033569336,70.27777290344238],[-112.56471252441406,70.19832038879395],[-111.48721313476562,70.3369312286377],[-113.93831634521484,70.71527290344238],[-117.55943298339844,70.59721565246582],[-118.41944885253906,70.99193000793457],[-115.05750274658203,71.52304267883301],[-118.11221313476562,71.37359809875488],[-118.30943298339844,71.46582221984863],[-117.69638061523438,71.66609382629395],[-119.13445281982422,71.7652759552002],[-118.10804557800293,72.23776435852051],[-118.53694152832031,72.49386787414551],[-117.35360717773438,72.91638374328613],[-114.56166076660156,73.37553596496582],[-113.961669921875,73.15304756164551],[-113.99749755859375,72.79942512512207]]],[[[-107.89555358886719,73.54136848449707],[-108.08332824707031,73.59721565246582],[-107.5824966430664,73.59776496887207],[-107.89555358886719,73.54136848449707]]],[[[-95.66972351074219,73.60498237609863],[-95.711669921875,73.6121997833252],[-95.65556335449219,73.61665534973145],[-95.66972351074219,73.60498237609863]]],[[[-124.30750274658203,73.55636787414551],[-124.35861206054688,73.6302661895752],[-124.1138916015625,73.56414985656738],[-124.30750274658203,73.55636787414551]]],[[[-124.58473205566406,73.67915534973145],[-124.73361206054688,73.70054817199707],[-124.56443786621094,73.68719673156738],[-124.58473205566406,73.67915534973145]]],[[[-105.08944702148438,73.73526191711426],[-104.48306274414062,73.53442573547363],[-105.27555847167969,72.84553718566895],[-107.03555297851562,73.48082160949707],[-105.08944702148438,73.73526191711426]]],[[[-80.14222717285156,73.69664192199707],[-77.4244384765625,73.5547046661377],[-76.05943298339844,72.90081977844238],[-79.42916870117188,72.73581123352051],[-80.8760986328125,73.3277759552002],[-80.85777282714844,73.74193000793457],[-80.14222717285156,73.69664192199707]]],[[[-73.35467529296875,68.3292179107666],[-73.211669921875,68.37692451477051],[-73.31806945800781,68.39305305480957],[-73.35467529296875,68.3292179107666],[-73.85166931152344,68.34221076965332],[-73.76139831542969,68.68637275695801],[-74.09416198730469,68.7199878692627],[-73.99028015136719,68.49275398254395],[-74.91777038574219,68.80137825012207],[-74.82084655761719,69.08221626281738],[-76.66082763671875,68.69941902160645],[-76.62554931640625,69.0183277130127],[-75.5916748046875,69.22165107727051],[-76.64111328125,69.55415534973145],[-76.18777465820312,69.66526985168457],[-77.2005615234375,69.64610481262207],[-76.79388427734375,69.71859931945801],[-77.310546875,69.83581733703613],[-76.98056030273438,69.93803596496582],[-77.62638854980469,69.74498176574707],[-77.67832946777344,70.1877613067627],[-78.40167236328125,70.21249580383301],[-79.070556640625,70.46971321105957],[-78.71888732910156,70.54776191711426],[-79.00944519042969,70.6797046661377],[-79.58889770507812,70.3994312286377],[-78.92166137695312,70.30081367492676],[-78.79194641113281,69.89109992980957],[-81.76333618164062,70.12303352355957],[-80.95249938964844,69.7138843536377],[-82.10110473632812,70.10803413391113],[-83.0069580078125,70.3047046661377],[-81.71083068847656,69.93414497375488],[-82.14334106445312,69.78137397766113],[-83.06666564941406,70.01082038879395],[-85.66639709472656,70.10470771789551],[-85.8780517578125,70.07693672180176],[-85.23611450195312,69.9891529083252],[-85.82333374023438,70.00027656555176],[-86.55194091796875,70.23498725891113],[-86.37471008300781,70.52527046203613],[-87.92304992675781,70.24275398254395],[-89.54972839355469,71.08859443664551],[-87.00279235839844,70.99414253234863],[-89.83000183105469,71.3288745880127],[-90.04861450195312,71.9538745880127],[-89.57472229003906,72.16360664367676],[-89.9566650390625,72.32165718078613],[-89.22833251953125,73.12581062316895],[-88.40916442871094,73.52360725402832],[-85.0694580078125,73.80192756652832],[-84.83778381347656,73.74165534973145],[-86.73277282714844,72.71609687805176],[-86.24082946777344,72.42025947570801],[-86.42054557800293,72.01277351379395],[-84.83389282226562,71.27415657043457],[-86.82000732421875,70.98858833312988],[-84.961669921875,71.18858528137207],[-85.14695739746094,71.08276557922363],[-84.79888916015625,70.9216480255127],[-84.625,71.66581916809082],[-86.05082702636719,72.01111030578613],[-85.48721313476562,72.2602710723877],[-84.16471862792969,72.02110481262207],[-84.93527221679688,72.28943061828613],[-84.44221496582031,72.38304328918457],[-85.5352783203125,72.46971321105957],[-85.68804931640625,72.89360237121582],[-83.95306396484375,72.75248908996582],[-85.44776916503906,73.1202564239502],[-83.63444519042969,72.98248481750488],[-85.1885986328125,73.22886848449707],[-81.55387878417969,73.71721076965332],[-80.24749755859375,72.73054695129395],[-81.37944030761719,72.24165534973145],[-80.51640319824219,72.50387763977051],[-80.90556335449219,72.18054389953613],[-80.56723022460938,72.0727710723877],[-81.08029174804688,72.0516529083252],[-80.79277038574219,72.02777290344238],[-80.97166442871094,71.88165473937988],[-80.385009765625,72.04832649230957],[-80.48666381835938,72.18942451477051],[-80.26083374023438,72.29498481750488],[-79.6744384765625,72.12664985656738],[-80.16639709472656,72.32222175598145],[-79.79916381835938,72.50139045715332],[-79.75,72.21554756164551],[-79.01278686523438,72.27388191223145],[-79.20306396484375,71.9619312286377],[-78.50361633300781,71.86886787414551],[-78.85444641113281,72.17303657531738],[-77.78555297851562,71.7874927520752],[-78.87083435058594,72.22665596008301],[-76.99583435058594,72.12886238098145],[-78.55915832519531,72.43803596496582],[-77.6138916015625,72.75166511535645],[-75.19248962402344,72.49193000793457],[-74.94749450683594,72.24971199035645],[-76.34805297851562,71.89166450500488],[-75.21945190429688,72.07443428039551],[-76.08528137207031,71.69192695617676],[-75.03582763671875,72.12581062316895],[-74.12222290039062,71.98359870910645],[-75.38999938964844,71.68109321594238],[-74.63194274902344,71.6624927520752],[-75.15194702148438,71.47165107727051],[-74.69943237304688,71.39082527160645],[-75.08139038085938,71.17943000793457],[-73.748046875,71.77693367004395],[-74.24082946777344,71.2008228302002],[-73.62193298339844,71.58333015441895],[-73.38027954101562,71.3852710723877],[-73.89834594726562,71.05748176574707],[-73.0494384765625,71.2683277130127],[-73.37748718261719,70.98054695129395],[-72.53805541992188,71.66081428527832],[-71.11972045898438,71.26416206359863],[-72.65361022949219,70.8277759552002],[-72.16361999511719,70.83638191223145],[-72.5694580078125,70.60998725891113],[-70.60166931152344,71.05386543273926],[-70.7469482421875,70.74553108215332],[-71.80305480957031,70.42831611633301],[-71.16250610351562,70.52527046203613],[-71.53582763671875,70.01971626281738],[-70.99722290039062,70.62581062316895],[-69.90472412109375,70.8813648223877],[-70.49610900878906,70.47943305969238],[-69.45140075683594,70.79193305969238],[-68.31388854980469,70.56303596496582],[-70.46861267089844,69.84276008605957],[-68.64250183105469,70.1494312286377],[-69.99055480957031,69.61499214172363],[-67.79472351074219,70.25888252258301],[-67.12777709960938,69.72693061828613],[-67.99610900878906,69.7744312286377],[-68.32945251464844,69.62776374816895],[-70.03083801269531,69.53610420227051],[-66.79554557800293,69.34109687805176],[-66.75862121582031,69.12803840637207],[-69.0150146484375,69.35498237609863],[-69.25778198242188,69.27026557922363],[-68.07749938964844,69.21748542785645],[-68.9677734375,69.22110176086426],[-68.50250244140625,69.19859504699707],[-69.02583312988281,68.96859931945801],[-68.17832946777344,69.14665412902832],[-67.70584106445312,69.01638984680176],[-68.55610656738281,68.96415901184082],[-67.77139282226562,68.78137397766113],[-69.39805603027344,68.8621997833252],[-67.61250305175781,68.37942695617676],[-66.70695495605469,68.44470405578613],[-67.87832641601562,68.2652759552002],[-67.23249816894531,68.35748481750488],[-67.01167297363281,68.31608772277832],[-67.59834289550781,68.16276741027832],[-67.01139831542969,68.29498481750488],[-66.76583862304688,68.23858833312988],[-66.9466552734375,68.01361274719238],[-66.69444274902344,68.14305305480957],[-66.69721984863281,67.98748970031738],[-66.54194641113281,68.1483325958252],[-66.18415832519531,68.01887702941895],[-66.73222351074219,67.8672046661377],[-66.35665893554688,67.82138252258301],[-65.91194152832031,68.15887641906738],[-66.00862121582031,67.62553596496582],[-65.80776977539062,67.97110176086426],[-65.443603515625,67.9922046661377],[-65.61582946777344,67.78610420227051],[-65.34638977050781,67.59332466125488],[-65.42361450195312,67.89804267883301],[-64.72361755371094,67.99054145812988],[-65.20417785644531,67.6483325958252],[-64.5069580078125,67.80720710754395],[-64.03860473632812,67.52859687805176],[-64.4405517578125,67.4749927520752],[-63.90416717529297,67.30581855773926],[-64.79750061035156,67.35664558410645],[-63.96277618408203,67.27249336242676],[-64.69194030761719,67.00055122375488],[-63.45055389404297,67.22249031066895],[-63.772499084472656,66.9588794708252],[-63.11028289794922,67.32998847961426],[-63.24083709716797,66.96165657043457],[-63.771385192871094,66.81109809875488],[-62.846946716308594,66.9619312286377],[-62.89972686767578,66.63665962219238],[-62.10139465332031,67.0547046661377],[-61.26250457763672,66.62942695617676],[-62.12388610839844,66.62637519836426],[-61.462501525878906,66.36914253234863],[-61.87749481201172,66.28332710266113],[-62.89500427246094,66.32971382141113],[-61.954444885253906,66.01915168762207],[-62.970550537109375,66.14804267883301],[-62.317222595214844,65.80803108215332],[-63.723609924316406,65.68026924133301],[-63.31999969482422,65.59332466125488],[-63.655555725097656,65.47082710266113],[-63.33555603027344,65.30053901672363],[-63.54695129394531,64.88720893859863],[-64.38082885742188,65.18109321594238],[-64.23721313476562,65.42997932434082],[-64.55555725097656,65.09221076965332],[-64.91221618652344,65.33804512023926],[-64.4183349609375,65.48275947570801],[-65.14999389648438,65.43414497375488],[-64.71000671386719,65.65220832824707],[-65.33860778808594,65.57554817199707],[-64.79499816894531,65.7280445098877],[-65.50556945800781,65.74331855773926],[-64.35638427734375,66.34971809387207],[-65.91610717773438,65.95109748840332],[-65.47361755371094,66.38582038879395],[-66.07362365722656,66.12053108215332],[-67.04888916015625,66.64471626281738],[-67.74276733398438,66.56833076477051],[-67.14862060546875,66.4438648223877],[-67.2822265625,66.27527046203613],[-67.99276733398438,66.50694465637207],[-67.19444274902344,65.90971565246582],[-67.82417297363281,65.88081550598145],[-67.9385986328125,65.90803718566895],[-68.03056335449219,65.99803352355957],[-68.02583312988281,66.0658130645752],[-68.24472045898438,66.1827564239502],[-68.85139465332031,66.18997383117676],[-68.41471862792969,66.15942573547363],[-68.23777770996094,66.06999397277832],[-68.2469482421875,66.11276435852051],[-68.15750122070312,66.11747932434082],[-68.04722595214844,66.06498908996582],[-68.05360412597656,65.99109077453613],[-68.12388610839844,65.96304512023926],[-68.304443359375,66.02804756164551],[-68.3336181640625,65.93193244934082],[-67.82112121582031,65.76805305480957],[-68.02583312988281,65.4810962677002],[-67.28056335449219,65.64248847961426],[-67.45889282226562,65.49803352355957],[-67.05833435058594,65.4266529083252],[-67.41610717773438,65.33915901184082],[-66.92887878417969,65.22970771789551],[-67.09611511230469,65.05609321594238],[-66.72610473632812,65.18026924133301],[-66.69804382324219,64.76193428039551],[-66.68865966796875,65.03877449035645],[-66.21221923828125,64.68553352355957],[-65.7177734375,64.84027290344238],[-65.72166442871094,64.49414253234863],[-65.07167053222656,64.4408130645752],[-65.65834045410156,64.30276679992676],[-65.0494384765625,64.07222175598145],[-65.21417236328125,64.02554512023926],[-64.66111755371094,64.02859687805176],[-64.98750305175781,63.82305335998535],[-64.52250671386719,63.67276954650879],[-64.53111267089844,63.24971961975098],[-65.30387878417969,63.80694007873535],[-64.62721252441406,62.90416145324707],[-65.25473022460938,62.98526954650879],[-64.94888305664062,62.64860725402832],[-65.1875,62.562211990356445],[-65.83833312988281,63.033334732055664],[-66.44444274902344,63.02054786682129],[-66.64277458190918,63.37249183654785],[-66.54666137695312,62.99138069152832],[-67.91471862792969,63.75943946838379],[-67.68527221679688,63.36888313293457],[-68.54277038574219,63.732492446899414],[-68.9969482421875,63.753610610961914],[-68.1461181640625,63.15027046203613],[-67.59999084472656,63.08443641662598],[-67.76972961425781,62.958330154418945],[-67.55305480957031,63.04860877990723],[-67.67277526855469,62.92332649230957],[-67.39805603027344,62.96721076965332],[-66.35166931152344,62.44499397277832],[-66.47000122070312,62.33221626281738],[-65.99305725097656,62.244157791137695],[-66.13249206542969,62.089433670043945],[-65.9466552734375,61.8991641998291],[-66.06610107421875,61.868600845336914],[-71.15666198730469,62.98916053771973],[-70.90888977050781,63.17083168029785],[-71.40055847167969,63.05166053771973],[-72.14555358886719,63.44610023498535],[-71.22972106933594,63.60471534729004],[-71.57695007324219,63.58166694641113],[-71.58111572265625,63.71499824523926],[-71.90444946289062,63.80999183654785],[-71.93388366699219,63.64943885803223],[-72.32417297363281,63.67666053771973],[-72.2388916015625,63.95249366760254],[-72.52639770507812,63.78777503967285],[-72.66471862792969,64.08055305480957],[-72.72000122070312,63.96110725402832],[-72.91166687011719,64.16887092590332],[-73.38055419921875,64.26860237121582],[-73.30278015136719,64.65887641906738],[-73.46333312988281,64.50248908996582],[-73.46722412109375,64.61276435852051],[-73.929443359375,64.60220527648926],[-73.8447265625,64.50193977355957],[-74.06277465820312,64.33442878723145],[-74.05387878417969,64.72859382629395],[-74.39028930664062,64.5697193145752],[-74.63999938964844,64.90359687805176],[-74.98527526855469,64.79582405090332],[-74.47000122070312,64.55748176574707],[-74.68582153320312,64.37109565734863],[-75.82417297363281,64.61165046691895],[-75.72694396972656,64.3672046661377],[-76.67054557800293,64.18414497375488],[-78.18331909179688,64.57249641418457],[-78.14527893066406,64.95749092102051],[-77.31582641601562,65.19053840637207],[-77.42166137695312,65.46138191223145],[-75.7691650390625,65.21887397766113],[-75.4244384765625,65.04387092590332],[-75.66749572753906,64.9408130645752],[-75.373046875,64.71499824523926],[-75.5675048828125,64.88360786437988],[-75.18693542480469,65.10165596008301],[-75.95028686523438,65.31833076477051],[-73.50056457519531,65.47442817687988],[-74.46611022949219,66.15193367004395],[-72.25834655761719,67.24803352355957],[-73.35467529296875,68.3292179107666]]],[[[-99.80455780029297,73.88910102844238],[-99.23500061035156,73.73776435852051],[-97.76194763183594,73.91192817687988],[-96.96221923828125,73.73858833312988],[-97.6683349609375,73.48332405090332],[-97.17193603515625,73.35276985168457],[-98.4505615234375,72.87498664855957],[-97.84695434570312,73.0486011505127],[-97.22500610351562,72.93997383117676],[-97.1966552734375,72.60443305969238],[-96.51750183105469,72.71470832824707],[-96.29833984375,72.41581916809082],[-96.87193298339844,72.32110786437988],[-96.48306274414062,72.11303901672363],[-96.866943359375,72.04109382629395],[-96.49305725097656,71.91415596008301],[-97.5050048828125,71.61165046691895],[-98.21806335449219,71.64972114562988],[-98.26722717285156,71.90416145324707],[-98.49388122558594,71.7138843536377],[-98.03750610351562,71.52665901184082],[-98.72972106933594,71.27054023742676],[-100.63445281982422,72.18553352355957],[-102.74166870117188,72.72415351867676],[-102.13722229003906,73.0869312286377],[-101.29750061035156,72.70999336242676],[-100.41221618652344,72.74193000793457],[-100.45195007324219,73.02054023742676],[-100.03138732910156,72.93498420715332],[-100.58000183105469,73.17303657531738],[-99.77166557312012,73.20804023742676],[-101.62138366699219,73.49026679992676],[-100.43055725097656,73.40693855285645],[-101.12000274658203,73.72720527648926],[-99.80455780029297,73.88910102844238]]],[[[-124.43055725097656,73.87858772277832],[-124.55278015136719,73.91693305969238],[-124.42027282714844,73.90915107727051],[-124.43055725097656,73.87858772277832]]],[[[-89.9888916015625,73.98831367492676],[-90.28500366210938,74.02971076965332],[-89.90194702148438,74.03776741027832],[-89.9888916015625,73.98831367492676]]],[[[-98.91860961914062,73.80609321594238],[-99.4375,73.89694404602051],[-97.63778686523438,74.07554817199707],[-98.91860961914062,73.80609321594238]]],[[[-92.6380615234375,74.1030445098877],[-90.19444274902344,73.89972114562988],[-92.09584045410156,72.74304389953613],[-94.3155517578125,72.76304817199707],[-93.46333312988281,72.46220588684082],[-94.06304931640625,71.97831916809082],[-95.21333312988281,71.99443244934082],[-94.75222778320312,72.15332221984863],[-95.17111206054688,72.13916206359863],[-95.13333129882812,72.46026802062988],[-95.67361450195312,72.81387519836426],[-95.68331909179688,73.0758228302002],[-95.57501220703125,73.16499519348145],[-95.68388366699219,73.45027351379395],[-95.70028686523438,73.55386543273926],[-95.61256408691406,73.6109790802002],[-95.67304992675781,73.72331428527832],[-94.61805725097656,73.6513843536377],[-95.32778930664062,73.90915107727051],[-94.73222351074219,74.09526252746582],[-92.6380615234375,74.1030445098877]]],[[[-98.6572265625,74.29942512512207],[-98.86471557617188,74.3047046661377],[-98.51112365722656,74.31833076477051],[-98.6572265625,74.29942512512207]]],[[[-120.14998626708984,74.27249336242676],[-119.60916137695312,74.23332405090332],[-119.74481201171875,74.02551460266113],[-119.14862060546875,74.21220588684082],[-119.1675033569336,73.9871997833252],[-117.42223358154297,74.22693061828613],[-115.31500244140625,73.47970771789551],[-119.13751220703125,72.63247871398926],[-119.31111145019531,72.35220527648926],[-120.25110626220703,72.25860786437988],[-120.54332733154297,71.51666450500488],[-122.78111267089844,71.08610725402832],[-125.25361633300781,71.95025825500488],[-124.94833374023438,71.96110725402832],[-125.99777221679688,71.97360420227051],[-125.02610778808594,72.82109260559082],[-124.475830078125,72.92720222473145],[-124.86888122558594,73.08055305480957],[-123.77471923828125,73.76443672180176],[-124.77084350585938,74.34027290344238],[-121.56416320800781,74.55108833312988],[-120.14998626708984,74.27249336242676]]],[[[-97.65278625488281,74.4558277130127],[-97.79249572753906,74.48581123352051],[-97.2569580078125,74.59054756164551],[-97.65278625488281,74.4558277130127]]],[[[-95.31111145019531,74.49775886535645],[-95.86639404296875,74.57415962219238],[-95.51750183105469,74.6302661895752],[-95.31111145019531,74.49775886535645]]],[[[-97.17582702636719,75.24414253234863],[-97.27528381347656,75.34749031066895],[-97.15306091308594,75.31526374816895],[-97.17582702636719,75.24414253234863]]],[[[-103.9175033569336,75.05497932434082],[-104.85722351074219,75.16470527648926],[-104.18222045898438,75.43553352355957],[-103.58306884765625,75.16470527648926],[-103.9175033569336,75.05497932434082]]],[[[-95.91000366210938,75.56025886535645],[-96.85110473632812,75.35026741027832],[-97.05305480957031,75.4922046661377],[-95.91000366210938,75.56025886535645]]],[[[-94.3638916015625,75.59082221984863],[-93.48750305175781,75.25665473937988],[-93.4677734375,74.70305061340332],[-96.616943359375,74.99109077453613],[-95.74972534179688,75.5133228302002],[-94.3638916015625,75.59082221984863]]],[[[-100.17223358154297,75.60138130187988],[-100.45417785644531,75.54637336730957],[-101.03943634033203,75.56721687316895],[-100.17223358154297,75.60138130187988]]],[[[-96.95445251464844,75.59553718566895],[-97.0050048828125,75.60443305969238],[-96.71583557128906,75.65999031066895],[-96.95445251464844,75.59553718566895]]],[[[-96.57917785644531,75.73692512512207],[-96.71722412109375,75.73970222473145],[-96.45584106445312,75.8177661895752],[-96.57917785644531,75.73692512512207]]],[[[-111.79998779296875,75.83915901184082],[-111.92250061035156,75.85276985168457],[-111.57861328125,75.87997627258301],[-111.79998779296875,75.83915901184082]]],[[[-122.3408432006836,75.86276435852051],[-122.69554138183594,75.90803718566895],[-122.35305786132812,75.91443061828613],[-122.3408432006836,75.86276435852051]]],[[[-121.09306335449219,75.7260913848877],[-121.288330078125,75.75277900695801],[-120.87777709960938,75.93609809875488],[-121.09306335449219,75.7260913848877]]],[[[-103.13778686523438,75.74275398254395],[-103.38276672363281,75.76555061340332],[-101.98332214355469,75.9458179473877],[-103.13778686523438,75.74275398254395]]],[[[-95.79277038574219,75.89972114562988],[-95.89999389648438,75.9538745880127],[-95.73582458496094,75.96832466125488],[-95.79277038574219,75.89972114562988]]],[[[-94.40556335449219,75.75082588195801],[-94.90444946289062,75.93692207336426],[-94.48194885253906,75.97442817687988],[-94.40556335449219,75.75082588195801]]],[[[-122.81916809082031,76.06053352355957],[-122.63082885742188,76.0466480255127],[-122.89250183105469,76.01361274719238],[-122.81916809082031,76.06053352355957]]],[[[-118.31639099121094,75.57249641418457],[-119.40805053710938,75.60582160949707],[-117.46389770507812,76.08305549621582],[-118.31639099121094,75.57249641418457]]],[[[-102.38999938964844,76.08360481262207],[-102.3194580078125,76.02470588684082],[-103.9716567993164,75.93831062316895],[-102.38999938964844,76.08360481262207]]],[[[-78.9263916015625,75.87581062316895],[-79.75222778320312,75.87858772277832],[-78.80583190917969,76.09305000305176],[-79.1763916015625,75.9527759552002],[-78.9263916015625,75.87581062316895]]],[[[-94.84361267089844,76.1222095489502],[-95.00666809082031,76.04748725891113],[-95.14723205566406,76.11693000793457],[-94.84361267089844,76.1222095489502]]],[[[-81.32778930664062,76.14721870422363],[-81.46250915527344,76.15887641906738],[-81.20140075683594,76.17776679992676],[-81.32778930664062,76.14721870422363]]],[[[-102.53083801269531,76.22331428527832],[-103.34221458435059,76.03665351867676],[-104.48277282714844,76.14221382141113],[-102.53083801269531,76.22331428527832]]],[[[-89.39889526367188,76.43553352355957],[-89.62554931640625,76.44497871398926],[-89.53306579589844,76.47665596008301],[-89.39889526367188,76.43553352355957]]],[[[-83.96278381347656,76.42637825012207],[-84.13945007324219,76.5072193145752],[-83.90805053710938,76.46499824523926],[-83.96278381347656,76.42637825012207]]],[[[-104.05387878417969,76.56303596496582],[-103.00446319580078,76.42997932434082],[-104.33500671386719,76.31860542297363],[-104.66583251953125,76.5516529083252],[-104.05387878417969,76.56303596496582]]],[[[-98.41806030273438,76.66832160949707],[-97.50917053222656,76.18887519836426],[-97.9385986328125,75.74136543273926],[-97.38667297363281,75.6827564239502],[-97.28083801269531,75.39694404602051],[-97.74415588378906,75.57110786437988],[-98.165283203125,75.33415412902832],[-97.58250427246094,75.13749885559082],[-100.14584350585938,74.99109077453613],[-100.54695129394531,75.19941902160645],[-99.98777770996094,75.2361011505127],[-100.77887725830078,75.35054206848145],[-98.95028686523438,75.70999336242676],[-102.88390350341797,75.61914253234863],[-101.18222045898438,75.77971076965332],[-101.9072265625,76.07859992980957],[-101.38778686523438,76.25193977355957],[-102.16583251953125,76.23831367492676],[-101.88583374023438,76.44497871398926],[-99.88833618164062,75.88638496398926],[-99.43943786621094,75.97053718566895],[-100.15278625488281,76.13247871398926],[-99.41444396972656,76.15832710266113],[-100.98249816894531,76.50499153137207],[-99.68443298339844,76.63333320617676],[-99.07972717285156,76.39721870422363],[-98.41806030273438,76.66832160949707]]],[[[-99.9969482421875,76.73442268371582],[-99.43055725097656,76.69941902160645],[-100.12860107421875,76.72192573547363],[-99.9969482421875,76.73442268371582]]],[[[-101.38054656982422,76.55359077453613],[-101.68831634521484,76.58638191223145],[-100.24889373779297,76.73471260070801],[-101.38054656982422,76.55359077453613]]],[[[-120.88362121582031,76.73970222473145],[-120.97000122070312,76.71666145324707],[-121.18472290039062,76.7310962677002],[-120.88362121582031,76.73970222473145]]],[[[-89.93443298339844,76.47665596008301],[-90.59999084472656,76.74664497375488],[-89.67388916015625,76.73748970031738],[-89.93443298339844,76.47665596008301]]],[[[-108.65110778808594,76.81360054016113],[-108.55803680419922,76.40860176086426],[-108.07749938964844,76.28055000305176],[-108.3961181640625,76.04609870910645],[-107.63249206542969,75.99109077453613],[-108.02027893066406,75.78082466125488],[-106.89666557312012,75.72026252746582],[-106.336669921875,76.0547046661377],[-105.39195251464844,75.63888740539551],[-106.01112365722656,75.05081367492676],[-108.8324966430664,75.06999397277832],[-112.75306701660156,74.4013843536377],[-114.44776916503906,74.6746997833252],[-110.91278076171875,75.23387336730957],[-113.9175033569336,75.05359077453613],[-113.34056091308594,75.41331672668457],[-114.06500244140625,75.46609687805176],[-115.05082702636719,74.96110725402832],[-117.68388366699219,75.25305366516113],[-114.9997329711914,75.6908130645752],[-117.25110626220703,75.59749031066895],[-114.81749725341797,75.88081550598145],[-116.73416137695312,75.92248725891113],[-116.29611206054688,76.18858528137207],[-114.66251373291016,76.1605396270752],[-115.92500305175781,76.28665351867676],[-114.89972686767578,76.51693916320801],[-112.45388793945312,76.17637825012207],[-111.727783203125,75.9216480255127],[-112.2255630493164,75.81109809875488],[-111.45195007324219,75.83665657043457],[-111.24722290039062,75.51805305480957],[-108.8994369506836,75.47638130187988],[-108.82695007324219,75.68664741516113],[-110.05555725097656,75.89055061340332],[-109.31360626220703,76.1091480255127],[-110.39306640625,76.39193916320801],[-108.65110778808594,76.81360054016113]]],[[[-97.04527282714844,76.79776191711426],[-97.20083618164062,76.85748481750488],[-96.99722290039062,76.81331062316895],[-97.04527282714844,76.79776191711426]]],[[[-113.46611022949219,76.76638984680176],[-114.87581634521484,76.77083015441895],[-113.88555908203125,76.89166450500488],[-113.46611022949219,76.76638984680176]]],[[[-109.06610107421875,76.90054512023926],[-109.30776977539062,76.92804145812988],[-109.179443359375,76.93248176574707],[-109.06610107421875,76.90054512023926]]],[[[-97.25639343261719,76.96748542785645],[-97.47305297851562,76.98054695129395],[-97.09222412109375,77.01082038879395],[-97.25639343261719,76.96748542785645]]],[[[-95.65972900390625,77.05887031555176],[-93.17971801757812,76.74109077453613],[-93.54833984375,76.38611030578613],[-91.41055297851562,76.68914985656738],[-90.46806335449219,76.4730396270752],[-91.56666564941406,76.49887275695801],[-89.29249572753906,76.29609870910645],[-91.61361694335938,76.26220893859863],[-90.1905517578125,76.06109809875488],[-91.12998962402344,75.83915901184082],[-90.0150146484375,76.0102710723877],[-89.17277526855469,75.78055000305176],[-89.76528930664062,75.57554817199707],[-88.9505615234375,75.4297046661377],[-88.7388916015625,75.67943000793457],[-86.54472351074219,75.3591480255127],[-83.8781509399414,75.8189640045166],[-81.53694152832031,75.80941963195801],[-79.57472229003906,75.44999885559082],[-79.57112121582031,75.19914436340332],[-80.4405517578125,75.03804206848145],[-79.3336181640625,74.89444160461426],[-80.32167053222656,74.9377613067627],[-80.23167419433594,74.57805061340332],[-81.81082153320312,74.45694160461426],[-83.51139831542969,74.90165901184082],[-83.47444152832031,74.57971382141113],[-84.28555297851562,74.50360298156738],[-88.4969482421875,74.49775886535645],[-88.54777526855469,74.90776252746582],[-89.48971557617188,74.54553413391113],[-91.02471923828125,74.7027759552002],[-90.77223205566406,74.88499641418457],[-91.53999328613281,74.6463794708252],[-92.49082946777344,75.21360969543457],[-92.0050048828125,75.5949878692627],[-92.10861206054688,75.85887336730957],[-93.0836181640625,76.35803413391113],[-95.3760986328125,76.23442268371582],[-94.80082702636719,76.32165718078613],[-96.96444702148438,76.73332405090332],[-96.30555725097656,76.75387763977051],[-96.81027221679688,76.97915840148926],[-95.65972900390625,77.05887031555176]]],[[[-113.32888793945312,77.07998847961426],[-113.49749755859375,77.08831977844238],[-113.3447265625,77.12776374816895],[-113.32888793945312,77.07998847961426]]],[[[-113.77861022949219,77.10415840148926],[-113.93138122558594,77.12970161437988],[-113.65778350830078,77.12915229797363],[-113.77861022949219,77.10415840148926]]],[[[-104.25250244140625,77.0727710723877],[-104.43167114257812,77.09887886047363],[-104.00110626220703,77.13582038879395],[-104.25250244140625,77.0727710723877]]],[[[-95.22444152832031,77.16720771789551],[-95.63999938964844,77.23776435852051],[-95.35610961914062,77.23637580871582],[-95.22444152832031,77.16720771789551]]],[[[-90.93305969238281,77.25444221496582],[-90.713623046875,77.2008228302002],[-91.29916381835938,77.21776008605957],[-90.93305969238281,77.25444221496582]]],[[[-116.3510971069336,77.53915596008301],[-115.39028930664062,77.30636787414551],[-116.28056335449219,77.18359565734863],[-115.73137664794922,76.94970893859863],[-116.36528015136719,76.92637825012207],[-115.89666557312012,76.69165229797363],[-117.05387878417969,76.53305244445801],[-117.09555053710938,76.29525947570801],[-118.05999755859375,76.40915107727051],[-117.84221458435059,76.82388496398926],[-118.96806335449219,76.5052661895752],[-118.56749725341797,76.33665657043457],[-119.07584381103516,76.08333015441895],[-119.65499877929688,76.30304145812988],[-119.80499267578125,76.10887336730957],[-119.48110961914062,75.97082710266113],[-119.87000274658203,75.85748481750488],[-120.45445251464844,75.8158130645752],[-120.85722351074219,76.19664192199707],[-120.99944305419922,75.93969917297363],[-123.03778076171875,76.08471870422363],[-122.59889221191406,76.34832954406738],[-121.53307342529297,76.43719673156738],[-121.21250915527344,76.64972114562988],[-120.40167236328125,76.79721260070801],[-119.1533432006836,77.3258228302002],[-116.3510971069336,77.53915596008301]]],[[[-85.2852783203125,77.58749580383301],[-84.81388854980469,77.4972095489502],[-85.538330078125,77.53997993469238],[-85.2852783203125,77.58749580383301]]],[[[-90.60305786132812,77.6283130645752],[-89.63612365722656,77.33915901184082],[-91.20889282226562,77.41499519348145],[-90.60305786132812,77.6283130645752]]],[[[-105.0102767944336,77.40803718566895],[-104.36554718017578,77.23027229309082],[-105.2469482421875,77.1938648223877],[-106.0947265625,77.72415351867676],[-105.0102767944336,77.40803718566895]]],[[[-95.40583801269531,77.76388740539551],[-93.10194396972656,77.6624927520752],[-93.570556640625,77.4377613067627],[-96.32888793945312,77.60498237609863],[-95.40583801269531,77.76388740539551]]],[[[-77.85194396972656,77.7744312286377],[-77.95500183105469,77.83027839660645],[-77.56861877441406,77.84971809387207],[-77.85194396972656,77.7744312286377]]],[[[-101.7114028930664,77.90165901184082],[-100.92555236816406,77.7371997833252],[-102.52971458435059,77.83415412902832],[-101.7114028930664,77.90165901184082]]],[[[-114.07305908203125,77.98166084289551],[-113.57611083984375,77.81414985656738],[-115.1160945892334,77.95833015441895],[-114.07305908203125,77.98166084289551]]],[[[-109.58805847167969,78.06469917297363],[-110.90471458435059,77.84387397766113],[-110.09028625488281,77.76915168762207],[-110.20333862304688,77.51138496398926],[-112.03111267089844,77.32470893859863],[-113.19803619384766,77.52388191223145],[-113.31973266601562,77.79553413391113],[-109.58805847167969,78.06469917297363]]],[[[-103.05695343017578,78.11970710754395],[-103.2822265625,78.15776252746582],[-102.7822265625,78.23858833312988],[-103.05695343017578,78.11970710754395]]],[[[-94.36665344238281,78.15915107727051],[-94.69415283203125,78.25860786437988],[-94.48194885253906,78.2683277130127],[-94.36665344238281,78.15915107727051]]],[[[-88.28721618652344,78.24331855773926],[-88.40972900390625,78.29220771789551],[-88.0433349609375,78.43664741516113],[-88.28721618652344,78.24331855773926]]],[[[-74.30694580078125,78.6766529083252],[-74.71028137207031,78.7310962677002],[-74.16361999511719,78.71609687805176],[-74.30694580078125,78.6766529083252]]],[[[-109.64806365966797,78.58804512023926],[-109.26055908203125,78.4558277130127],[-113.33416557312012,78.33276557922363],[-110.63751220703125,78.74859809875488],[-109.64806365966797,78.58804512023926]]],[[[-96.76806640625,78.68414497375488],[-94.87777709960938,78.3913745880127],[-95.399169921875,78.2310962677002],[-94.88694763183594,78.10276985168457],[-97.09695434570312,77.80331611633301],[-97.77555847167969,78.03499031066895],[-96.87054443359375,78.13333320617676],[-98.41139221191406,78.4952564239502],[-98.02223205566406,78.53637886047363],[-98.37165832519531,78.7199878692627],[-98.14445495605469,78.8166675567627],[-96.76806640625,78.68414497375488]]],[[[-86.3194580078125,78.88360786437988],[-86.48443603515625,78.89276313781738],[-85.16722106933594,79.02083015441895],[-86.3194580078125,78.88360786437988]]],[[[-103.59388732910156,79.3258228302002],[-102.56082153320312,78.86970710754395],[-101.6489028930664,79.0758228302002],[-99.95249938964844,78.72554206848145],[-99.52972412109375,78.57805061340332],[-99.79388427734375,78.29721260070801],[-98.94583129882812,78.05581855773926],[-99.90695190429688,77.77859687805176],[-101.03555297851562,78.19609260559082],[-102.61860656738281,78.24136543273926],[-102.80610656738281,78.37776374816895],[-104.46749877929688,78.2652759552002],[-105.0513916015625,78.49443244934082],[-103.52362060546875,78.49609565734863],[-104.04222106933594,78.62997627258301],[-103.31639099121094,78.73442268371582],[-104.19888305664062,78.77026557922363],[-103.82167053222656,78.8983325958252],[-104.20361328125,78.99165534973145],[-104.98832702636719,78.79832649230957],[-104.68110656738281,79.01666450500488],[-105.62860107421875,79.16137886047363],[-103.59388732910156,79.3258228302002]]],[[[-99.47166442871094,80.10971260070801],[-98.6441650390625,79.79414558410645],[-100.177490234375,79.90999031066895],[-99.47166442871094,80.10971260070801]]],[[[-99.15556335449219,80.1746997833252],[-99.1138916015625,80.16388130187988],[-99.41806030273438,80.15721321105957],[-99.15556335449219,80.1746997833252]]],[[[-95.03083801269531,80.67025947570801],[-94.97055053710938,80.6352710723877],[-96.149169921875,80.66470527648926],[-95.03083801269531,80.67025947570801]]],[[[-92.727783203125,81.30554389953613],[-90.76640319824219,80.56553840637207],[-89.2449951171875,80.51721382141113],[-88.77667236328125,80.1313648223877],[-88.14555358886719,80.09387397766113],[-88.61528015136719,80.40387153625488],[-87.68388366699219,80.41026496887207],[-87.56277465820312,80.17915534973145],[-88.0655517578125,80.12082099914551],[-86.95777893066406,79.90359687805176],[-87.46250915527344,79.53471565246582],[-86.33416557312012,79.64554023742676],[-86.04611206054688,79.56888008117676],[-86.07084655761719,79.43414497375488],[-85.68194580078125,79.61331367492676],[-84.9041748046875,79.26776313781738],[-86.98332214355469,79.05664253234863],[-87.61582946777344,78.64526557922363],[-88.00334167480469,78.80720710754395],[-87.72471618652344,79.0758228302002],[-88.16250610351562,78.99054145812988],[-87.90834045410156,78.5486011505127],[-88.80416870117188,78.60971260070801],[-88.53555297851562,78.41304206848145],[-88.81777954101562,78.1544361114502],[-89.98056030273438,78.60971260070801],[-89.45249938964844,78.1624927520752],[-92.05833435058594,78.2088794708252],[-92.98750305175781,78.46554756164551],[-91.63528442382812,78.54609870910645],[-93.2711181640625,78.58415412902832],[-93.81361389160156,78.76582527160645],[-93.03778076171875,78.76582527160645],[-94.28860473632812,78.98637580871582],[-90.36326599121094,79.24681282043457],[-92.2388916015625,79.20555305480957],[-92.69471740722656,79.2572193145752],[-91.1199951171875,79.38638496398926],[-93.09056091308594,79.48221015930176],[-95.08755493164062,79.27075386047363],[-95.77944946289062,79.42581367492676],[-94.28277587890625,79.75749397277832],[-95.85333251953125,79.64610481262207],[-96.80278015136719,80.09082221984863],[-94.38362121582031,79.98248481750488],[-94.74888610839844,80.07998847961426],[-94.08389282226562,80.17553901672363],[-96.68167114257812,80.34221076965332],[-93.78639221191406,80.52554512023926],[-95.53416442871094,80.81888008117676],[-93.0916748046875,81.15999031066895],[-94.26861572265625,81.34610176086426],[-92.727783203125,81.30554389953613]]],[[[-91.71833801269531,81.54915046691895],[-91.96055603027344,81.5949878692627],[-91.58222961425781,81.57805061340332],[-91.71833801269531,81.54915046691895]]],[[[-78.36582946777344,82.88360786437988],[-78.41471862792969,82.94192695617676],[-78.116943359375,82.94220161437988],[-78.36582946777344,82.88360786437988]]],[[[-70.1119384765625,83.10942268371582],[-66.2994384765625,82.92943000793457],[-68.64250183105469,82.62858772277832],[-64.72972106933594,82.90416145324707],[-64.93693542480469,82.87137031555176],[-62.926109313964844,82.57609748840332],[-63.3699951171875,82.43887519836426],[-61.076393127441406,82.32083320617676],[-64.35527038574219,81.72638130187988],[-69.2913818359375,81.71887397766113],[-66.60861206054688,81.51277351379395],[-70.21000671386719,81.17387580871582],[-64.43638610839844,81.47943305969238],[-69.427490234375,80.38275337219238],[-70.82528686523438,80.55859565734863],[-70.14555358886719,80.19359016418457],[-72.42083740234375,80.21110725402832],[-70.49749755859375,80.08276557922363],[-71.46055603027344,79.9013843536377],[-70.9102783203125,79.88582038879395],[-71.18388366699219,79.7774829864502],[-74.2388916015625,79.88720893859863],[-74.84638977050781,79.84721565246582],[-73.12582397460938,79.55832099914551],[-78.0513916015625,79.35470771789551],[-74.43666076660156,79.0577564239502],[-78.89138793945312,79.06331062316895],[-77.70333862304688,79.00694465637207],[-78.248046875,78.77026557922363],[-76.71055603027344,79.02832221984863],[-74.7197265625,78.70749092102051],[-76.693603515625,78.50972175598145],[-75.0625,78.3097095489502],[-76.91221618652344,78.20109748840332],[-75.5755615234375,78.10775947570801],[-75.92277526855469,77.95665168762207],[-78.26083374023438,77.9952564239502],[-77.71861267089844,77.60582160949707],[-78.6905517578125,77.31553840637207],[-80.45611572265625,77.29609870910645],[-81.93028259277344,77.68498420715332],[-81.16583251953125,77.33720588684082],[-82.16610717773438,77.29248237609863],[-81.83416557312012,77.1624927520752],[-79.2550048828125,77.21859931945801],[-79.0050048828125,77.0969409942627],[-79.38694763183594,76.92747688293457],[-77.77944946289062,76.79136848449707],[-78.37748718261719,76.45804023742676],[-81.05332946777344,76.12803840637207],[-80.77166557312012,76.41914558410645],[-82.72500610351562,76.81915473937988],[-82.12721252441406,76.44165229797363],[-83.00361633300781,76.42915534973145],[-83.40083312988281,76.75999641418457],[-83.18832397460938,76.41943550109863],[-84.31082153320312,76.65832710266113],[-84.19554138183594,76.45637702941895],[-85.02833557128906,76.57499885559082],[-84.3760986328125,76.3177661895752],[-84.92832946777344,76.28637886047363],[-86.59416198730469,76.63499641418457],[-86.34222412109375,76.51220893859863],[-88.38999938964844,76.38971138000488],[-88.49472045898438,76.81721687316895],[-88.60804557800293,76.39999580383301],[-89.679443359375,76.57165718078613],[-88.54583740234375,77.10026741027832],[-86.739990234375,77.17415046691895],[-87.71194458007812,77.35998725891113],[-88.2147216796875,77.65054512023926],[-88.06806945800781,77.82026863098145],[-86.42222595214844,77.8308277130127],[-85.79444885253906,77.41971015930176],[-84.47944641113281,77.29443550109863],[-83.4647216796875,77.34832954406738],[-83.83555603027344,77.45526313781738],[-82.31861877441406,78.07083320617676],[-83.89834594726562,77.49054145812988],[-85.40249633789062,77.81999397277832],[-84.32501220703125,77.89610481262207],[-85.67887878417969,77.92943000793457],[-84.12777709960938,78.17109870910645],[-84.96861267089844,78.20248603820801],[-84.5755615234375,78.34637641906738],[-84.866943359375,78.36914253234863],[-84.63861083984375,78.59414863586426],[-85.48611450195312,78.10247993469238],[-86.288330078125,78.07638740539551],[-85.83306884765625,78.37997627258301],[-87.53860473632812,78.13804817199707],[-87.08944702148438,78.20193672180176],[-87.52471923828125,78.41638374328613],[-86.85694885253906,78.73498725891113],[-85.06416320800781,78.91914558410645],[-82.33778381347656,78.5666675567627],[-82.59445190429688,78.70305061340332],[-82.22055053710938,78.73221015930176],[-83.25473022460938,78.83499336242676],[-81.47721862792969,79.04721260070801],[-84.748046875,79.03193855285645],[-83.35861206054688,79.05081367492676],[-84.32695007324219,79.18858528137207],[-84.48472595214844,79.40637397766113],[-85.06889343261719,79.62608528137207],[-86.48638916015625,79.76361274719238],[-85.2550048828125,79.92082405090332],[-86.48277282714844,80.00860786437988],[-86.51472473144531,80.29915046691895],[-83.78195190429688,80.24582099914551],[-81.7066650390625,79.58665657043457],[-79.90472412109375,79.64694404602051],[-81.51972961425781,79.73082160949707],[-81.66305541992188,79.90304756164551],[-81.40028381347656,79.9377613067627],[-83.20388793945312,80.31805610656738],[-78.03805541992188,80.56721687316895],[-79.96055603027344,80.60803413391113],[-76.48472595214844,80.86554145812988],[-78.93499755859375,80.87553596496582],[-76.74526977539062,81.43914985656738],[-79.50167846679688,81.19359016418457],[-79.06361389160156,81.08554267883301],[-80.91944885253906,80.65555000305176],[-83.5694580078125,80.7391529083252],[-83.2569580078125,80.83859443664551],[-85.06695556640625,80.5052661895752],[-86.7449951171875,80.6030445098877],[-85.6058349609375,80.97581672668457],[-82.36444091796875,81.17943000793457],[-85.68167114257812,81.04942512512207],[-87.5947265625,80.62858772277832],[-89.46611022949219,80.91415596008301],[-84.73388671875,81.28109931945801],[-89.82084655761719,81.01082038879395],[-90.35194396972656,81.16748237609863],[-87.24472045898438,81.49026679992676],[-90.44305419921875,81.36665534973145],[-90.85665893554688,81.44413948059082],[-89.58500671386719,81.62581062316895],[-91.9566650390625,81.65860176086426],[-88.0755615234375,82.10498237609863],[-84.60499572753906,81.88998603820801],[-86.8760986328125,82.20221138000488],[-85.04695129394531,82.48193550109863],[-79.22917175292969,81.81608772277832],[-82.73222351074219,82.40165901184082],[-81.54167175292969,82.49609565734863],[-82.21528625488281,82.6685962677002],[-80.57806396484375,82.54609870910645],[-81.47305297851562,82.82499885559082],[-78.50279235839844,82.68109321594238],[-80.43028259277344,82.88749885559082],[-79.7933349609375,82.95749092102051],[-75.89222717285156,82.5919361114502],[-76.2308349609375,82.44470405578613],[-75.3961181640625,82.61470222473145],[-77.38137817382812,82.99443244934082],[-74.43582153320312,83.02720832824707],[-72.63389587402344,82.69442939758301],[-73.65055847167969,82.92581367492676],[-70.1119384765625,83.10942268371582]]],[[[-92.95417785644531,63.871103286743164],[-93.09445190429688,63.90499305725098],[-92.97833251953125,63.90832710266113],[-92.95417785644531,63.871103286743164]]]]}},{"type":"Feature","properties":{"name":"Cambodia","iso2":"KH","iso3":"KHM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[103.77525520324707,10.442499160766602],[103.74858283996582,10.476388931274414],[103.75581550598145,10.511667251586914],[103.79886054992676,10.500001907348633],[103.77525520324707,10.442499160766602]]],[[[103.31414985656738,10.723054885864258],[103.26970863342285,10.669721603393555],[103.19331550598145,10.756387710571289],[103.31414985656738,10.723054885864258]]],[[[107.4891529083252,14.448610305786133],[107.54749488830566,12.353609085083008],[106.42024421691895,11.973608016967773],[106.45821571350098,11.665864944458008],[105.8510684967041,11.659997940063477],[106.20331001281738,10.77055549621582],[105.10191535949707,10.95555305480957],[104.4453296661377,10.422739028930664],[104.24774360656738,10.567499160766602],[103.92691230773926,10.590276718139648],[103.6233081817627,10.495553970336914],[103.55523872375488,11.156942367553711],[103.12970161437988,10.883054733276367],[102.91609382629395,11.63585090637207],[102.37719917297363,13.573888778686523],[103.18054389953613,14.329721450805664],[105.21060371398926,14.349649429321289],[106.05664253234863,13.929998397827148],[106.00470924377441,14.373052597045898],[106.54074287414551,14.598726272583008],[106.85359382629395,14.30305290222168],[107.54660224914551,14.708620071411133],[107.4891529083252,14.448610305786133]],[[103.03275489807129,11.431943893432617],[103.04551887512207,11.469720840454102],[103.00940895080566,11.524999618530273],[103.03275489807129,11.431943893432617]],[[103.02803230285645,11.24638557434082],[103.04192543029785,11.375555038452148],[102.98636054992676,11.422220230102539],[103.02803230285645,11.24638557434082]]]]}},{"type":"Feature","properties":{"name":"Sri Lanka","iso2":"LK","iso3":"LKA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[81.71499600000018,7.681388],[81.708328,7.674166],[81.70166,7.68111],[81.71276900000012,7.704999],[81.71499600000018,7.681388]]],[[[81.80693100000022,7.477777],[81.7233120000001,7.738610000000122],[81.804153,7.600554],[81.80693100000022,7.477777]]],[[[79.91249100000013,9.018055],[79.85054000000017,9.00111000000011],[79.693039,9.092497],[79.91249100000013,9.018055]]],[[[79.716385,9.477221],[79.658035,9.499165],[79.657486,9.555832000000152],[79.716385,9.477221]]],[[[79.974426,9.615274],[79.871918,9.634443],[79.854706,9.750832],[79.974426,9.615274]]],[[[80.27470400000013,9.775],[80.824432,9.261944],[80.91470300000017,8.94305400000016],[81.231094,8.65111],[81.130539,8.5],[81.361374,8.487219],[81.391937,8.149443],[81.881653,7.288054000000102],[81.66110200000017,6.439999000000128],[80.587204,5.9177770000001],[80.04609700000012,6.239721],[79.702484,8.079443],[80.051926,9.594442000000157],[80.61219800000012,9.443054],[79.925812,9.74472],[80.44413800000015,9.57166500000011],[80.27470400000013,9.775]]]]}},{"type":"Feature","properties":{"name":"Congo","iso2":"CG","iso3":"COG"},"geometry":{"type":"MultiPolygon","coordinates":[[[[12.779047,-4.388991],[12.026131,-5.014997],[11.140661000000108,-3.925277],[11.496944,-3.506945],[11.925833,-3.636945],[11.574165,-2.333333],[12.478054000000128,-2.327222],[12.65,-1.8225],[13.001507,-2.367672],[13.482777000000112,-2.4375],[13.76222,-2.088889],[14.110832,-2.493056],[14.429722000000112,-1.891667],[14.51861,-0.609167],[13.848331000000144,-0.198611],[14.487221,0.913611000000117],[14.188889,1.391389],[13.186785,1.222476],[13.293888,2.163611],[14.564999,2.169444],[16.07222000000013,1.654166],[16.207222,2.220833],[16.659721,3.533333],[17.475277,3.713055],[18.624958,3.479444],[18.09194200000013,2.224166],[17.714996,-0.537222],[16.195831,-2.175834],[16.226944,-3.328333],[15.890505000000132,-3.943009],[14.661388,-4.909445],[14.418888000000152,-4.887222],[14.400833,-4.2775],[13.729443,-4.445834],[13.413887000000102,-4.882501],[13.091389,-4.633056],[12.779047,-4.388991]]]]}},{"type":"Feature","properties":{"name":"Democratic Republic of the Congo","iso2":"CD","iso3":"COD"},"geometry":{"type":"MultiPolygon","coordinates":[[[[25.89166831970215,5.192499160766602],[27.455278396606445,5.016389846801758],[28.363054275512695,4.290002822875977],[29.64333152770996,4.643613815307617],[30.85881996154785,3.49339485168457],[30.72972297668457,2.448057174682617],[31.302778244018555,2.121389389038086],[29.960554122924805,0.825555801391602],[29.59694480895996,-1.385833740234375],[28.86833381652832,-2.394443511962891],[29.024442672729492,-2.744722366333008],[29.22989845275879,-3.75096321105957],[29.423887252807617,-4.448055267333984],[29.55027961730957,-6.295278549194336],[30.771242141723633,-8.19224739074707],[28.90166664123535,-8.478612899780273],[28.372220993041992,-9.260833740234375],[28.69972038269043,-10.65333366394043],[28.363332748413086,-11.550834655761719],[29.031389236450195,-12.383056640625],[29.49361228942871,-12.458057403564453],[29.805051803588867,-12.15524673461914],[29.801389694213867,-13.454168319702148],[29.589445114135742,-13.221944808959961],[29.015832901000977,-13.39777946472168],[28.441946029663086,-12.519723892211914],[27.660001754760742,-12.296667098999023],[27.199251174926758,-11.56790542602539],[26.86861228942871,-11.973611831665039],[26.00472068786621,-11.90250015258789],[25.359724044799805,-11.641668319702148],[25.332223892211914,-11.193334579467773],[24.448331832885742,-11.463611602783203],[23.986207962036133,-10.870460510253906],[22.253889083862305,-11.209722518920898],[22.312223434448242,-10.364444732666016],[21.790555953979492,-9.405555725097656],[21.782960891723633,-7.280841827392578],[20.548715591430664,-7.283615112304688],[20.62974739074707,-6.913881301879883],[19.538949966430664,-6.996614456176758],[19.373056411743164,-7.996110916137695],[17.62416648864746,-8.09805679321289],[16.941667556762695,-7.198610305786133],[16.579721450805664,-5.900833129882813],[13.997499465942383,-5.848611831665039],[13.17888069152832,-5.856328964233398],[12.435834884643555,-6.016666412353516],[12.21455192565918,-5.7685546875],[12.526666641235352,-5.724166870117188],[12.565553665161133,-5.025554656982422],[13.088888168334961,-4.662500381469727],[13.091390609741211,-4.633054733276367],[13.413888931274414,-4.882499694824219],[13.72944450378418,-4.445833206176758],[14.400835037231445,-4.277500152587891],[14.418889999389648,-4.887222290039063],[14.66139030456543,-4.909444808959961],[15.890504837036133,-3.943008422851563],[16.226945877075195,-3.328332901000977],[16.195833206176758,-2.175832748413086],[17.714998245239258,-0.537221908569336],[18.091943740844727,2.22416877746582],[18.62495994567871,3.47944450378418],[18.54194450378418,4.335554122924805],[19.421388626098633,5.13416862487793],[20.585554122924805,4.410001754760742],[22.379167556762695,4.127500534057617],[22.89583396911621,4.821111679077148],[23.420278549194336,4.59111213684082],[24.394166946411133,5.115556716918945],[24.734445571899414,4.910833358764648],[25.54222297668457,5.381391525268555],[25.89166831970215,5.192499160766602]],[[12.953054428100586,-5.87611198425293],[12.844167709350586,-5.850555419921875],[12.737222671508789,-5.943611145019531],[12.953054428100586,-5.87611198425293]]]]}},{"type":"Feature","properties":{"name":"Burundi","iso2":"BI","iso3":"BDI"},"geometry":{"type":"MultiPolygon","coordinates":[[[[29.229897,-3.750964],[29.024441,-2.744722],[29.85083,-2.759722],[29.952221,-2.309445],[30.57333,-2.399167],[30.4175,-2.861945],[30.843662,-2.978794],[30.83499900000018,-3.256945],[30.026108000000107,-4.269444],[29.423885,-4.448056],[29.229897,-3.750964]]]]}},{"type":"Feature","properties":{"name":"China","iso2":"CN","iso3":"CHN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[110.72054481506348,20.06333351135254],[111.03109931945801,19.639997482299805],[110.04776191711426,18.380552291870117],[109.56667518615723,18.168886184692383],[108.68553352355957,18.505277633666992],[108.6283130645752,19.2802791595459],[109.25943183898926,19.901662826538086],[110.72054481506348,20.06333351135254]],[[110.52414894104004,19.134443283081055],[110.5102710723877,19.1391658782959],[110.51500129699707,19.132776260375977],[110.52414894104004,19.134443283081055]]],[[[116.71887397766113,20.709440231323242],[116.70526313781738,20.71138572692871],[116.70192909240723,20.719995498657227],[116.71887397766113,20.709440231323242]]],[[[110.59721565246582,20.87944221496582],[110.54802894592285,20.91388511657715],[110.59665107727051,20.958330154418945],[110.59721565246582,20.87944221496582]]],[[[109.12191963195801,21.05527687072754],[109.0727710723877,21.010278701782227],[109.07193183898926,21.050275802612305],[109.12191963195801,21.05527687072754]]],[[[110.54886817932129,21.05916404724121],[110.49803352355957,20.95583152770996],[110.24887275695801,20.97722053527832],[110.54886817932129,21.05916404724121]]],[[[110.49942207336426,21.193330764770508],[110.6141529083252,21.193330764770508],[110.53665351867676,21.09694480895996],[110.49942207336426,21.193330764770508]]],[[[111.83611488342285,21.565275192260742],[111.84055519104004,21.64305305480957],[112.00248908996582,21.651941299438477],[111.83611488342285,21.565275192260742]]],[[[112.53386878967285,21.59083366394043],[112.64804267883301,21.702775955200195],[112.64694404602051,21.638608932495117],[112.53386878967285,21.59083366394043]]],[[[112.80581855773926,21.653329849243164],[112.70332527160645,21.687776565551758],[112.86887550354004,21.766389846801758],[112.80581855773926,21.653329849243164]]],[[[113.38333320617676,22.00889015197754],[113.30748176574707,22.01972007751465],[113.37803840637207,22.0847225189209],[113.38333320617676,22.00889015197754]]],[[[113.29665565490723,22.063886642456055],[113.26776313781738,22.113611221313477],[113.36026191711426,22.153608322143555],[113.29665565490723,22.063886642456055]]],[[[113.59499549865723,22.652219772338867],[113.4861011505127,22.720273971557617],[113.54358863830566,22.73638343811035],[113.59499549865723,22.652219772338867]]],[[[113.58804512023926,22.75055503845215],[113.38720893859863,22.897497177124023],[113.48387336730957,22.90083122253418],[113.58804512023926,22.75055503845215]]],[[[117.11804389953613,23.3991641998291],[116.94470405578613,23.438886642456055],[117.0980396270752,23.49055290222168],[117.11804389953613,23.3991641998291]]],[[[117.40471076965332,23.7711124420166],[117.50749397277832,23.72638511657715],[117.31165504455566,23.579721450805664],[117.40471076965332,23.7711124420166]]],[[[118.12692451477051,24.42582893371582],[118.06218910217285,24.45722007751465],[118.09108924865723,24.54972267150879],[118.18887519836426,24.493886947631836],[118.12692451477051,24.42582893371582]]],[[[119.3016529083252,25.419443130493164],[119.2774829864502,25.503053665161133],[119.3338794708252,25.570276260375977],[119.3016529083252,25.419443130493164]]],[[[119.82666206359863,25.58277702331543],[119.69637489318848,25.42805290222168],[119.7230396270752,25.638887405395508],[119.82666206359863,25.58277702331543]]],[[[119.27777290344238,26.035276412963867],[119.21132850646973,26.071931838989258],[119.40833473205566,25.983606338500977],[119.27777290344238,26.035276412963867]]],[[[121.17082405090332,28.046945571899414],[121.11914253234863,28.133886337280273],[121.24193000793457,28.200551986694336],[121.17082405090332,28.046945571899414]]],[[[121.94109535217285,29.052778244018555],[121.87359809875488,29.1491641998291],[121.94136238098145,29.16499900817871],[121.94109535217285,29.052778244018555]]],[[[122.11192512512207,29.787778854370117],[122.16609382629395,29.652498245239258],[122.03082466125488,29.716108322143555],[122.11192512512207,29.787778854370117]]],[[[122.41137886047363,29.933053970336914],[122.39082527160645,29.829442977905273],[122.31860542297363,29.94166374206543],[122.41137886047363,29.933053970336914]]],[[[121.86580848693848,29.969995498657227],[121.8611011505127,30.081666946411133],[121.90664863586426,30.0322208404541],[121.86580848693848,29.969995498657227]]],[[[122.32527351379395,30.01861000061035],[122.00804328918457,30.004446029663086],[121.96164894104004,30.1391658782959],[122.32527351379395,30.01861000061035]]],[[[122.21111488342285,30.241106033325195],[122.07470893859863,30.287221908569336],[122.21219825744629,30.33916664123535],[122.21111488342285,30.241106033325195]]],[[[122.42025947570801,30.413610458374023],[122.27554512023926,30.432218551635742],[122.27277565002441,30.47499656677246],[122.42025947570801,30.413610458374023]]],[[[121.84499549865723,31.288053512573242],[121.79193305969238,31.369997024536133],[121.87886238098145,31.356664657592773],[121.84499549865723,31.288053512573242]]],[[[121.48776435852051,31.717775344848633],[121.86831855773926,31.489164352416992],[121.20385932922363,31.800539016723633],[121.48776435852051,31.717775344848633]]],[[[119.8994312286377,32.07110786437988],[119.71608924865723,32.27193641662598],[119.82388496398926,32.26805305480957],[119.8994312286377,32.07110786437988]]],[[[121.43609809875488,39.39166450500488],[121.25583076477051,39.409433364868164],[121.39305305480957,39.47915840148926],[121.43609809875488,39.39166450500488]]],[[[123.38220405578613,53.52665901184082],[126.09554481506348,52.76444435119629],[127.58606910705566,50.208566665649414],[127.52942848205566,49.78916358947754],[130.67163276672363,48.864999771118164],[130.52163887023926,48.60777473449707],[130.98855781555176,47.68860054016113],[132.521089553833,47.710275650024414],[133.08856391906738,48.10166358947754],[134.74075508117676,48.26712989807129],[134.76721382141113,47.70749855041504],[134.182466506958,47.32332801818848],[133.90017890930176,46.250314712524414],[133.12219429016113,45.12860298156738],[131.86468696594238,45.34554481506348],[130.94998359680176,44.84110450744629],[131.311372756958,43.392221450805664],[131.12329292297363,42.91082191467285],[130.4052448272705,42.71805000305176],[130.60437202453613,42.42186164855957],[129.90753364562988,43.00582313537598],[129.71191596984863,42.44415473937988],[128.92581367492676,42.02443885803223],[128.05887031555176,42.00332832336426],[128.15582466125488,41.38249397277832],[126.91304206848145,41.79610633850098],[126.01693916320801,40.89999580383301],[124.37359809875488,40.0936222076416],[121.14694404602051,38.72276496887207],[121.75110054016113,39.35166358947754],[121.22886848449707,39.53833198547363],[122.29971504211426,40.511667251586914],[121.17746925354004,40.92193794250488],[120.45526313781738,40.20054817199707],[119.51970863342285,39.868051528930664],[118.92442512512207,39.1280460357666],[117.74387550354004,39.104997634887695],[117.67221260070801,38.38665962219238],[118.84192848205566,38.15054512023926],[118.95665168762207,37.300546646118164],[119.23275947570801,37.14361000061035],[119.76721382141113,37.151384353637695],[120.74054145812988,37.83526802062988],[121.57054328918457,37.42471504211426],[122.56218910217285,37.39638710021973],[122.50470924377441,36.89361000061035],[121.94914436340332,37.00000190734863],[120.78333473205566,36.62193489074707],[120.68081855773926,36.12748146057129],[120.08885383605957,36.19998359680176],[120.23776435852051,35.95943641662598],[119.17608833312988,34.88499641418457],[120.25388526916504,34.30999183654785],[120.83582496643066,32.64083290100098],[121.89554023742676,31.7469425201416],[120.60193061828613,32.09360694885254],[120.10608863830566,31.94388771057129],[119.82666206359863,32.30638313293457],[119.62970161437988,32.26082801818848],[120.12915229797363,31.905553817749023],[120.71443367004395,31.983606338500977],[121.88472175598145,30.97499656677246],[120.14610481262207,30.194719314575195],[121.2844181060791,30.304445266723633],[121.67775917053223,29.96305274963379],[122.12664985656738,29.888887405395508],[121.44832038879395,29.511667251586914],[121.97971534729004,29.585275650024414],[121.93359565734863,29.195276260375977],[121.41192817687988,29.163331985473633],[121.61026191711426,28.72499656677246],[121.13860511779785,28.84055519104004],[121.57859992980957,28.269166946411133],[120.59082221984863,28.079442977905273],[120.84305000305176,27.876943588256836],[120.47747993469238,27.1774959564209],[120.19359016418457,27.2902774810791],[120.42221260070801,27.14527702331543],[120.03386878967285,26.899721145629883],[120.12719917297363,26.641664505004883],[119.54915046691895,26.753610610961914],[119.65804481506348,26.33860969543457],[119.93942451477051,26.35416603088379],[119.42526435852051,25.9969425201416],[119.09276008605957,26.14249610900879],[119.34499549865723,25.938329696655273],[119.70555305480957,25.993608474731445],[119.45110511779785,25.68027687072754],[119.65220832824707,25.357221603393555],[119.30887031555176,25.606943130493164],[119.10220527648926,25.408052444458008],[119.3530445098877,25.250276565551758],[118.87191963195801,25.243886947631836],[119.01609992980957,24.954164505004883],[118.57388496398926,24.884164810180664],[118.62275886535645,24.54388999938965],[118.23970222473145,24.536386489868164],[118.1605396270752,24.688608169555664],[118.01805305480957,24.436384201049805],[117.79202461242676,24.461320877075195],[118.1233081817627,24.2561092376709],[116.5213794708252,23.42083168029785],[116.7874927520752,23.233884811401367],[116.48082160949707,22.938051223754883],[114.22259712219238,22.55055046081543],[114.0333309173584,22.509138107299805],[113.5244312286377,23.011110305786133],[113.82971382141113,23.117219924926758],[113.47747993469238,23.052778244018555],[113.35915565490723,22.883333206176758],[113.5658130645752,22.550275802612305],[113.55443000793457,22.212732315063477],[113.53166389465332,22.194738388061523],[113.16526985168457,22.571386337280273],[113.38804817199707,22.176664352416992],[113.29915046691895,22.175554275512695],[113.22415351867676,22.037500381469727],[113.08638191223145,22.206941604614258],[112.93914985656738,21.868608474731445],[111.89248847961426,21.92027473449707],[111.63720893859863,21.5211124420166],[110.39824867248535,21.38067054748535],[110.15804481506348,20.845552444458008],[110.52916145324707,20.473329544067383],[110.27887153625488,20.24610710144043],[109.92442512512207,20.233606338500977],[109.66192817687988,20.918886184692383],[109.94109535217285,21.446943283081055],[109.57332038879395,21.723329544067383],[109.14276313781738,21.396665573120117],[108.47580909729004,21.940275192260742],[108.51138496398926,21.58916664123535],[107.99002265930176,21.54241371154785],[106.69331550598145,22.030832290649414],[106.70720863342285,22.864999771118164],[105.57747840881348,23.05916404724121],[105.35386848449707,23.3347225189209],[103.96443367004395,22.499113082885742],[103.33638191223145,22.796388626098633],[103.03055000305176,22.4355525970459],[102.47971534729004,22.773889541625977],[102.14074897766113,22.39628791809082],[101.73803901672363,22.4969425201416],[101.57443428039551,22.20916175842285],[101.78720283508301,21.144163131713867],[101.28193855285645,21.18027687072754],[101.14824104309082,21.5726375579834],[101.10526466369629,21.771387100219727],[100.21275520324707,21.432554244995117],[99.96443367004395,22.048887252807617],[99.16276741027832,22.159162521362305],[99.56637763977051,22.938051223754883],[98.92747688293457,23.189165115356445],[98.67720222473145,23.968053817749023],[98.89073371887207,24.160070419311523],[97.5355396270752,23.93971824645996],[97.75999641418457,24.257497787475586],[97.55247688293457,24.743051528930664],[98.71081733703613,25.855554580688477],[98.77832221984863,26.636384963989258],[98.69970893859863,27.539167404174805],[98.31637763977051,27.54194450378418],[97.80664253234863,28.34416389465332],[97.55525398254395,28.54805564880371],[97.34887886047363,28.2227725982666],[96.40193367004395,28.351110458374023],[96.61581611633301,28.7902774810791],[96.47082710266113,29.056665420532227],[96.16914558410645,28.903608322143555],[96.39526557922363,29.255277633666992],[96.07748603820801,29.46860694885254],[95.38777351379395,29.035276412963867],[94.64750862121582,29.333459854125977],[92.54498481750488,27.861940383911133],[91.65776252746582,27.76472282409668],[91.30137825012207,28.08111000061035],[90.46638679504395,28.071664810180664],[90.01748847961426,28.32527732849121],[89.59027290344238,28.14333152770996],[88.91772651672363,27.32032585144043],[88.83166694641113,28.013334274291992],[88.14279365539551,27.866056442260742],[87.19275093078613,27.82305335998535],[86.68637275695801,28.112218856811523],[86.44497871398926,27.908052444458008],[86.18359565734863,28.16388511657715],[86.01443672180176,27.882776260375977],[85.72137641906738,28.279165267944336],[85.10664558410645,28.3094425201416],[85.18997383117676,28.603330612182617],[84.4810962677002,28.736661911010742],[84.11914253234863,29.260000228881836],[83.55276679992676,29.18583106994629],[82.10054206848145,30.342222213745117],[81.42109870910645,30.38527488708496],[81.22360420227051,30.010278701782227],[81.02536201477051,30.204355239868164],[79.09248542785645,31.437498092651367],[78.76721382141113,31.309999465942383],[78.39776802062988,32.54860877990723],[78.76054573059082,32.63555335998535],[78.97110176086426,32.35083198547363],[79.53027534484863,32.754167556762695],[78.81164741516113,33.525827407836914],[78.98535346984863,34.35001564025879],[78.30914497375488,34.64249610900879],[78.07554817199707,35.44582557678223],[77.82393074035645,35.50132942199707],[76.16638374328613,35.819719314575195],[75.86442756652832,36.659677505493164],[74.81749153137207,37.02176856994629],[74.56543159484863,37.02781867980957],[74.39221382141113,37.17507362365723],[74.91574287414551,37.23732948303223],[75.18748664855957,37.40658760070801],[74.90277290344238,37.64715766906738],[74.85664558410645,38.47048377990723],[73.8177661895752,38.60771369934082],[73.65568733215332,39.4548282623291],[73.99443244934082,40.04604530334473],[74.86026191711426,40.51938819885254],[75.57805061340332,40.64799690246582],[75.69720649719238,40.29911231994629],[76.34582710266113,40.35022163391113],[76.87387275695801,41.014108657836914],[78.0808277130127,41.040788650512695],[80.2340259552002,42.19622230529785],[80.17192268371582,42.66050910949707],[80.57859992980957,42.89107704162598],[80.37664985656738,43.02523994445801],[80.81721687316895,43.15606880187988],[80.36276435852051,44.12524604797363],[80.52083015441895,44.73247718811035],[79.87109565734863,44.904977798461914],[81.68831062316895,45.35081672668457],[82.56164741516113,45.12941932678223],[82.6494312286377,45.43026161193848],[82.3177661895752,45.57053565979004],[83.0405445098877,47.21221351623535],[84.75943183898926,46.82638740539551],[85.5293140411377,47.06016731262207],[85.75915718078613,48.387773513793945],[86.59610176086426,48.53611183166504],[86.87469673156738,49.11082649230957],[87.34820747375488,49.09262275695801],[87.84070014953613,49.17295265197754],[87.97331428527832,48.57694435119629],[88.65332221984863,48.18277168273926],[90.07443428039551,47.88638496398926],[91.02025032043457,46.60011100769043],[90.68193244934082,45.579721450805664],[90.89694404602051,45.25305366516113],[93.5547046661377,44.95721626281738],[95.41665840148926,44.29388618469238],[95.33610725402832,44.020830154418945],[96.38304328918457,42.73110389709473],[100.83554267883301,42.678049087524414],[105.01220893859863,41.58138465881348],[107.4719181060791,42.46610450744629],[109.31360054016113,42.42999458312988],[110.44053840637207,42.77777290344238],[111.95833015441895,43.692216873168945],[111.42137336730957,44.38249397277832],[111.98082160949707,45.09166145324707],[113.63804817199707,44.74527168273926],[114.54525947570801,45.38943672180176],[115.70192909240723,45.45860481262207],[116.58554267883301,46.29583168029785],[117.42109870910645,46.57833290100098],[119.89749336242676,46.675554275512695],[119.72998237609863,47.16415596008301],[118.53933906555176,47.99475288391113],[117.80108833312988,48.01055335998535],[117.37219429016113,47.65359687805176],[115.59219551086426,47.919443130493164],[116.71138191223145,49.83046913146973],[117.87471199035645,49.520578384399414],[119.21415901184082,50.015275955200195],[119.36136817932129,50.33693885803223],[119.13860511779785,50.39471626281738],[120.77665901184082,52.114999771118164],[120.71360969543457,52.54471778869629],[120.02916145324707,52.76805305480957],[120.86387825012207,53.27971839904785],[123.38220405578613,53.52665901184082]],[[108.32971382141113,21.654165267944336],[108.3288745880127,21.67860984802246],[108.32083320617676,21.665830612182617],[108.32971382141113,21.654165267944336]]]]}},{"type":"Feature","properties":{"name":"Afghanistan","iso2":"AF","iso3":"AFG"},"geometry":{"type":"MultiPolygon","coordinates":[[[[74.915741,37.237328],[74.392212,37.175072],[74.56543,37.027817],[72.556641,36.821266],[71.2435760000001,36.129715],[71.64942900000014,35.424995],[70.987488,34.551102000000114],[71.08194000000012,34.05582400000013],[69.90637200000018,34.035271],[70.326935,33.33194],[69.505264,33.034164],[69.32824700000012,31.940365000000114],[68.833054,31.603886],[68.166092,31.833054000000104],[67.575546,31.53194000000012],[67.778046,31.33221800000014],[66.72303800000012,31.212215],[66.395538,30.94083],[66.256653,29.851940000000113],[62.4844360000001,29.406105],[60.86859900000016,29.863884],[61.8511050000001,31.021111],[61.713608,31.383331],[60.84388,31.498329],[60.582497,33.06610100000013],[60.94304700000012,33.51944],[60.527771,33.64415700000011],[60.50833100000014,34.140274],[60.87887600000013,34.319717],[60.721657,34.522217],[61.27655800000011,35.60724600000013],[62.30915800000011,35.141663],[62.722214,35.254715],[63.10527000000016,35.45082900000013],[63.1194380000002,35.861938],[64.503601,36.280548],[64.798035,37.12499200000015],[65.70887800000011,37.538605],[66.537735,37.366379],[67.779877,37.185822],[68.058014,36.932526],[68.887772,37.3386],[69.315262,37.115273],[69.515823,37.580826],[70.155823,37.536232],[70.161377,37.933372],[70.967209,38.472115],[71.363037,38.248497],[71.252777,37.922035],[71.591934,37.902618],[71.429428,37.075829],[71.6772,36.67601],[73.307205,37.462753],[74.915741,37.237328]]]]}},{"type":"Feature","properties":{"name":"Bhutan","iso2":"BT","iso3":"BTN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[90.466385,28.071663],[91.301376,28.081108],[91.657761,27.764721],[92.113602,27.29749700000012],[92.069992,26.861942],[89.643051,26.715271],[88.89387500000012,26.975552],[88.9177250000001,27.320324],[89.59027100000012,28.14333],[90.017487,28.325275],[90.466385,28.071663]]]]}},{"type":"Feature","properties":{"name":"Chile","iso2":"CL","iso3":"CHL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-67.49305725097656,-55.82917022705078],[-67.61195373535156,-55.90222930908203],[-67.85751342773438,-55.84916687011719],[-67.49305725097656,-55.82917022705078]]],[[[-67.21278381347656,-55.89361572265625],[-67.41389465332031,-55.83222961425781],[-67.2469482421875,-55.82805633544922],[-67.21278381347656,-55.89361572265625]]],[[[-67.08528137207031,-55.917503356933594],[-67.17167663574219,-55.874168395996094],[-67.1058349609375,-55.80194854736328],[-67.08528137207031,-55.917503356933594]]],[[[-67.167236328125,-55.78639221191406],[-67.24139404296875,-55.790283203125],[-67.17388916015625,-55.75972557067871],[-67.167236328125,-55.78639221191406]]],[[[-67.26806640625,-55.72138977050781],[-67.55639457702637,-55.71222686767578],[-67.35667419433594,-55.57472229003906],[-67.26806640625,-55.72138977050781]]],[[[-67.72862243652344,-55.62445068359375],[-67.68806457519531,-55.501670837402344],[-67.58973693847656,-55.540557861328125],[-67.72862243652344,-55.62445068359375]]],[[[-69.69056701660156,-55.412506103515625],[-69.76472473144531,-55.33778381347656],[-69.63751220703125,-55.38250732421875],[-69.69056701660156,-55.412506103515625]]],[[[-69.98529052734375,-55.364173889160156],[-70.10612487792969,-55.29583740234375],[-69.94223022460938,-55.28722381591797],[-69.98529052734375,-55.364173889160156]]],[[[-66.87472534179688,-55.33222961425781],[-67.07362365722656,-55.27611541748047],[-66.87861633300781,-55.22888946533203],[-66.87472534179688,-55.33222961425781]]],[[[-66.57139587402344,-55.28472900390625],[-66.62611389160156,-55.19972229003906],[-66.42056274414062,-55.194725036621094],[-66.57139587402344,-55.28472900390625]]],[[[-66.81668090820312,-55.118614196777344],[-67.07223510742188,-55.002784729003906],[-66.86222839355469,-55.026390075683594],[-66.81668090820312,-55.118614196777344]]],[[[-68.39666557312012,-54.959449768066406],[-69.06111145019531,-55.057228088378906],[-68.21055603027344,-55.26500701904297],[-68.74501037597656,-55.2711181640625],[-68.15945434570312,-55.39861297607422],[-68.05361938476562,-55.712501525878906],[-68.93917846679688,-55.45972442626953],[-68.80361938476562,-55.18861389160156],[-69.43000793457031,-55.161949157714844],[-69.17417907714844,-55.51222229003906],[-70.03334045410156,-55.156394958496094],[-68.39666557312012,-54.959449768066406]]],[[[-67.78056335449219,-54.91944885253906],[-67.05361938476562,-55.136390686035156],[-68.09529113769531,-55.23694610595703],[-68.36445617675781,-54.94445037841797],[-67.78056335449219,-54.91944885253906]]],[[[-70.50875854492188,-54.970054626464844],[-70.73417663574219,-55.015281677246094],[-70.26445007324219,-55.116111755371094],[-71.01583862304688,-54.96666717529297],[-70.31167602539062,-54.90472412109375],[-70.50875854492188,-54.970054626464844]]],[[[-69.76222229003906,-55.038612365722656],[-69.93194580078125,-54.899169921875],[-69.16639709472656,-54.958335876464844],[-69.76222229003906,-55.038612365722656]]],[[[-71.10694885253906,-54.8719482421875],[-70.9122314453125,-54.92444610595703],[-71.45668029785156,-54.88500213623047],[-71.10694885253906,-54.8719482421875]]],[[[-70.60917663574219,-54.90472412109375],[-70.74555969238281,-54.87445068359375],[-70.39361572265625,-54.871673583984375],[-70.60917663574219,-54.90472412109375]]],[[[-72.0211181640625,-54.63472557067871],[-71.93112182617188,-54.744728088378906],[-72.10139465332031,-54.656394958496094],[-72.0211181640625,-54.63472557067871]]],[[[-72.30833435058594,-54.369171142578125],[-72.46334838867188,-54.43000030517578],[-72.54055786132812,-54.341392517089844],[-72.30833435058594,-54.369171142578125]]],[[[-70.28140258789062,-54.27555847167969],[-70.51112365722656,-54.16083526611328],[-70.21890258789062,-54.22666931152344],[-70.28140258789062,-54.27555847167969]]],[[[-71.25750732421875,-54.07611846923828],[-71.00973510742188,-54.102783203125],[-71.11639404296875,-54.38472557067871],[-71.69944763183594,-54.16111755371094],[-71.25750732421875,-54.07611846923828]]],[[[-72.32223510742188,-54.258056640625],[-72.51112365722656,-54.202781677246094],[-72.30168151855469,-54.07167053222656],[-72.20695495605469,-54.148338317871094],[-72.32223510742188,-54.258056640625]]],[[[-73.19416809082031,-54.12889099121094],[-73.47056579589844,-54.072784423828125],[-73.24667358398438,-54.03583526611328],[-73.19416809082031,-54.12889099121094]]],[[[-71.67111206054688,-53.94389343261719],[-71.95361328125,-54.019447326660156],[-71.8466796875,-54.33972930908203],[-72.25750732421875,-53.94111633300781],[-71.67111206054688,-53.94389343261719]]],[[[-70.44195556640625,-53.860557556152344],[-70.67445373535156,-53.926673889160156],[-70.52444458007812,-54.228614807128906],[-70.87861633300781,-54.05083465576172],[-70.53445434570312,-53.56083679199219],[-70.44195556640625,-53.860557556152344]]],[[[-73.83195495605469,-53.59027862548828],[-73.85722351074219,-53.453338623046875],[-73.6875,-53.52166557312012],[-73.83195495605469,-53.59027862548828]]],[[[-72.91111755371094,-53.42945098876953],[-72.87834167480469,-53.68194580078125],[-72.84390258789062,-53.45806121826172],[-72.13945007324219,-53.801673889160156],[-72.87083435058594,-54.13667297363281],[-72.73222351074219,-53.83972930908203],[-73.13250732421875,-54.01167297363281],[-73.25,-53.70722961425781],[-73.58778381347656,-53.75556182861328],[-72.91111755371094,-53.42945098876953]]],[[[-73.46389770507812,-53.475006103515625],[-73.49473571777344,-53.57444763183594],[-73.80195617675781,-53.429168701171875],[-73.46389770507812,-53.475006103515625]]],[[[-74.19168090820312,-53.331947326660156],[-74.24362182617188,-53.29972839355469],[-74.0594482421875,-53.24305725097656],[-74.19168090820312,-53.331947326660156]]],[[[-73.41307067871094,-52.87861633300781],[-73.39111328125,-52.95361328125],[-73.75222778320312,-52.893333435058594],[-73.41307067871094,-52.87861633300781]]],[[[-70.72584533691406,-52.89361572265625],[-70.78083801269531,-52.877784729003906],[-70.61889457702637,-52.82139587402344],[-70.72584533691406,-52.89361572265625]]],[[[-74.36056518554688,-52.948890686035156],[-74.74501037597656,-52.75666809082031],[-73.09001159667969,-53.35472869873047],[-74.36056518554688,-52.948890686035156]]],[[[-70.917236328125,-54.7086181640625],[-70.77139282226562,-54.681114196777344],[-70.87028503417969,-54.68639373779297],[-70.917236328125,-54.7086181640625],[-72.00306701660156,-54.46361541748047],[-70.13084411621094,-54.54888916015625],[-70.88027954101562,-54.13389587402344],[-70.14279174804688,-54.42833709716797],[-70.20083618164062,-54.31611633300781],[-70.05528259277344,-54.249168395996094],[-69.77000427246094,-54.55750274658203],[-69.85917663574219,-54.283058166503906],[-69.24111938476562,-54.44639587402344],[-69.37640380859375,-54.686668395996094],[-69.17750358581543,-54.580833435058594],[-68.99166870117188,-54.43194580078125],[-70.1844482421875,-53.81361389160156],[-69.35639953613281,-53.351112365722656],[-70.44667053222656,-53.36805725097656],[-70.4444580078125,-53.012779235839844],[-70.0997314453125,-52.90416717529297],[-70.42472839355469,-52.77305603027344],[-69.917236328125,-52.825836181640625],[-69.42056274414062,-52.45806121826172],[-68.61758422851562,-52.641510009765625],[-68.63583374023438,-54.78833770751953],[-68.63612365722656,-54.804771423339844],[-68.64311218261719,-54.88861083984375],[-70.917236328125,-54.7086181640625]]],[[[-73.80751037597656,-52.698333740234375],[-74.07778930664062,-52.60667419433594],[-73.74223327636719,-52.40361785888672],[-73.80751037597656,-52.698333740234375]]],[[[-74.73945617675781,-52.31694793701172],[-74.820556640625,-52.22944641113281],[-74.62001037597656,-52.20777893066406],[-74.73945617675781,-52.31694793701172]]],[[[-73.80805969238281,-52.39722442626953],[-74.09278869628906,-52.161949157714844],[-73.78916931152344,-52.26416778564453],[-73.80805969238281,-52.39722442626953]]],[[[-74.19416809082031,-52.13667297363281],[-73.93501281738281,-52.33722686767578],[-74.41862487792969,-52.13972473144531],[-74.19416809082031,-52.13667297363281]]],[[[-74.76251220703125,-52.18833923339844],[-74.7852783203125,-52.12139129638672],[-74.59611511230469,-52.07361602783203],[-74.76251220703125,-52.18833923339844]]],[[[-74.36056518554688,-52.07722473144531],[-74.40583801269531,-52.04722595214844],[-74.35417175292969,-52.056114196777344],[-74.36056518554688,-52.07722473144531]]],[[[-74.71722412109375,-52.08722686767578],[-74.55195617675781,-51.92750358581543],[-74.48779296875,-51.95722961425781],[-74.71722412109375,-52.08722686767578]]],[[[-73.69473266601562,-52.241668701171875],[-74.09529113769531,-51.92278289794922],[-73.76806640625,-52.06833457946777],[-73.69473266601562,-52.241668701171875]]],[[[-74.86361694335938,-52.13916778564453],[-74.7469482421875,-51.833892822265625],[-74.59916687011719,-51.84056091308594],[-74.86361694335938,-52.13916778564453]]],[[[-75.08973693847656,-51.90167236328125],[-75.07084655761719,-51.74028015136719],[-74.97250366210938,-51.72361755371094],[-75.08973693847656,-51.90167236328125]]],[[[-74.14472961425781,-51.951393127441406],[-74.50527954101562,-51.71417236328125],[-74.09222412109375,-51.875],[-74.14472961425781,-51.951393127441406]]],[[[-73.79667663574219,-51.81916809082031],[-73.94000244140625,-51.663063049316406],[-73.7933349609375,-51.728614807128906],[-73.79667663574219,-51.81916809082031]]],[[[-74.78111267089844,-51.82167053222656],[-74.9697265625,-52.11805725097656],[-74.93251037597656,-51.64361572265625],[-74.78111267089844,-51.82167053222656]]],[[[-74.05500793457031,-51.553611755371094],[-73.94000244140625,-51.78583526611328],[-74.23806762695312,-51.701393127441406],[-74.05500793457031,-51.553611755371094]]],[[[-75.00028991699219,-51.39556121826172],[-75.31028747558594,-51.63417053222656],[-75.20529174804688,-51.299171447753906],[-75.00028991699219,-51.39556121826172]]],[[[-74.11778259277344,-51.454444885253906],[-74.26139831542969,-51.300559997558594],[-74.17111206054688,-51.28583526611328],[-74.11778259277344,-51.454444885253906]]],[[[-73.78140258789062,-51.37139129638672],[-73.91445922851562,-51.30000305175781],[-73.79139709472656,-51.26111602783203],[-73.78140258789062,-51.37139129638672]]],[[[-74.04583740234375,-51.379173278808594],[-74.09722900390625,-51.22583770751953],[-73.96806335449219,-51.244171142578125],[-74.04583740234375,-51.379173278808594]]],[[[-74.53611755371094,-51.27916717529297],[-75.0211181640625,-51.46833801269531],[-74.79389953613281,-51.209449768066406],[-74.53611755371094,-51.27916717529297]]],[[[-74.99555969238281,-51.177223205566406],[-74.94000244140625,-51.09861755371094],[-74.85722351074219,-51.135284423828125],[-74.99555969238281,-51.177223205566406]]],[[[-74.41166687011719,-51.208335876464844],[-74.60305786132812,-51.07750701904297],[-74.4666748046875,-51.02833557128906],[-74.41166687011719,-51.208335876464844]]],[[[-74.26333618164062,-51.247779846191406],[-74.32223510742188,-50.91972351074219],[-74.19139099121094,-51.195556640625],[-74.26333618164062,-51.247779846191406]]],[[[-74.39666557312012,-50.860557556152344],[-74.40556335449219,-51.08972930908203],[-74.48222351074219,-50.997779846191406],[-74.72056579589844,-51.11194610595703],[-74.96473693847656,-50.96583557128906],[-74.39666557312012,-50.860557556152344]]],[[[-74.68917846679688,-50.890838623046875],[-74.95472717285156,-50.731117248535156],[-74.7489013671875,-50.70195007324219],[-74.68917846679688,-50.890838623046875]]],[[[-74.99389457702637,-50.81389617919922],[-75.07084655761719,-50.65222930908203],[-74.979736328125,-50.664451599121094],[-74.99389457702637,-50.81389617919922]]],[[[-74.65139770507812,-50.58861541748047],[-74.68583679199219,-50.52166557312012],[-74.58168029785156,-50.5322265625],[-74.65139770507812,-50.58861541748047]]],[[[-75.09638977050781,-50.516395568847656],[-75.28889465332031,-50.78583526611328],[-75.5150146484375,-50.663063049316406],[-75.09638977050781,-50.516395568847656]]],[[[-74.3638916015625,-50.49139404296875],[-74.19334411621094,-50.84833526611328],[-74.5150146484375,-50.733062744140625],[-74.42361450195312,-50.52361297607422],[-74.67001342773438,-50.47944641113281],[-74.3638916015625,-50.49139404296875]]],[[[-74.73834228515625,-50.5],[-74.75306701660156,-50.388336181640625],[-74.54362487792969,-50.38139343261719],[-74.73834228515625,-50.5]]],[[[-75.04861450195312,-50.16694641113281],[-74.78973388671875,-50.149444580078125],[-75.4586181640625,-50.364173889160156],[-75.14361572265625,-50.24639129638672],[-75.39973258972168,-50.03666687011719],[-75.04861450195312,-50.16694641113281]]],[[[-75.30694580078125,-49.67195129394531],[-75.17388916015625,-49.90306091308594],[-75.59194946289062,-49.78388977050781],[-75.30694580078125,-49.67195129394531]]],[[[-75.48056030273438,-49.54722595214844],[-75.57890319824219,-49.46472930908203],[-75.48445129394531,-49.481117248535156],[-75.48056030273438,-49.54722595214844]]],[[[-74.29417419433594,-49.56056213378906],[-74.41944885253906,-49.627784729003906],[-74.43583679199219,-49.42750358581543],[-74.29417419433594,-49.56056213378906]]],[[[-74.92056274414062,-49.295005798339844],[-75.24028015136719,-49.15028381347656],[-74.97250366210938,-49.03111267089844],[-74.92056274414062,-49.295005798339844]]],[[[-75.28584289550781,-49.10028076171875],[-75.65640258789062,-49.216949462890625],[-75.35890197753906,-48.985557556152344],[-75.28584289550781,-49.10028076171875]]],[[[-75.28140258789062,-48.89000701904297],[-75.25778198242188,-49.081947326660156],[-75.322509765625,-48.954444885253906],[-75.5,-49.04639434814453],[-75.65667724609375,-48.93889617919922],[-75.28140258789062,-48.89000701904297]]],[[[-75.17611694335938,-48.999725341796875],[-75.3125,-48.80000305175781],[-75.08222961425781,-48.88916778564453],[-75.17611694335938,-48.999725341796875]]],[[[-74.97944641113281,-48.74250030517578],[-74.99139404296875,-48.648895263671875],[-74.8255615234375,-48.66166687011719],[-74.97944641113281,-48.74250030517578]]],[[[-75.28167724609375,-48.713340759277344],[-75.65472412109375,-48.76805877685547],[-75.34806823730469,-48.63555908203125],[-75.28167724609375,-48.713340759277344]]],[[[-75.12055969238281,-48.8336181640625],[-75.24833679199219,-48.771392822265625],[-75.07139587402344,-48.63444519042969],[-75.12055969238281,-48.8336181640625]]],[[[-75.322509765625,-48.60417175292969],[-75.60111999511719,-48.69194793701172],[-75.65055847167969,-48.48194885253906],[-75.322509765625,-48.60417175292969]]],[[[-74.41139221191406,-48.530006408691406],[-74.49778747558594,-48.399169921875],[-74.30195617675781,-48.47583770751953],[-74.41139221191406,-48.530006408691406]]],[[[-74.04917907714844,-48.44611358642578],[-74.07417297363281,-48.491111755371094],[-74.2489013671875,-48.37639617919922],[-74.04917907714844,-48.44611358642578]]],[[[-74.26445007324219,-48.466949462890625],[-74.49166870117188,-48.351112365722656],[-74.30639457702637,-48.28666687011719],[-74.26445007324219,-48.466949462890625]]],[[[-74.41889953613281,-48.304725646972656],[-74.5372314453125,-48.333892822265625],[-74.5997314453125,-48.15167236328125],[-74.41889953613281,-48.304725646972656]]],[[[-74.60833740234375,-48.455833435058594],[-74.41278076171875,-49.732505798339844],[-74.7711181640625,-50.05500030517578],[-74.92001342773438,-49.68305969238281],[-74.64639282226562,-49.355560302734375],[-75.0050048828125,-49.508056640625],[-75.01722717285156,-49.899444580078125],[-75.47111511230469,-49.33167266845703],[-74.91806030273438,-49.33611297607422],[-74.82722473144531,-49.09584045410156],[-75.0513916015625,-48.79833984375],[-74.61111450195312,-48.69667053222656],[-75.02862358093262,-48.49500274658203],[-74.7086181640625,-48.45417022705078],[-74.73500061035156,-48.12306213378906],[-74.60833740234375,-48.455833435058594]]],[[[-75.23945617675781,-48.27056121826172],[-75.23445129394531,-48.711395263671875],[-75.58250427246094,-48.086669921875],[-75.23945617675781,-48.27056121826172]]],[[[-74.92500305175781,-48.15583801269531],[-75.04417419433594,-48.44361114501953],[-75.2569580078125,-48.073333740234375],[-74.92500305175781,-48.15583801269531]]],[[[-74.80528259277344,-47.89805603027344],[-74.86973571777344,-48.06916809082031],[-75.26667785644531,-48.031951904296875],[-74.80528259277344,-47.89805603027344]]],[[[-73.92445373535156,-47.88611602783203],[-73.79972839355469,-47.887779235839844],[-74.4989013671875,-47.923057556152344],[-73.92445373535156,-47.88611602783203]]],[[[-75.1319580078125,-47.84889221191406],[-75.30361938476562,-47.773338317871094],[-75.13444519042969,-47.698333740234375],[-75.1319580078125,-47.84889221191406]]],[[[-74.95472717285156,-47.783058166503906],[-75.07528686523438,-47.69445037841797],[-74.95140075683594,-47.706390380859375],[-74.95472717285156,-47.783058166503906]]],[[[-74.45529174804688,-47.17694854736328],[-74.48417663574219,-47.083335876464844],[-74.31306457519531,-47.062782287597656],[-74.45529174804688,-47.17694854736328]]],[[[-74.15444946289062,-47.17250061035156],[-74.18362426757812,-47.02528381347656],[-73.97528076171875,-47.04750061035156],[-74.15444946289062,-47.17250061035156]]],[[[-73.7650146484375,-46.21111297607422],[-73.9122314453125,-46.02027893066406],[-73.68333435058594,-46.07666778564453],[-73.7650146484375,-46.21111297607422]]],[[[-73.68112182617188,-46.02833557128906],[-73.8194580078125,-45.99889373779297],[-73.77806091308594,-45.905006408691406],[-73.68112182617188,-46.02833557128906]]],[[[-74.71556091308594,-45.851951599121094],[-75.08306884765625,-46.08861541748047],[-75.10195922851562,-45.874168395996094],[-74.71556091308594,-45.851951599121094]]],[[[-73.70390319824219,-45.84278106689453],[-73.92889404296875,-45.97583770751953],[-73.88417053222656,-45.858612060546875],[-73.70390319824219,-45.84278106689453]]],[[[-74.0150146484375,-45.91777801513672],[-74.10694885253906,-45.78833770751953],[-74.03861999511719,-45.73638916015625],[-74.0150146484375,-45.91777801513672]]],[[[-74.75279235839844,-45.70777893066406],[-74.87667846679688,-45.64972686767578],[-74.86917114257812,-45.6058349609375],[-74.75279235839844,-45.70777893066406]]],[[[-74.62028503417969,-45.75695037841797],[-74.68251037597656,-45.63694763183594],[-74.54861450195312,-45.57750701904297],[-74.62028503417969,-45.75695037841797]]],[[[-73.98695373535156,-45.72472381591797],[-74.11000061035156,-45.59278106689453],[-74.01194763183594,-45.537506103515625],[-73.8961181640625,-45.62055969238281],[-73.98695373535156,-45.72472381591797]]],[[[-74.4586181640625,-45.77916717529297],[-74.39028930664062,-45.44389343261719],[-74.21000671386719,-45.63611602783203],[-74.4586181640625,-45.77916717529297]]],[[[-73.64556884765625,-45.75944519042969],[-73.78195190429688,-45.67028045654297],[-73.7005615234375,-45.44389343261719],[-73.64556884765625,-45.75944519042969]]],[[[-74.01779174804688,-45.43305969238281],[-73.81584167480469,-45.47583770751953],[-74.14472961425781,-45.576393127441406],[-74.01779174804688,-45.43305969238281]]],[[[-74.50445556640625,-45.539451599121094],[-74.57000732421875,-45.52916717529297],[-74.43806457519531,-45.42388916015625],[-74.50445556640625,-45.539451599121094]]],[[[-73.89695739746094,-45.434173583984375],[-74.024169921875,-45.40028381347656],[-73.8255615234375,-45.37306213378906],[-73.89695739746094,-45.434173583984375]]],[[[-74.34140014648438,-45.40611267089844],[-74.52778625488281,-45.30528259277344],[-74.38722229003906,-45.288063049316406],[-74.34140014648438,-45.40611267089844]]],[[[-73.97666931152344,-45.26750183105469],[-73.78306579589844,-45.33528137207031],[-74.16612243652344,-45.25055694580078],[-73.97666931152344,-45.26750183105469]]],[[[-74.30889892578125,-45.30583953857422],[-74.39472961425781,-45.154449462890625],[-74.27056884765625,-45.21417236328125],[-74.30889892578125,-45.30583953857422]]],[[[-73.8466796875,-45.002784729003906],[-73.73139953613281,-45.284446716308594],[-74.23583984375,-45.1602783203125],[-73.8466796875,-45.002784729003906]]],[[[-73.98028564453125,-44.98445129394531],[-74.36666870117188,-45.01055908203125],[-74.1683349609375,-44.866668701171875],[-73.98028564453125,-44.98445129394531]]],[[[-74.026123046875,-44.85694885253906],[-74.18667602539062,-44.8125],[-73.95777893066406,-44.78361511230469],[-74.026123046875,-44.85694885253906]]],[[[-73.79362487792969,-44.965003967285156],[-73.92417907714844,-44.89222717285156],[-73.91778564453125,-44.78166961669922],[-73.79362487792969,-44.965003967285156]]],[[[-75.0694580078125,-44.925559997558594],[-75.11167907714844,-44.77833557128906],[-75.02305603027344,-44.84638977050781],[-75.0694580078125,-44.925559997558594]]],[[[-73.651123046875,-44.844451904296875],[-73.7489013671875,-44.75639343261719],[-73.60833740234375,-44.741111755371094],[-73.651123046875,-44.844451904296875]]],[[[-74.376953125,-44.85945129394531],[-74.52639770507812,-44.74195098876953],[-74.42945861816406,-44.719451904296875],[-74.376953125,-44.85945129394531]]],[[[-74.20973205566406,-44.784446716308594],[-74.40972900390625,-44.63444519042969],[-73.87333679199219,-44.68695068359375],[-74.20973205566406,-44.784446716308594]]],[[[-74.45556640625,-44.69389343261719],[-74.67361450195312,-44.668617248535156],[-74.57833862304688,-44.62000274658203],[-74.45556640625,-44.69389343261719]]],[[[-74.77723693847656,-44.6875],[-74.80416870117188,-44.549171447753906],[-74.72611999511719,-44.5977783203125],[-74.77723693847656,-44.6875]]],[[[-73.74555969238281,-44.743614196777344],[-73.68861389160156,-44.54444885253906],[-73.58973693847656,-44.70972442626953],[-73.74555969238281,-44.743614196777344]]],[[[-74.2952880859375,-44.57722473144531],[-74.36834716796875,-44.53278350830078],[-74.13917541503906,-44.550559997558594],[-74.2952880859375,-44.57722473144531]]],[[[-74.41250610351562,-44.512779235839844],[-74.54750061035156,-44.468055725097656],[-74.21778869628906,-44.468055725097656],[-74.41250610351562,-44.512779235839844]]],[[[-74.01972961425781,-44.556671142578125],[-74.12945556640625,-44.448333740234375],[-73.95945739746094,-44.48278045654297],[-74.01972961425781,-44.556671142578125]]],[[[-73.84417724609375,-44.464447021484375],[-73.89889526367188,-44.371673583984375],[-73.78861999511719,-44.42250061035156],[-73.84417724609375,-44.464447021484375]]],[[[-72.7227783203125,-44.549171447753906],[-72.81916809082031,-44.64055633544922],[-72.98333740234375,-44.606117248535156],[-72.82833862304688,-44.69055938720703],[-73.13833618164062,-44.913063049316406],[-73.28028869628906,-44.94000244140625],[-73.40779113769531,-44.820556640625],[-73.20722961425781,-44.798614501953125],[-73.46473693847656,-44.644447326660156],[-72.99806213378906,-44.367225646972656],[-72.7227783203125,-44.549171447753906]]],[[[-73.68890380859375,-44.439727783203125],[-73.78807067871094,-44.38195037841797],[-73.65278625488281,-44.352783203125],[-73.68890380859375,-44.439727783203125]]],[[[-73.92945861816406,-44.44805908203125],[-74.10556030273438,-44.322784423828125],[-73.93084716796875,-44.355560302734375],[-73.92945861816406,-44.44805908203125]]],[[[-73.24195861816406,-44.388336181640625],[-73.3033447265625,-44.36333465576172],[-73.24972534179688,-44.31083679199219],[-73.16889953613281,-44.37000274658203],[-73.24195861816406,-44.388336181640625]]],[[[-73.84695434570312,-44.33805847167969],[-73.97389221191406,-44.281951904296875],[-73.80223083496094,-44.270835876464844],[-73.84695434570312,-44.33805847167969]]],[[[-73.71139526367188,-44.304168701171875],[-73.76112365722656,-44.25389099121094],[-73.66555786132812,-44.25139617919922],[-73.71139526367188,-44.304168701171875]]],[[[-74.29167175292969,-44.30639457702637],[-74.42140197753906,-44.262779235839844],[-74.32722473144531,-44.24639129638672],[-74.29167175292969,-44.30639457702637]]],[[[-74.32000732421875,-44.19500732421875],[-74.38555908203125,-44.154449462890625],[-74.25917053222656,-44.159446716308594],[-74.32000732421875,-44.19500732421875]]],[[[-74.01167297363281,-44.28417205810547],[-74.12611389160156,-44.20777893066406],[-74.06723022460938,-44.151947021484375],[-74.01167297363281,-44.28417205810547]]],[[[-73.852783203125,-44.195838928222656],[-74.01112365722656,-44.141944885253906],[-73.92222595214844,-44.09889221191406],[-73.852783203125,-44.195838928222656]]],[[[-74.2933349609375,-44.031951904296875],[-74.3194580078125,-44.01722717285156],[-74.20472717285156,-44.01917266845703],[-74.2933349609375,-44.031951904296875]]],[[[-73.6461181640625,-44.13139343261719],[-73.72862243652344,-43.93889617919922],[-73.63444519042969,-44.01000213623047],[-73.6461181640625,-44.13139343261719]]],[[[-73.15501403808594,-44.02278137207031],[-73.26945495605469,-43.92083740234375],[-73.14805603027344,-43.888336181640625],[-73.15501403808594,-44.02278137207031]]],[[[-73.85556030273438,-43.765838623046875],[-73.7650146484375,-43.893333435058594],[-74.17250061035156,-43.877784729003906],[-73.85556030273438,-43.765838623046875]]],[[[-74.6461181640625,-43.61250305175781],[-74.79389953613281,-43.64778137207031],[-74.86250305175781,-43.5625],[-74.6461181640625,-43.61250305175781]]],[[[-73.59750366210938,-42.61805725097656],[-73.75140380859375,-42.617225646972656],[-73.61889457702637,-42.570281982421875],[-73.59750366210938,-42.61805725097656]]],[[[-73.41667175292969,-42.55639457702637],[-73.6541748046875,-42.38750457763672],[-73.53584289550781,-42.38500213623047],[-73.41667175292969,-42.55639457702637]]],[[[-73.10612487792969,-42.31139373779297],[-73.18972778320312,-42.25139617919922],[-73.06916809082031,-42.260284423828125],[-73.10612487792969,-42.31139373779297]]],[[[-72.5130615234375,-42.152503967285156],[-72.61695861816406,-42.0977783203125],[-72.50944519042969,-42.06083679199219],[-72.5130615234375,-42.152503967285156]]],[[[-73.88528442382812,-41.81555938720703],[-73.50111389160156,-41.84333801269531],[-73.36862182617188,-42.25055694580078],[-73.67222595214844,-42.36194610595703],[-73.61805725097656,-42.51722717285156],[-73.82028198242188,-42.50750732421875],[-73.80029296875,-42.61778259277344],[-73.4989013671875,-42.80083465576172],[-73.65390014648438,-42.93333435058594],[-73.48945617675781,-43.114723205566406],[-73.85917663574219,-43.400001525878906],[-74.40779113769531,-43.243614196777344],[-73.88528442382812,-41.81555938720703]]],[[[-73.01583862304688,-41.86444854736328],[-73.08973693847656,-41.84416961669922],[-73.0775146484375,-41.74000358581543],[-73.01583862304688,-41.86444854736328]]],[[[-80.73779296875,-33.779449462890625],[-80.77473258972168,-33.74195098876953],[-80.73529052734375,-33.689443588256836],[-80.73779296875,-33.779449462890625]]],[[[-78.77250671386719,-33.62361145019531],[-78.99166870117188,-33.668060302734375],[-78.88833618164062,-33.58055877685547],[-78.77250671386719,-33.62361145019531]]],[[[-109.24138641357422,-27.133056640625],[-109.44917297363281,-27.193058013916016],[-109.39083862304688,-27.066669464111328],[-109.24138641357422,-27.133056640625]]],[[[-105.45639038085938,-26.460556030273438],[-105.45945739746094,-26.464723587036133],[-105.47416687011719,-26.45305633544922],[-105.45639038085938,-26.460556030273438]]],[[[-79.88250732421875,-26.346946716308594],[-79.90695190429688,-26.346389770507812],[-79.86944580078125,-26.340835571289062],[-79.88250732421875,-26.346946716308594]]],[[[-80.07695007324219,-26.261669158935547],[-80.0997314453125,-26.261390686035156],[-80.08056640625,-26.251392364501953],[-80.07695007324219,-26.261669158935547]]],[[[-69.48361206054688,-17.63555908203125],[-69.07167053222656,-18.038890838623047],[-68.90779113769531,-19.055278778076172],[-68.4375,-19.430278778076172],[-68.7569580078125,-20.40694808959961],[-68.18861389160156,-21.296945571899414],[-67.87640380859375,-22.82805633544922],[-67.18362426757812,-22.821666717529297],[-67.00083923339844,-23.00278091430664],[-67.33584594726562,-24.021665573120117],[-68.56500244140625,-24.774444580078125],[-68.35195922851562,-25.117225646972656],[-68.5836181640625,-26.505279541015625],[-68.2872314453125,-26.915279388427734],[-68.81083679199219,-27.120555877685547],[-69.65538024902344,-28.40093231201172],[-70.03140258789062,-29.306392669677734],[-69.83168029785156,-30.190555572509766],[-70.53306579589844,-31.18805694580078],[-70.09889221191406,-33.17250061035156],[-69.77444458007812,-33.38111114501953],[-69.8125,-34.235557556152344],[-70.5675048828125,-35.247779846191406],[-70.42431640625,-36.13603973388672],[-71.18528747558594,-36.84222412109375],[-70.82417297363281,-38.56806182861328],[-71.40139770507812,-38.92028045654297],[-71.695556640625,-39.584449768066406],[-71.9505615234375,-40.73278045654297],[-71.72611999511719,-42.09667205810547],[-72.1319580078125,-42.28889465332031],[-72.13694763183594,-43.00917053222656],[-71.7327880859375,-43.18805694580078],[-71.85501098632812,-44.371673583984375],[-71.10806274414062,-44.53972625732422],[-71.2822265625,-44.80028533935547],[-72.07861328125,-44.769447326660156],[-71.29779052734375,-45.2933349609375],[-71.78056335449219,-45.648895263671875],[-71.66944885253906,-46.679168701171875],[-71.94029235839844,-46.81555938720703],[-71.86862182617188,-47.22167205810547],[-72.36029052734375,-47.470001220703125],[-72.53639221191406,-47.92139434814453],[-72.2872314453125,-48.341949462890625],[-72.56417846679688,-48.80445098876953],[-73.5836181640625,-49.538063049316406],[-73.16612243652344,-50.753334045410156],[-72.29417419433594,-50.64972686767578],[-72.40055847167969,-51.51361846923828],[-71.91056823730469,-51.99583435058594],[-69.99833679199219,-51.99639129638672],[-68.44175720214844,-52.377777099609375],[-69.26112365722656,-52.206390380859375],[-70.81167602539062,-52.732505798339844],[-70.97361755371094,-53.75556182861328],[-71.28472900390625,-53.886390686035156],[-72.45390319824219,-53.401390075683594],[-71.86445617675781,-53.22167205810547],[-72.00723266601562,-53.56305694580078],[-71.80307006835938,-53.516395568847656],[-71.17056274414062,-52.80805969238281],[-72.55278015136719,-53.07472229003906],[-72.18861389160156,-53.18389129638672],[-72.6541748046875,-53.323890686035156],[-72.40028381347656,-53.540283203125],[-73.21778869628906,-53.231117248535156],[-72.70611572265625,-53.293060302734375],[-72.79306030273438,-53.17833709716797],[-72.65306091308594,-53.146949768066406],[-72.93695068359375,-53.10667419433594],[-72.95834350585938,-52.857505798339844],[-72.71945190429688,-52.746116638183594],[-71.47528076171875,-52.633338928222656],[-72.79917907714844,-52.53972625732422],[-72.89889526367188,-52.62555694580078],[-72.67529296875,-52.65888977050781],[-73.00584411621094,-52.85417175292969],[-72.9808349609375,-53.06611633300781],[-73.45112609863281,-53.00666809082031],[-73.23500061035156,-52.88972473144531],[-73.56278991699219,-52.793617248535156],[-72.885009765625,-52.51555633544922],[-73.69000244140625,-52.725006103515625],[-73.54779052734375,-52.53889465332031],[-73.72334289550781,-52.02472686767578],[-73.3275146484375,-52.22361755371094],[-72.98861694335938,-52.06861114501953],[-72.86195373535156,-52.26416778564453],[-72.69833374023438,-51.98333740234375],[-72.570556640625,-52.315834045410156],[-72.89944458007812,-52.4586181640625],[-72.4908447265625,-52.31889343261719],[-72.46890258789062,-51.78916931152344],[-73.24362182617188,-51.46222686767578],[-72.56083679199219,-51.78166961669922],[-73.28140258789062,-51.61028289794922],[-72.92417907714844,-51.86333465576172],[-73.23695373535156,-52.090003967285156],[-73.38667297363281,-51.655555725097656],[-73.28361511230469,-52.155006408691406],[-73.5452880859375,-52.05639457702637],[-73.461669921875,-51.687225341796875],[-73.90583801269531,-51.62250518798828],[-73.89418029785156,-51.37000274658203],[-73.59806823730469,-51.61833953857422],[-73.711669921875,-51.15972900390625],[-74.25279235839844,-50.940834045410156],[-73.52862358093262,-50.714447021484375],[-73.56639099121094,-50.40167236328125],[-74.04833984375,-50.82750701904297],[-74.29306030273438,-50.48222351074219],[-73.88473510742188,-50.53889465332031],[-74.69361877441406,-50.203338623046875],[-73.8658447265625,-50.29389190673828],[-74.37251281738281,-49.99139404296875],[-73.885009765625,-50.06945037841797],[-74.32528686523438,-49.627227783203125],[-73.71250915527344,-49.757225036621094],[-74.11167907714844,-49.48027801513672],[-73.83416557312012,-49.02916717529297],[-74.3739013671875,-49.42750358581543],[-74.44972229003906,-48.812225341796875],[-74.06083679199219,-48.74139404296875],[-74.40028381347656,-48.61444854736328],[-74.04667663574219,-48.54778289794922],[-74.0211181640625,-48.413612365722656],[-74.65444946289062,-48.023895263671875],[-73.5533447265625,-48.24583435058594],[-73.274169921875,-48.08722686767578],[-73.6541748046875,-47.90361785888672],[-73.22084045410156,-48.00111389160156],[-73.71917724609375,-47.52833557128906],[-73.9344482421875,-47.846946716308594],[-74.74166870117188,-47.71583557128906],[-74.04112243652344,-47.61805725097656],[-74.5291748046875,-47.437782287597656],[-73.9344482421875,-47.03611755371094],[-74.2650146484375,-46.785560607910156],[-75.01390075683594,-46.750282287597656],[-74.94223022460938,-46.44000244140625],[-75.65472412109375,-46.76500701904297],[-75.41307067871094,-46.93389129638672],[-75.71751403808594,-46.72528076171875],[-74.36111450195312,-45.791114807128906],[-74.14083862304688,-45.80583953857422],[-73.97445678710938,-46.0947265625],[-74.0836181640625,-46.18611145019531],[-74.31167602539062,-46.249168395996094],[-74.49444580078125,-46.190284729003906],[-74.34083557128906,-46.266395568847656],[-74.04972839355469,-46.195556640625],[-73.85389709472656,-46.34722900390625],[-73.88278198242188,-46.14111328125],[-73.76806640625,-46.30278015136719],[-73.99501037597656,-46.56139373779297],[-73.84112358093262,-46.588890075683594],[-73.42556762695312,-46.07444763183594],[-73.69084167480469,-46.31916809082031],[-73.66334533691406,-45.97333526611328],[-73.18223571777344,-45.667503356933594],[-73.58723258972168,-45.77972412109375],[-73.51556396484375,-45.45500183105469],[-72.82722473144531,-45.42250061035156],[-73.44694519042969,-45.2852783203125],[-73.39167785644531,-44.980560302734375],[-73.14250183105469,-44.94445037841797],[-72.76611328125,-44.753334045410156],[-72.6138916015625,-44.4727783203125],[-73.28945922851562,-44.14361572265625],[-72.84584045410156,-43.77667236328125],[-73.11639404296875,-43.439727783203125],[-72.74528503417969,-43.04833984375],[-72.86083984375,-42.57444763183594],[-72.53500366210938,-42.559173583984375],[-72.84750366210938,-42.280006408691406],[-72.42140197753906,-42.45305633544922],[-72.46278381347656,-41.97111511230469],[-72.85945129394531,-41.906951904296875],[-72.35057067871094,-41.652503967285156],[-72.31001281738281,-41.43583679199219],[-72.57139587402344,-41.70777893066406],[-72.94667053222656,-41.48333740234375],[-73.20361328125,-41.792503356933594],[-73.75028991699219,-41.754722595214844],[-73.49195861816406,-41.520835876464844],[-73.86889457702637,-41.482505798339844],[-73.99501037597656,-40.970001220703125],[-73.22250366210938,-39.41472625732422],[-73.64334106445312,-37.2086181640625],[-73.19000244140625,-37.1380615234375],[-71.4425048828125,-32.64000701904297],[-71.70333862304688,-30.761669158935547],[-71.28779602050781,-29.89694595336914],[-71.52166557312012,-28.970001220703125],[-70.91084289550781,-27.6219482421875],[-70.44917297363281,-25.364723205566406],[-70.39111328125,-23.561946868896484],[-70.62251281738281,-23.492778778076172],[-70.0533447265625,-21.42565155029297],[-70.40548706054688,-18.34854507446289],[-69.95112609863281,-18.242778778076172],[-69.49972534179688,-17.505279541015625],[-69.48361206054688,-17.63555908203125]],[[-74.0694580078125,-46.00611114501953],[-74.16445922851562,-46.13667297363281],[-74.07223510742188,-46.0977783203125],[-74.0694580078125,-46.00611114501953]],[[-73.38528442382812,-52.74000358581543],[-73.32806396484375,-52.69944763183594],[-73.39805603027344,-52.732505798339844],[-73.38528442382812,-52.74000358581543]]]]}},{"type":"Feature","properties":{"name":"Cayman Islands","iso2":"KY","iso3":"CYM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-81.09722899999988,19.308887000000155],[-81.401123,19.28833],[-81.254456,19.353886],[-81.09722899999988,19.308887000000155]]],[[[-80.097504,19.654163],[-80.0758359999999,19.697498],[-79.966675,19.707222],[-80.097504,19.654163]]],[[[-79.866394,19.686943],[-79.893341,19.693333],[-79.732788,19.748608],[-79.866394,19.686943]]]]}},{"type":"Feature","properties":{"name":"Cameroon","iso2":"CM","iso3":"CMR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[9.687222,3.574722],[9.62611,3.551111000000105],[9.6425,3.578611000000123],[9.687222,3.574722]]],[[[14.577221,12.73860900000011],[15.042597,12.078888],[15.061666,10.789999000000108],[15.68185,9.989649],[14.194769000000122,9.98175],[13.957499000000155,9.638611],[15.201944,8.485832],[15.499008,7.526609],[14.41916700000013,6.035277],[14.732777,4.623055],[16.103054,2.898333],[16.207222,2.220833],[16.07222000000013,1.654166],[14.564999,2.169444],[13.293888,2.163611],[12.523611000000102,2.283333],[11.339764,2.168611],[10.02611,2.168056],[9.811764000000153,2.343698],[9.7225,3.865278],[8.975832000000139,4.09666600000017],[8.845833,4.638055000000151],[8.504166000000168,4.527778],[8.591738000000134,4.810932000000122],[8.865276,5.841944],[9.795555,6.801666],[10.615000000000123,7.06861],[11.340277,6.440833],[11.864166,7.084722],[12.253887000000134,8.408054],[12.79694400000011,8.769722],[13.80722,11.055832],[14.646387,11.575832],[14.645277,12.188332000000145],[14.174444,12.396666],[14.07472,13.0816650000001],[14.500875,13.001314],[14.577221,12.73860900000011]]]]}},{"type":"Feature","properties":{"name":"Chad","iso2":"TD","iso3":"TCD"},"geometry":{"type":"MultiPolygon","coordinates":[[[[14.500875,13.001314],[14.07472,13.0816650000001],[13.62512,13.718338],[13.468887,14.461111],[15.489166,16.914165],[15.996666,20.353054],[15.202499,21.495831],[14.997889,23.000591],[16.000832,23.450554],[24.002747,19.499065],[23.999603,15.698709],[22.937222000000105,15.561943],[22.935833,15.11611],[22.384163,14.55416500000014],[22.55499600000013,14.125555000000148],[22.084442,13.779165],[22.294167,13.35861],[21.827774,12.797499000000144],[22.46694200000013,12.621666],[22.866505,10.922447],[21.719444,10.639444],[21.715553,10.290554],[20.371666,9.108332],[18.988888,8.964167],[19.058792,8.578382],[18.588886,8.040277],[15.499008,7.526609],[15.201944,8.485832],[13.957499000000155,9.638611],[14.194769000000122,9.98175],[15.68185,9.989649],[15.061666,10.789999000000108],[15.042597,12.078888],[14.577221,12.73860900000011],[14.500875,13.001314]]]]}},{"type":"Feature","properties":{"name":"Comoros","iso2":"KM","iso3":"COM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[43.86055000000013,-12.356112],[43.66861,-12.3575],[43.622772,-12.258335],[43.86055000000013,-12.356112]]],[[[44.487495,-12.093056],[44.513611,-12.38028],[44.206665,-12.161945],[44.487495,-12.093056]]],[[[43.459717000000154,-11.935556],[43.219162000000125,-11.761112],[43.281387,-11.379723],[43.459717000000154,-11.935556]]]]}},{"type":"Feature","properties":{"name":"Colombia","iso2":"CO","iso3":"COL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-78.12139892578125,2.500833511352539],[-78.21556091308594,2.577779769897461],[-78.18917846679688,2.640554428100586],[-78.12779235839844,2.643056869506836],[-78.0916748046875,2.539445877075195],[-78.12139892578125,2.500833511352539]]],[[[-77.98638916015625,2.542501449584961],[-78.04556274414062,2.58305549621582],[-77.97750854492188,2.651945114135742],[-77.94833374023438,2.627779006958008],[-77.96028137207031,2.557222366333008],[-77.98638916015625,2.542501449584961]]],[[[-77.85751342773438,2.573335647583008],[-77.92111206054688,2.693891525268555],[-77.78695678710938,2.592779159545898],[-77.85751342773438,2.573335647583008]]],[[[-77.76972961425781,2.591390609741211],[-77.83973693847656,2.640279769897461],[-77.88473510742188,2.717222213745117],[-77.82778930664062,2.703889846801758],[-77.74972534179688,2.614999771118164],[-77.76972961425781,2.591390609741211]]],[[[-77.56889343261719,3.06916618347168],[-77.66278076171875,3.075834274291992],[-77.53056335449219,3.209444046020508],[-77.56889343261719,3.06916618347168]]],[[[-77.44833374023438,4.074167251586914],[-77.53556823730469,4.16722297668457],[-77.49417114257812,4.204168319702148],[-77.44833374023438,4.074167251586914]]],[[[-77.54306030273438,4.193334579467773],[-77.42611694335938,4.334722518920898],[-77.31973266601562,4.251665115356445],[-77.54306030273438,4.193334579467773]]],[[[-71.56361389160156,12.453611373901367],[-71.1158447265625,12.101110458374023],[-71.32472229003906,11.853055953979492],[-71.97723388671875,11.664999008178711],[-72.2093505859375,11.250001907348633],[-72.49305725097656,11.121110916137695],[-73.37806701660156,9.171388626098633],[-72.77972412109375,9.080278396606445],[-72.32528686523438,8.095556259155273],[-72.4716796875,7.491945266723633],[-72,7.018888473510742],[-70.11917114257812,6.975835800170898],[-69.24528503417969,6.081388473510742],[-67.45445251464844,6.193056106567383],[-67.85972595214844,4.558610916137695],[-67.29055786132812,3.397500991821289],[-67.82833862304688,2.825002670288086],[-67.1925048828125,2.392499923706055],[-66.87188720703125,1.221643447875977],[-67.07667541503906,1.173334121704102],[-67.42417907714844,2.143888473510742],[-67.91473388671875,1.745279312133789],[-68.19639587402344,1.977502822875977],[-68.15306091308594,1.72416877746582],[-69.84609985351562,1.710454940795898],[-69.84222412109375,1.072221755981445],[-69.27000427246094,1.038335800170898],[-69.12472534179688,0.645002365112305],[-70.04417419433594,0.59083366394043],[-70.05805969238281,-0.157499313354492],[-69.60751342773438,-0.517499923706055],[-69.37806701660156,-1.338054656982422],[-69.95692443847656,-4.236873626708984],[-70.72416687011719,-3.779722213745117],[-70.0675048828125,-2.755556106567383],[-70.28834533691406,-2.504999160766602],[-71.69805908203125,-2.146944046020508],[-72.8819580078125,-2.506387710571289],[-73.55639457702637,-1.370832443237305],[-74.22723388671875,-1.027776718139648],[-74.77694702148438,-0.204166412353516],[-75.28584289550781,-0.119722366333008],[-76.24305725097656,0.39555549621582],[-77.37945556640625,0.384721755981445],[-78.5916748046875,1.24305534362793],[-78.80972290039062,1.437780380249023],[-79.0533447265625,1.628332138061523],[-78.58416557312012,1.768888473510742],[-78.56529235839844,2.429166793823242],[-78.44056701660156,2.509443283081055],[-78.34361267089844,2.436666488647461],[-78.2650146484375,2.519166946411133],[-78.12556457519531,2.486944198608398],[-77.98695373535156,2.522500991821289],[-77.94862365722656,2.559446334838867],[-77.94000244140625,2.655000686645508],[-77.86723327636719,2.560277938842773],[-77.79251098632812,2.567499160766602],[-77.7408447265625,2.60472297668457],[-77.02862358093262,3.917779922485352],[-77.43417358398438,4.02833366394043],[-77.23918151855469,4.260000228881836],[-77.38417053222656,4.341943740844727],[-77.3477783203125,5.240556716918945],[-77.5322265625,5.518888473510742],[-77.2408447265625,5.75139045715332],[-77.49028015136719,6.190832138061523],[-77.34001159667969,6.567777633666992],[-77.88972473144531,7.228891372680664],[-77.74667358398438,7.722223281860352],[-77.57389831542969,7.525278091430664],[-77.21556091308594,7.937223434448242],[-77.36666870117188,8.67500114440918],[-76.75527954101562,7.918889999389648],[-76.9283447265625,8.568334579467773],[-75.62945556640625,9.453611373901367],[-75.26972961425781,10.798334121704102],[-74.86080932617188,11.125486373901367],[-74.28861999511719,11.002500534057617],[-74.59222412109375,10.878053665161133],[-74.39056396484375,10.74305534362793],[-74.15501403808594,11.331388473510742],[-73.28445434570312,11.295557022094727],[-71.56361389160156,12.453611373901367]],[[-78.5452880859375,2.416112899780273],[-78.54417419433594,2.432500839233398],[-78.55029296875,2.433332443237305],[-78.55361938476562,2.406667709350586],[-78.5452880859375,2.416112899780273]]],[[[-81.71028137207031,12.490835189819336],[-81.7197265625,12.55000114440918],[-81.68833923339844,12.59111213684082],[-81.71028137207031,12.490835189819336]]],[[[-81.36557006835938,13.323057174682617],[-81.38945007324219,13.335000991821289],[-81.35389709472656,13.378610610961914],[-81.36557006835938,13.323057174682617]]]]}},{"type":"Feature","properties":{"name":"Costa Rica","iso2":"CR","iso3":"CRI"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-85.115845,10.07361],[-85.17611699999989,10.077499],[-85.198059,10.110554],[-85.161957,10.122499],[-85.109177,10.105833],[-85.115845,10.07361]]],[[[-85.087784,11.009998],[-83.915558,10.708611],[-83.645798,10.924847],[-82.563568,9.562876000000145],[-82.934723,9.471666],[-82.71084599999989,8.93111],[-82.898849,8.025669],[-83.341675,8.726944000000117],[-83.291122,8.370277],[-83.730835,8.583055],[-83.624176,9.035276000000124],[-84.61527999999987,9.575832000000105],[-84.74028,9.966665],[-85.243057,10.204166],[-85.228622,10.088888],[-84.897232,9.807499],[-85.142227,9.589443],[-85.664459,9.908609000000126],[-85.861679,10.368332000000123],[-85.631958,10.626389],[-85.91139199999986,10.891109],[-85.692383,11.076061],[-85.087784,11.009998]]]]}},{"type":"Feature","properties":{"name":"Central African Republic","iso2":"CF","iso3":"CAF"},"geometry":{"type":"MultiPolygon","coordinates":[[[[19.058792,8.578382],[18.988888,8.964167],[20.371666,9.108332],[21.715553,10.290554],[21.719444,10.639444],[22.866505,10.922447],[23.669167,9.866943],[23.517776,8.714167],[24.201111,8.686943],[24.192497000000117,8.30361],[25.25333,7.850555],[25.206944000000135,7.497499],[26.404999,6.646388],[26.437496000000124,6.077777],[27.142776,5.771944],[27.455276,5.016388],[25.891666,5.192499],[25.542221,5.381389],[24.734444,4.910832000000141],[24.394165,5.115555],[23.420277,4.59111],[22.895832,4.821111],[22.37916600000014,4.1275],[20.585552,4.410000000000139],[19.421387,5.134166],[18.541943,4.335555],[18.624958,3.479444],[17.475277,3.713055],[16.659721,3.533333],[16.207222,2.220833],[16.103054,2.898333],[14.732777,4.623055],[14.41916700000013,6.035277],[15.499008,7.526609],[18.588886,8.040277],[19.058792,8.578382]]]]}},{"type":"Feature","properties":{"name":"Cuba","iso2":"CU","iso3":"CUB"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-78.32778930664062,20.513612747192383],[-78.45834350585938,20.605554580688477],[-78.34584045410156,20.56944465637207],[-78.32778930664062,20.513612747192383]]],[[[-78.3819580078125,20.63777732849121],[-78.4122314453125,20.6472225189209],[-78.40278625488281,20.675832748413086],[-78.3819580078125,20.63777732849121]]],[[[-78.44168090820312,20.710554122924805],[-78.54750061035156,20.703611373901367],[-78.4586181640625,20.73166847229004],[-78.44168090820312,20.710554122924805]]],[[[-78.76750183105469,20.70611000061035],[-78.82194519042969,20.75694465637207],[-78.76362609863281,20.730554580688477],[-78.76750183105469,20.70611000061035]]],[[[-75.48722839355469,20.7288875579834],[-75.57806396484375,20.781110763549805],[-75.5150146484375,20.79194450378418],[-75.48722839355469,20.7288875579834]]],[[[-78.84750366210938,20.771665573120117],[-78.96583557128906,20.809999465942383],[-78.93167114257812,20.834165573120117],[-78.84750366210938,20.771665573120117]]],[[[-78.977783203125,20.839445114135742],[-79.0775146484375,20.893888473510742],[-78.9697265625,20.87416648864746],[-78.977783203125,20.839445114135742]]],[[[-79.08445739746094,20.898332595825195],[-79.22557067871094,21.00055503845215],[-79.17668151855469,21.00861167907715],[-79.08445739746094,20.898332595825195]]],[[[-79.30223083496094,21.064443588256836],[-79.38417053222656,21.119722366333008],[-79.34140014648438,21.121110916137695],[-79.30223083496094,21.064443588256836]]],[[[-79.40640258789062,21.10472297668457],[-79.45112609863281,21.122777938842773],[-79.40251159667969,21.121110916137695],[-79.40640258789062,21.10472297668457]]],[[[-81.53083801269531,21.600278854370117],[-81.55694580078125,21.622777938842773],[-81.36695861816406,21.711942672729492],[-81.53083801269531,21.600278854370117]]],[[[-82.5452880859375,21.57111167907715],[-82.89723205566406,21.43277931213379],[-83.19306945800781,21.621389389038086],[-82.93722534179688,21.579999923706055],[-83.08944702148438,21.785554885864258],[-82.97445678710938,21.942777633666992],[-82.5452880859375,21.57111167907715]]],[[[-77.91505432128906,22.094697952270508],[-77.65333557128906,22.06972312927246],[-77.63833618164062,21.953054428100586],[-77.91505432128906,22.094697952270508]]],[[[-77.84638977050781,22.10638999938965],[-78.04417419433594,22.18666648864746],[-77.99751281738281,22.285276412963867],[-77.84638977050781,22.10638999938965]]],[[[-77.77723693847656,22.19500160217285],[-77.77166557312012,22.168054580688477],[-77.85000610351562,22.294721603393555],[-77.77723693847656,22.19500160217285]]],[[[-78.11862182617188,22.413888931274414],[-78.01945495605469,22.261945724487305],[-78.3114013671875,22.40389060974121],[-78.11862182617188,22.413888931274414]]],[[[-78.34140014648438,22.53388786315918],[-78.42529296875,22.412500381469727],[-78.69667053222656,22.51472282409668],[-78.34140014648438,22.53388786315918]]],[[[-78.97639465332031,22.63749885559082],[-79.05445861816406,22.6652774810791],[-78.96890258789062,22.66916847229004],[-78.97639465332031,22.63749885559082]]],[[[-79.32305908203125,22.614721298217773],[-79.63250732421875,22.80000114440918],[-79.57612609863281,22.809999465942383],[-79.32305908203125,22.614721298217773]]],[[[-79.89195251464844,22.928335189819336],[-79.9586181640625,22.947500228881836],[-79.883056640625,22.96527671813965],[-79.89195251464844,22.928335189819336]]],[[[-80.2327880859375,22.9950008392334],[-80.23417663574219,22.956388473510742],[-80.34945678710938,22.98166847229004],[-80.2327880859375,22.9950008392334]]],[[[-80.04945373535156,23.02610969543457],[-80.07722473144531,23.04194450378418],[-80.07667541503906,23.074445724487305],[-80.04945373535156,23.02610969543457]]],[[[-80.14639282226562,23.070276260375977],[-80.22416687011719,23.099443435668945],[-80.19944763183594,23.121946334838867],[-80.14639282226562,23.070276260375977]]],[[[-80.92750358581543,23.12555503845215],[-80.79722595214844,23.150556564331055],[-80.97361755371094,23.107500076293945],[-80.92750358581543,23.12555503845215]]],[[[-82.00389099121094,23.18638801574707],[-81.58056640625,23.155553817749023],[-81.50083923339844,23.05555534362793],[-81.22695922851562,23.161664962768555],[-81.28556823730469,23.119722366333008],[-81.13473510742188,23.023054122924805],[-80.633056640625,23.09833335876465],[-80.54444885253906,22.99110984802246],[-80.27862358093262,22.9052791595459],[-80.03334045410156,22.951112747192383],[-77.34112358093262,21.636110305786133],[-77.54306030273438,21.918611526489258],[-76.8961181640625,21.3063907623291],[-75.70722961425781,21.121946334838867],[-75.73667907714844,20.696943283081055],[-74.14140319824219,20.252222061157227],[-75.08528137207031,19.893041610717773],[-75.13973999023438,19.962873458862305],[-75.1591796875,19.960695266723633],[-75.22372436523438,19.90155601501465],[-77.72250366210938,19.83277702331543],[-77.1158447265625,20.364999771118164],[-77.23638916015625,20.663057327270508],[-78.05029296875,20.69972038269043],[-78.75028991699219,21.6391658782959],[-79.98779296875,21.72361183166504],[-80.49195861816406,22.177221298217773],[-81.82305908203125,22.183610916137695],[-82.16307067871094,22.398332595825195],[-81.64889526367188,22.49138832092285],[-81.885009765625,22.68083381652832],[-82.76390075683594,22.7005558013916],[-84.026123046875,21.91499900817871],[-84.95333862304688,21.85999870300293],[-84.33805847167969,22.01222038269043],[-84.07695007324219,22.660554885864258],[-82.00389099121094,23.18638801574707]]],[[[-80.49305725097656,23.18805503845215],[-80.57972717285156,23.176111221313477],[-80.55862426757812,23.203611373901367],[-80.49305725097656,23.18805503845215]]]]}},{"type":"Feature","properties":{"name":"Cape Verde","iso2":"CV","iso3":"CPV"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-24.368336,14.812222],[-24.52528,14.92111],[-24.381668,15.047499],[-24.368336,14.812222]]],[[[-23.446667,14.982777000000112],[-23.681393,14.935555],[-23.76667,15.253054],[-23.446667,14.982777000000112]]],[[[-22.706112,16.036388],[-22.957779,16.089443],[-22.79861499999987,16.23527500000013],[-22.706112,16.036388]]],[[[-24.034168,16.594166],[-24.32139199999989,16.482777],[-24.432224,16.644165],[-24.034168,16.594166]]],[[[-24.926113,16.799999000000142],[-25.093334,16.83083],[-24.933056,16.921387],[-24.926113,16.799999000000142]]],[[[-25.28139099999987,16.91333],[-25.33028,17.096386],[-24.97444499999989,17.112778],[-25.28139099999987,16.91333]]]]}},{"type":"Feature","properties":{"name":"Cook Islands","iso2":"CK","iso3":"COK"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-157.890564,-21.938053],[-157.962799,-21.904167],[-157.921967,-21.880283],[-157.890564,-21.938053]]],[[[-159.741119,-21.254169],[-159.833893,-21.195831],[-159.752502,-21.193054],[-159.741119,-21.254169]]],[[[-157.316437,-20.188053],[-157.332214,-20.13306],[-157.309174,-20.147781],[-157.316437,-20.188053]]],[[[-158.098358,-20.016113],[-158.118591,-19.973057],[-158.08197,-19.986942],[-158.098358,-20.016113]]],[[[-158.27948,-19.817783],[-158.262512,-19.836666],[-158.291382,-19.833332],[-158.27948,-19.817783]]],[[[-157.708649,-19.853054],[-157.741364,-19.814167],[-157.713928,-19.770283],[-157.708649,-19.853054]]],[[[-158.92865,-19.270283],[-158.943909,-19.27195],[-158.951935,-19.242496],[-158.92865,-19.270283]]],[[[-159.78833,-18.890556],[-159.803345,-18.861389],[-159.78421,-18.841393],[-159.78833,-18.890556]]],[[[-163.16333,-18.089443],[-163.170319,-18.079449],[-163.154724,-18.056667],[-163.16333,-18.089443]]],[[[-165.422241,-11.548334],[-165.435028,-11.5375],[-165.414185,-11.537781],[-165.422241,-11.548334]]],[[[-165.82666,-10.888334],[-165.850281,-10.884169],[-165.831146,-10.876945],[-165.82666,-10.888334]]],[[[-161.022827,-10.431391],[-161.043335,-10.419724],[-161.048615,-10.392778],[-161.022827,-10.431391]]],[[[-160.975586,-10.395555],[-161.012512,-10.352777],[-160.973602,-10.378057],[-160.975586,-10.395555]]],[[[-161.084442,-10.041945],[-161.090576,-10.018333],[-161.072266,-10.008059],[-161.084442,-10.041945]]],[[[-157.941681,-8.982502],[-157.97226,-8.981943],[-158.008362,-8.951389],[-157.941681,-8.982502]]]]}},{"type":"Feature","properties":{"name":"Cyprus","iso2":"CY","iso3":"CYP"},"geometry":{"type":"MultiPolygon","coordinates":[[[[33.652618,35.354103],[34.590271,35.690277],[33.921387,35.272774],[34.083328,34.959442],[33.030838,34.56255],[32.274162,35.043884],[33.652618,35.354103]]]]}},{"type":"Feature","properties":{"name":"Denmark","iso2":"DK","iso3":"DNK"},"geometry":{"type":"MultiPolygon","coordinates":[[[[11.513887,54.829720000000165],[11.85611,54.683327000000176],[10.98989100000017,54.790848],[11.513887,54.829720000000165]]],[[[12.038055,54.892494],[11.964443,54.561661],[11.708611,54.936661000000115],[12.038055,54.892494]]],[[[10.432777000000101,54.84166],[10.248333000000173,54.90416],[10.184166,54.97361],[10.432777000000101,54.84166]]],[[[12.557499,54.96416500000011],[12.11583300000018,54.90416],[12.311943,55.03527100000015],[12.557499,54.96416500000011]]],[[[10.615000000000123,54.950272],[10.49861,55.006386],[10.631943,55.043327],[10.615000000000123,54.950272]]],[[[9.79250000000016,55.074997000000124],[10.071110000000147,54.87471000000012],[9.630554000000103,55.04943800000011],[9.79250000000016,55.074997000000124]]],[[[10.756943000000149,54.777222],[10.681944,54.908607],[10.949165,55.16111],[10.756943000000149,54.777222]]],[[[15.051666,54.994995000000145],[14.679722,55.099716],[14.746387,55.295555000000135],[15.051666,54.994995000000145]]],[[[8.46361,55.33416],[8.360277,55.457771],[8.458332,55.426384],[8.46361,55.33416]]],[[[10.745277000000101,55.482216],[10.782776,55.122498],[10.497776,55.028885],[10.152777,55.084442],[10.11861,55.178886],[10.005833,55.193329],[9.896944,55.279716],[9.810833,55.436661],[9.675554,55.499161000000115],[9.74861,55.540276000000105],[9.813055,55.547493],[9.904999,55.505829000000105],[10.309721000000138,55.616943],[10.478611,55.438049000000106],[10.619165000000123,55.619164],[10.745277000000101,55.482216]]],[[[12.579443,55.551384],[12.606110000000115,55.696106],[12.67861,55.590553],[12.579443,55.551384]]],[[[10.630554,55.865555],[10.527498,55.765831],[10.523611,55.981384],[10.630554,55.865555]]],[[[12.567221,55.992218],[12.190832,55.478607],[12.461666,55.286385],[12.071943,54.968605000000125],[11.246666,55.199715],[10.873610000000156,55.732498],[11.763887,55.964722],[12.057220000000143,55.653328000000116],[11.859444,55.96666000000012],[12.567221,55.992218]]],[[[11.565832,56.67083000000012],[11.503332000000114,56.707771],[11.648054000000116,56.72332800000011],[11.565832,56.67083000000012]]],[[[8.924721,56.91861],[8.766943,56.692215000000104],[8.509722,56.74166100000015],[8.924721,56.91861]]],[[[9.974274,57.071732000000125],[10.311891,56.981304],[10.305277,56.748055],[9.866388000000171,56.650276],[10.963055,56.439438],[10.24679,56.17855100000013],[9.992777,55.704994],[9.549999,55.7058260000001],[9.81916600000011,55.604721],[9.704166,55.53110500000015],[9.588333,55.421661],[9.68861,55.196938],[9.459166,55.123886],[9.768055,54.89110600000011],[9.445358,54.825401],[8.664545,54.913094],[8.623888,55.427498],[8.087221,55.548882],[8.127222,55.98555],[8.397221,55.897499],[8.108332,56.017776000000126],[8.165277,56.653328],[8.728333,56.482216],[9.075567,56.807449],[9.321665,56.525551000000135],[9.178200000000118,56.916031],[9.309444000000155,57.001938],[9.974274,57.071732000000125]]],[[[11.195833,57.31082900000017],[10.997499000000118,57.223328],[10.854443000000117,57.263054],[11.195833,57.31082900000017]]],[[[10.43249900000012,57.592216],[10.336616,56.991665],[10.006666,57.0899890000001],[9.24388900000011,56.995552],[9.115549,57.05277300000013],[8.670832000000132,56.945274],[8.415797,56.67812700000012],[8.591389,56.686104],[8.554998,56.582497],[8.240276,56.70722200000013],[8.617222,57.121666],[10.645953000000134,57.736267],[10.43249900000012,57.592216]]]]}},{"type":"Feature","properties":{"name":"Djibouti","iso2":"DJ","iso3":"DJI"},"geometry":{"type":"MultiPolygon","coordinates":[[[[42.866806,11.585428],[43.249222,11.469534],[42.944092,11.002438],[41.789719,11.008055],[41.828606,11.74],[42.399719,12.469721],[43.12138400000018,12.708332],[43.413887,12.056944],[42.508606,11.567221],[42.866806,11.585428]]]]}},{"type":"Feature","properties":{"name":"Dominica","iso2":"DM","iso3":"DMA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-61.363617,15.198055],[-61.452225,15.631943],[-61.253334,15.461388],[-61.363617,15.198055]]]]}},{"type":"Feature","properties":{"name":"Dominican Republic","iso2":"DO","iso3":"DOM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-71.532227,17.540276],[-71.522232,17.615276],[-71.46305799999988,17.581944],[-71.532227,17.540276]]],[[[-68.574448,18.129444],[-68.731949,18.119999],[-68.78389,18.195],[-68.574448,18.129444]]],[[[-70.783615,19.846664],[-69.936401,19.67110800000013],[-69.75361599999985,19.289444000000103],[-69.22167999999988,19.362221],[-69.631668,19.101665],[-68.729172,18.952774],[-68.32556199999988,18.616665],[-68.4497219999999,18.35583100000015],[-69.881668,18.469444],[-70.510834,18.194721],[-70.690002,18.433887],[-71.079727,18.301109],[-71.4225009999999,17.601944],[-71.767868,18.038502],[-72.003067,18.60083],[-71.715836,18.749722],[-71.754181,19.70583000000012],[-70.783615,19.846664]]]]}},{"type":"Feature","properties":{"name":"Ecuador","iso2":"EC","iso3":"ECU"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-80.19334411621094,-3.034721374511719],[-80.20668029785156,-2.724166870117188],[-79.90306091308594,-2.719720840454102],[-80.19334411621094,-3.034721374511719]]],[[[-79.838623046875,-2.641944885253906],[-79.88694763183594,-2.626943588256836],[-79.85667419433594,-2.466667175292969],[-79.838623046875,-2.641944885253906]]],[[[-89.62112426757812,-1.406665802001953],[-89.751953125,-1.360832214355469],[-89.64834594726562,-1.343889236450195],[-89.62112426757812,-1.406665802001953]]],[[[-90.4344482421875,-1.355278015136719],[-90.48167419433594,-1.219165802001953],[-90.3658447265625,-1.269166946411133],[-90.4344482421875,-1.355278015136719]]],[[[-90.0433349609375,-0.838888168334961],[-90.08222961425781,-0.801111221313477],[-90.03973388671875,-0.809444427490234],[-90.0433349609375,-0.838888168334961]]],[[[-89.44361877441406,-0.936666488647461],[-89.62945556640625,-0.927221298217773],[-89.25862121582031,-0.6875],[-89.44361877441406,-0.936666488647461]]],[[[-90.26055908203125,-0.751110076904297],[-90.5352783203125,-0.583889007568359],[-90.19056701660156,-0.542778015136719],[-90.26055908203125,-0.751110076904297]]],[[[-91.4989013671875,-0.496110916137695],[-91.66389465332031,-0.316110610961914],[-91.47111511230469,-0.248056411743164],[-91.4989013671875,-0.496110916137695]]],[[[-90.54750061035156,-0.305000305175781],[-90.87445068359375,-0.270000457763672],[-90.7933349609375,-0.149442672729492],[-90.54750061035156,-0.305000305175781]]],[[[-91.21890258789062,-0.011110305786133],[-90.81083679199219,-0.732500076293945],[-91.37611389160156,-1.026666641235352],[-91.08056640625,-0.587221145629883],[-91.6058349609375,-0.004999160766602],[-91.21890258789062,-0.011110305786133]]],[[[-90.45916557312012,0.266389846801758],[-90.53250122070312,0.34666633605957],[-90.40834045410156,0.326944351196289],[-90.45916557312012,0.266389846801758]]],[[[-90.75111389160156,0.547502517700195],[-90.79972839355469,0.563333511352539],[-90.792236328125,0.651666641235352],[-90.75111389160156,0.547502517700195]]],[[[-78.5916748046875,1.24305534362793],[-77.37945556640625,0.384721755981445],[-76.24305725097656,0.39555549621582],[-75.28584289550781,-0.119722366333008],[-75.62796020507812,-0.108858108520508],[-75.21607971191406,-0.965335845947266],[-75.55917358398438,-1.53416633605957],[-76.66062927246094,-2.572134017944336],[-78.33750915527344,-3.42277717590332],[-78.70903015136719,-4.584787368774414],[-79.05482482910156,-5.009132385253906],[-79.64973258972168,-4.432777404785156],[-80.46778869628906,-4.43889045715332],[-80.46722412109375,-3.986944198608398],[-80.15333557128906,-3.884227752685547],[-80.34042358398438,-3.380516052246094],[-79.94805908203125,-3.198333740234375],[-79.72750854492188,-2.602777481079102],[-79.84584045410156,-2.376388549804688],[-79.76362609863281,-2.009166717529297],[-80.25639343261719,-2.73638916015625],[-80.8900146484375,-2.320554733276367],[-80.91111755371094,-1.031110763549805],[-80.26472473144531,-0.627222061157227],[-80.501953125,-0.367500305175781],[-80.06834411621094,0.062780380249023],[-80.05972290039062,0.828611373901367],[-78.80972290039062,1.437780380249023],[-78.5916748046875,1.24305534362793]],[[-78.9122314453125,1.239168167114258],[-78.90333557128906,1.367780685424805],[-78.9989013671875,1.274999618530273],[-78.9122314453125,1.239168167114258]]]]}},{"type":"Feature","properties":{"name":"Egypt","iso2":"EG","iso3":"EGY"},"geometry":{"type":"MultiPolygon","coordinates":[[[[34.026384353637695,27.498334884643555],[34.041940689086914,27.44222068786621],[33.917497634887695,27.52638816833496],[34.026384353637695,27.498334884643555]]],[[[32.04722023010254,31.14333152770996],[32.04277229309082,31.158056259155273],[32.049997329711914,31.15333366394043],[32.04722023010254,31.14333152770996]]],[[[33.47666358947754,31.13749885559082],[33.26666450500488,31.21527671813965],[33.40055274963379,31.181665420532227],[33.47666358947754,31.13749885559082]]],[[[33.19527626037598,31.232778549194336],[33.26138496398926,31.214998245239258],[33.10166358947754,31.22722053527832],[32.97666358947754,31.168333053588867],[33.09610939025879,31.232500076293945],[33.19527626037598,31.232778549194336]]],[[[25.316667556762695,31.50111198425293],[27.33111000061035,31.374998092651367],[29.06944465637207,30.821664810180664],[31.02777671813965,31.600557327270508],[31.921480178833008,31.52988624572754],[32.20499610900879,31.28999900817871],[31.899999618530273,31.531110763549805],[31.773889541625977,31.271665573120117],[32.14306831359863,31.074167251586914],[32.21055030822754,31.288057327270508],[32.71721839904785,31.032499313354492],[33.11166572570801,31.193056106567383],[33.14972114562988,31.101667404174805],[33.14361000061035,31.058332443237305],[33.41055488586426,31.154722213745117],[33.53277778625488,31.116945266723633],[33.7438907623291,31.133333206176758],[34.21666145324707,31.323331832885742],[34.26758003234863,31.216543197631836],[34.9038028717041,29.48670768737793],[34.25444221496582,27.728612899780273],[33.24277687072754,28.554445266723633],[32.57499885559082,30.005277633666992],[32.340829849243164,29.59694480895996],[33.55888557434082,27.883054733276367],[35.13861274719238,24.517499923706055],[35.81305122375488,23.916112899780273],[35.48305702209473,23.93833351135254],[35.67055702209473,22.96583366394043],[36.88846778869629,22.000112533569336],[31.453889846801758,21.998334884643555],[31.455556869506836,22.232221603393555],[31.2711124420166,21.998334884643555],[25.00142478942871,21.999696731567383],[24.997777938842773,29.24888801574707],[24.706666946411133,30.168611526489258],[25.15166664123535,31.646944046020508],[25.316667556762695,31.50111198425293]],[[34.00139045715332,26.707223892211914],[33.99472236633301,26.749723434448242],[33.96000099182129,26.788331985473633],[34.00139045715332,26.707223892211914]]]]}},{"type":"Feature","properties":{"name":"Ireland","iso2":"IE","iso3":"IRL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-9.656389236450195,53.22222328186035],[-9.724723815917969,53.26805305480957],[-9.660833358764648,53.28000068664551],[-9.656389236450195,53.22222328186035]]],[[[-9.964168548583984,54.01861000061035],[-9.955001831054688,53.876665115356445],[-10.268611907958984,53.97500038146973],[-9.964168548583984,54.01861000061035]]],[[[-8.518611907958984,54.96416664123535],[-8.546945571899414,55.01194190979004],[-8.490556716918945,54.99472236633301],[-8.518611907958984,54.96416664123535]]],[[[-7.406389236450195,54.95333290100098],[-8.159444808959961,54.44194221496582],[-7.559444427490234,54.12693977355957],[-7.030834197998047,54.41777229309082],[-6.266975402832031,54.09983253479004],[-6.013055801391602,52.94500160217285],[-6.361110687255859,52.177499771118164],[-6.994722366333008,52.28277778625488],[-9.234167098999023,51.48055458068848],[-9.817501068115234,51.4455509185791],[-9.53555679321289,51.75000190734863],[-10.132501602172852,51.593332290649414],[-9.57750129699707,51.87221717834473],[-10.338592529296875,51.78292274475098],[-9.75777816772461,52.14860725402832],[-10.460834503173828,52.18222236633301],[-8.818334579467773,52.66555213928223],[-9.936389923095703,52.55583381652832],[-8.941112518310547,53.26416206359863],[-10.175834655761719,53.40777778625488],[-9.561389923095703,53.85972023010254],[-9.940555572509766,53.86694526672363],[-9.787778854370117,53.94194221496582],[-10.006111145019531,54.218889236450195],[-10.124444961547852,54.096384048461914],[-10.112222671508789,54.229997634887695],[-8.471668243408203,54.27388954162598],[-8.6683349609375,54.349443435668945],[-8.188333511352539,54.63360786437988],[-8.800834655761719,54.691667556762695],[-8.317501068115234,55.10888862609863],[-7.657499313354492,55.27443885803223],[-7.681388854980469,54.94832801818848],[-7.393888473510742,55.37944221496582],[-6.931667327880859,55.2358341217041],[-7.252506256103516,55.07059669494629],[-7.406389236450195,54.95333290100098]],[[-8.436944961547852,54.94444465637207],[-8.43861198425293,54.955278396606445],[-8.453889846801758,54.95499610900879],[-8.436944961547852,54.94444465637207]]]]}},{"type":"Feature","properties":{"name":"Equatorial Guinea","iso2":"GQ","iso3":"GNQ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[5.641388,-1.474722],[5.615277,-1.469167],[5.633888000000184,-1.420556],[5.641388,-1.474722]]],[[[10.02611,2.168056],[11.339764,2.168611],[11.353888,1.001944],[9.803976,1.002608],[9.356943,1.167222],[9.811764000000153,2.343698],[10.02611,2.168056]]],[[[8.856667,3.499444],[8.44611,3.27444400000013],[8.68611,3.741666000000109],[8.958887000000175,3.703888],[8.856667,3.499444]]]]}},{"type":"Feature","properties":{"name":"Estonia","iso2":"EE","iso3":"EST"},"geometry":{"type":"MultiPolygon","coordinates":[[[[23.990829,58.099998],[23.947773,58.147217],[24.022186,58.142746],[23.990829,58.099998]]],[[[22.990829,58.597771],[23.332775,58.441658],[21.994160000000193,57.922768],[22.201385,58.144714],[21.83194,58.5049970000001],[22.990829,58.597771]]],[[[23.364998,58.529991],[23.05777400000011,58.60833000000015],[23.247459,58.671051],[23.364998,58.529991]]],[[[23.27722200000011,58.963051],[23.110828,59.024712],[23.391663,58.998047],[23.27722200000011,58.963051]]],[[[22.7497180000002,59],[23.045277000000112,58.83638],[22.042221,58.939987],[22.7497180000002,59]]],[[[25.780277000000126,59.62887600000012],[28.015831,59.4786],[28.170359,59.30978],[27.426105,58.81360600000012],[27.82305100000019,57.87387800000012],[27.372059,57.535637],[26.511387,57.5261],[25.294998000000106,58.084435],[24.314980000000105,57.871826],[24.555553,58.327217],[23.728607,58.370827],[23.495548,58.694153],[23.874996,58.7686],[23.483051000000103,58.80999],[23.464161,59.206383],[25.780277000000126,59.62887600000012]]]]}},{"type":"Feature","properties":{"name":"Eritrea","iso2":"ER","iso3":"ERI"},"geometry":{"type":"MultiPolygon","coordinates":[[[[40.087219,15.851665],[40.419441,15.573889000000136],[39.977776,15.605],[40.087219,15.851665]]],[[[40.113327,16.05583200000011],[39.979721,16.012218000000118],[40.030273,16.095276],[40.113327,16.05583200000011]]],[[[38.797775,17.653332],[39.7211070000001,15.084166],[39.881386,15.489443],[40.17083,14.973610000000136],[41.170555,14.6325],[43.12138400000018,12.708332],[42.399719,12.469721],[40.228058,14.443506],[39.024021,14.655162000000146],[38.44944000000012,14.4175],[37.91138500000014,14.88361],[37.572212,14.102253],[37.291664,14.451944],[36.5428160000001,14.262053],[36.44328300000021,15.149952],[36.97305300000019,16.269444],[36.995827,17.073887],[37.423286000000104,17.034214],[38.600693,17.994881],[38.797775,17.653332]]]]}},{"type":"Feature","properties":{"name":"El Salvador","iso2":"SV","iso3":"SLV"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-87.686401,13.168333],[-87.72168,13.168055],[-87.723068,13.214722],[-87.686401,13.168333]]],[[[-89.339737,14.416111],[-88.47084,13.855276],[-87.75029,13.864166],[-87.815582,13.405386000000107],[-87.93779,13.156387],[-88.53862,13.194166],[-90.09639,13.745832],[-89.348312,14.431982],[-89.339737,14.416111]]]]}},{"type":"Feature","properties":{"name":"Ethiopia","iso2":"ET","iso3":"ETH"},"geometry":{"type":"MultiPolygon","coordinates":[[[[36.5428160000001,14.262053],[37.291664,14.451944],[37.572212,14.102253],[37.91138500000014,14.88361],[38.44944000000012,14.4175],[39.024021,14.655162000000146],[40.228058,14.443506],[42.399719,12.469721],[41.828606,11.74],[41.789719,11.008055],[42.944092,11.002438],[42.663055,10.6325],[42.848053,10.22361],[44.010551,9.007221],[47.01194,8.00111],[47.988243,8.004107],[44.950829,4.902499],[43.686386,4.891944],[41.905167,3.980322],[41.171387,3.9425],[40.783768,4.287975],[39.524437,3.406389],[38.121109,3.611666],[37.039719,4.375555000000134],[35.940552,4.622499],[35.821663,5.32861],[35.30194100000014,5.378055],[34.70472,6.677777000000106],[33.711388,7.660277],[32.991104,7.924999],[33.252777,8.458611000000118],[34.120552,8.577221000000122],[34.28611,10.554165],[34.594444,10.887777],[34.864441,10.734999],[35.096939000000106,11.826944],[35.70108,12.666115],[36.142693,12.706923000000117],[36.5428160000001,14.262053]]]]}},{"type":"Feature","properties":{"name":"Austria","iso2":"AT","iso3":"AUT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[13.833611,48.773605],[14.70028,48.581379],[15.025833,49.018883],[16.946182,48.619064],[17.166386,48.012497],[17.053886,47.709442],[16.450554,47.698051],[16.713886,47.543884],[16.510555,47.00666],[16.111805,46.86972],[14.544998,46.407494],[13.718655,46.526611],[12.440554000000134,46.69082600000014],[12.127777,47.00166300000011],[10.471235,46.871353],[9.598635,47.063835],[9.533569,47.274544],[9.566724,47.540451],[10.173332,47.274719000000104],[10.478054,47.591942000000145],[11.095554,47.396111],[12.735554,47.684166000000104],[13.016666,47.470276],[12.758333,48.123886],[13.833611,48.773605]]]]}},{"type":"Feature","properties":{"name":"Czech Republic","iso2":"CZ","iso3":"CZE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[14.70028,48.581379],[13.833611,48.773605],[12.674444,49.42499500000015],[12.093704000000116,50.322533],[14.309721,51.05360400000011],[14.828333,50.865829],[16.341942,50.66111],[16.20583,50.423882],[16.641941,50.10833],[17.00222,50.216942],[16.890274,50.439438],[17.722775,50.319717],[17.657776,50.108055],[18.577221,49.914444],[18.851246,49.517357],[16.946182,48.619064],[15.025833,49.018883],[14.70028,48.581379]]]]}},{"type":"Feature","properties":{"name":"French Guiana","iso2":"GF","iso3":"GUF"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-53.494339,5.572342],[-52.285278,4.937499],[-52.040001,4.331388],[-51.850563,4.653333],[-51.684067,4.034163],[-52.909729,2.195833],[-54.603783,2.329195],[-54.001114,3.448333],[-54.477501,4.747777],[-54.166946,5.346944],[-53.939728,5.744721],[-53.494339,5.572342]]]]}},{"type":"Feature","properties":{"name":"Finland","iso2":"FI","iso3":"FIN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[22.8336124420166,59.95638465881348],[23.072500228881836,59.95111274719238],[22.91750144958496,59.898332595825195],[22.8336124420166,59.95638465881348]]],[[[22.438886642456055,59.99582862854004],[22.351945877075195,60.06694221496582],[22.440553665161133,60.07249641418457],[22.438886642456055,59.99582862854004]]],[[[21.598054885864258,60.09805488586426],[21.48527717590332,60.1138858795166],[21.655553817749023,60.15555000305176],[21.598054885864258,60.09805488586426]]],[[[21.74888801574707,60.11138343811035],[21.71555519104004,60.183053970336914],[21.885278701782227,60.17721748352051],[21.74888801574707,60.11138343811035]]],[[[21.396665573120117,60.178606033325195],[21.385278701782227,60.15666389465332],[21.26833152770996,60.18805122375488],[21.396665573120117,60.178606033325195]]],[[[22.00083351135254,60.12944221496582],[21.937498092651367,60.170000076293945],[22.060834884643555,60.20388984680176],[22.00083351135254,60.12944221496582]]],[[[25.84861183166504,60.1955509185791],[25.810556411743164,60.20416450500488],[25.874998092651367,60.21110725402832],[25.84861183166504,60.1955509185791]]],[[[22.824445724487305,60.22722053527832],[22.469465255737305,60.00000190734863],[22.44972038269043,60.218332290649414],[22.587778091430664,60.20250129699707],[22.824445724487305,60.22722053527832]]],[[[22.242223739624023,60.181108474731445],[22.2177791595459,60.21860694885254],[22.294443130493164,60.248605728149414],[22.242223739624023,60.181108474731445]]],[[[22.342222213745117,60.28305244445801],[22.06888771057129,60.26861000061035],[22.09610939025879,60.30777931213379],[22.342222213745117,60.28305244445801]]],[[[22.383333206176758,60.28833198547363],[22.32527732849121,60.33471870422363],[22.476945877075195,60.32361030578613],[22.383333206176758,60.28833198547363]]],[[[21.982778549194336,60.324167251586914],[21.78999900817871,60.37249946594238],[21.8075008392334,60.46555519104004],[21.982778549194336,60.324167251586914]]],[[[21.751665115356445,60.49833106994629],[21.684446334838867,60.452775955200195],[21.73000144958496,60.520273208618164],[21.763334274291992,60.52250099182129],[21.751665115356445,60.49833106994629]]],[[[21.48333168029785,60.520273208618164],[21.4325008392334,60.4697208404541],[21.321943283081055,60.54305458068848],[21.48333168029785,60.520273208618164]]],[[[21.328889846801758,60.48111152648926],[21.275835037231445,60.47805213928223],[21.226945877075195,60.552499771118164],[21.328889846801758,60.48111152648926]]],[[[21.2902774810791,60.61222267150879],[21.289167404174805,60.56138801574707],[21.21416664123535,60.61972236633301],[21.2902774810791,60.61222267150879]]],[[[21.32750129699707,60.87722206115723],[21.254167556762695,60.95888710021973],[21.357221603393555,60.921945571899414],[21.32750129699707,60.87722206115723]]],[[[21.080278396606445,63.281389236450195],[21.427221298217773,63.19693946838379],[21.246946334838867,63.144723892211914],[21.080278396606445,63.281389236450195]]],[[[22.18083381652832,63.265275955200195],[22.040834426879883,63.30694007873535],[22.1924991607666,63.32193946838379],[22.18083381652832,63.265275955200195]]],[[[21.323331832885742,63.28916358947754],[21.231943130493164,63.3255558013916],[21.3811092376709,63.34111213684082],[21.323331832885742,63.28916358947754]]],[[[22.87360954284668,63.799997329711914],[22.671388626098633,63.794443130493164],[22.80611228942871,63.87693977355957],[22.87360954284668,63.799997329711914]]],[[[24.73499870300293,64.94444465637207],[24.551668167114258,65.02499580383301],[25.035001754760742,65.03610420227051],[24.73499870300293,64.94444465637207]]],[[[24.462221145629883,65.76388740539551],[24.43694496154785,65.76971626281738],[24.503053665161133,65.78055000305176],[24.462221145629883,65.76388740539551]]],[[[28.165834426879883,69.91221809387207],[29.176111221313477,69.6352710723877],[28.78416633605957,69.16055488586426],[28.95734214782715,69.05162239074707],[28.431943893432617,68.89694404602051],[28.820554733276367,68.84443855285645],[28.45749855041504,68.53193855285645],[28.693334579467773,68.19749641418457],[30.02861213684082,67.6947193145752],[29.07499885559082,66.89583015441895],[30.134164810180664,65.71916389465332],[29.81888771057129,65.65332221984863],[29.636667251586914,64.92805671691895],[30.578054428100586,64.22137641906738],[29.99333381652832,63.743608474731445],[31.588930130004883,62.91441535949707],[27.807832717895508,60.546403884887695],[26.497220993041992,60.44693946838379],[26.65916633605957,60.64750099182129],[25.920000076293945,60.24166297912598],[22.90972328186035,59.80499458312988],[23.338335037231445,60.01999855041504],[22.87444496154785,60.14555549621582],[23.086942672729492,60.346940994262695],[23.05583381652832,60.35333442687988],[22.662778854370117,60.22222328186035],[22.57499885559082,60.21055030822754],[22.447221755981445,60.24444007873535],[22.63222312927246,60.39193916320801],[21.358610153198242,60.65361213684082],[21.668054580688477,61.546945571899414],[21.064722061157227,62.61222267150879],[21.68610954284668,63.02499580383301],[21.497777938842773,63.21000099182129],[22.337221145629883,63.27360725402832],[22.18805503845215,63.46305274963379],[23.31888771057129,63.89666175842285],[24.343332290649414,64.52360725402832],[24.54222297668457,64.80249214172363],[25.447221755981445,64.95471382141113],[25.310834884643555,65.51111030578613],[24.66916847229004,65.65471076965332],[24.689165115356445,65.89610481262207],[24.167009353637695,65.81402778625488],[23.661943435668945,66.31221199035645],[24.007776260375977,66.8005542755127],[23.571664810180664,67.15666389465332],[23.767778396606445,67.41610908508301],[23.43111228942871,67.46554756164551],[23.666112899780273,67.9416675567627],[21.809167861938477,68.57054328918457],[20.580930709838867,69.06030464172363],[21.320833206176758,69.32611274719238],[22.398332595825195,68.71110725402832],[23.976388931274414,68.83249092102051],[24.934919357299805,68.58081245422363],[25.761110305786133,68.98916816711426],[25.945833206176758,69.67332649230957],[26.44999885559082,69.92721748352051],[28.165834426879883,69.91221809387207]],[[25.677221298217773,60.234994888305664],[25.56110954284668,60.26583290100098],[25.598054885864258,60.207773208618164],[25.677221298217773,60.234994888305664]],[[23.705827713012695,59.92721748352051],[23.538328170776367,59.960275650024414],[23.3700008392334,59.911386489868164],[23.705827713012695,59.92721748352051]]]]}},{"type":"Feature","properties":{"name":"Fiji","iso2":"FJ","iso3":"FJI"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-178.707764,-20.674442],[-178.737213,-20.666115],[-178.73056,-20.646114],[-178.707764,-20.674442]]],[[[-178.211426,-19.852505],[-178.209747,-19.826389],[-178.19809,-19.835838],[-178.211426,-19.852505]]],[[[-178.396698,-19.185001],[-178.425049,-19.177502],[-178.398621,-19.129169],[-178.396698,-19.185001]]],[[[179.779694,-19.195278],[179.740234,-19.188053],[179.773041,-19.123333],[179.779694,-19.195278]]],[[[-178.538605,-19.181946],[-178.596954,-19.155834],[-178.585846,-19.113613],[-178.538605,-19.181946]]],[[[178.498291,-18.989998],[177.95108,-19.13139],[178.306915,-18.935555],[178.498291,-18.989998]]],[[[-178.936707,-18.989445],[-178.967224,-18.978336],[-178.949432,-18.925835],[-178.936707,-18.989445]]],[[[-179.78363,-18.946388],[-179.868896,-19.005283],[-179.845001,-18.922504],[-179.78363,-18.946388]]],[[[178.528046,-18.910831],[178.4766240000002,-18.883057],[178.521637,-18.859722],[178.528046,-18.910831]]],[[[-178.498627,-18.674725],[-178.506683,-18.635281],[-178.473053,-18.650558],[-178.498627,-18.674725]]],[[[179.91275,-18.641945],[179.837463,-18.576389],[179.963867,-18.540558],[179.91275,-18.641945]]],[[[177.66330000000013,-18.590279],[177.6191099999999,-18.538334],[177.6307980000001,-18.491943],[177.66330000000013,-18.590279]]],[[[178.13272100000015,-18.4175],[178.109406,-18.407501],[178.13970900000012,-18.351944],[178.13272100000015,-18.4175]]],[[[-178.778351,-18.249725],[-178.828613,-18.190002],[-178.747528,-18.201389],[-178.778351,-18.249725]]],[[[179.351898,-18.121113],[179.245789,-18.036388],[179.266663,-17.936111],[179.351898,-18.121113]]],[[[-179.011719,-17.995277],[-179.068359,-17.932503],[-178.991119,-17.950832],[-179.011719,-17.995277]]],[[[-178.286987,-17.96611],[-178.347809,-17.894165],[-178.244476,-17.917778],[-178.286987,-17.96611]]],[[[179.421906,-17.848335],[179.392761,-17.786388],[179.42108199999987,-17.797222],[179.421906,-17.848335]]],[[[-179.292511,-17.783897],[-179.331146,-17.771954],[-179.319153,-17.727509],[-179.292511,-17.783897]]],[[[178.820251,-17.742775],[178.7477420000001,-17.719719],[178.791931,-17.621113],[178.820251,-17.742775]]],[[[-179.141998,-17.476952],[-179.178894,-17.433064],[-179.143341,-17.431114],[-179.141998,-17.476952]]],[[[178.280823,-17.403053],[178.67804,-18.078335],[177.299133,-18.078613],[177.510254,-17.509445],[178.280823,-17.403053]]],[[[177.112457,-17.314445],[177.10025,-17.271114],[177.1419369999999,-17.247776],[177.112457,-17.314445]]],[[[-179.128632,-17.283611],[-179.162811,-17.250835],[-179.121429,-17.258617],[-179.128632,-17.283611]]],[[[179.399414,-17.394444],[179.357178,-17.259445],[179.4330440000002,-17.242222],[179.399414,-17.394444]]],[[[-178.925293,-17.257225],[-178.98584,-17.318058],[-179.02005,-17.153053],[-178.925293,-17.257225]]],[[[177.263611,-17.123611],[177.177185,-17.163612],[177.281097,-17.051945],[177.263611,-17.123611]]],[[[178.333038,-16.835835],[178.282196,-16.833889],[178.277191,-16.789444],[178.333038,-16.835835]]],[[[179.947479,-17.002781],[179.882446,-16.964165],[180,-16.787395],[179.947479,-17.002781]]],[[[-179.993317,-16.955276],[-179.861633,-16.680321],[-179.821106,-16.781094],[-179.993317,-16.955276]]],[[[177.443024,-16.83778],[177.559967,-16.677498],[177.593018,-16.687778],[177.443024,-16.83778]]],[[[179.929413,-16.659164],[179.914154,-16.661945],[179.88443,-16.657501],[179.916656,-16.625832],[179.947754,-16.613056],[179.929413,-16.659164]]],[[[180,-16.537918],[179.9810790000001,-16.524445],[180,-16.494274],[180,-16.537918]]],[[[-179.976166,-16.535278],[-179.988617,-16.476952],[-179.896423,-16.43111],[-179.976166,-16.535278]]],[[[179.958008,-16.197498],[179.478577,-16.701111],[179.932465,-16.460831],[179.950256,-16.513058],[179.87133800000012,-16.665001],[179.951904,-16.741943],[179.9021910000001,-16.769447],[179.265808,-16.690556],[178.747192,-17.011948],[178.478851,-16.78167],[179.958008,-16.197498]]],[[[-179.968872,-16.16761],[-180,-16.154732],[-179.941132,-16.128345],[-179.968872,-16.16761]]],[[[177.119415,-12.514446],[177.026917,-12.507223],[177.11911000000018,-12.484722],[177.119415,-12.514446]]]]}},{"type":"Feature","properties":{"name":"Falkland Islands (Malvinas)","iso2":"FK","iso3":"FLK"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-59.691673,-52.242783],[-59.761116,-52.273613],[-59.753334,-52.170006],[-59.683891,-52.172783],[-59.691673,-52.242783]]],[[[-58.435005,-52.093895],[-58.53389,-52.024445],[-58.432503,-51.99028],[-58.435005,-52.093895]]],[[[-61.224449,-51.864723],[-61.313896,-51.824722],[-61.215004,-51.797226],[-61.224449,-51.864723]]],[[[-61.034447,-51.869446],[-60.867783,-51.903336],[-61.149445,-51.848892],[-60.940559,-51.800285],[-61.034447,-51.869446]]],[[[-61.195839,-51.699448],[-61.315834,-51.733612],[-61.305,-51.693062],[-61.195839,-51.699448]]],[[[-59.210556,-51.410561],[-60.368057,-52.159172],[-60.980835,-52.061951],[-60.180557,-51.758896],[-60.638335999999896,-51.722229],[-60.163612,-51.661392],[-60.642227,-51.3555599999999],[-60.132225,-51.494728],[-60.019447,-51.380005],[-59.210556,-51.410561]]],[[[-58.69667099999987,-51.33667],[-58.22695199999987,-51.654449],[-58.279449,-51.417503],[-57.911949,-51.376396],[-57.761673,-51.538338],[-58.142784,-51.553894],[-57.731392,-51.692223],[-58.940559,-51.801949],[-58.64695,-52.067223],[-59.289726,-52.004173],[-59.035278,-52.14389],[-59.449173,-52.140839],[-59.348061,-52.343056],[-59.718056,-52.121117],[-58.69667099999987,-51.33667]]],[[[-59.93556199999989,-51.350838],[-60.025284,-51.297783],[-59.906113,-51.303062],[-59.93556199999989,-51.350838]]],[[[-60.110557999999884,-51.405281],[-60.300285,-51.271393],[-60.068062,-51.307503],[-60.110557999999884,-51.405281]]],[[[-59.508339,-51.337502],[-59.81111099999987,-51.26973],[-59.479172,-51.264725],[-59.508339,-51.337502]]]]}},{"type":"Feature","properties":{"name":"Micronesia, Federated States of","iso2":"FM","iso3":"FSM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[153.674408,5.286943],[153.659973,5.291666],[153.711365,5.319721],[153.674408,5.286943]]],[[[163.007477,5.263055000000108],[162.904144,5.307221],[163.016388,5.378332],[163.007477,5.263055000000108]]],[[[143.063599,6.707222000000115],[143.054688,6.714722],[143.063599,6.719443],[143.063599,6.707222000000115]]],[[[149.320251,6.698332],[149.313293,6.702499],[149.324982,6.721944],[149.320251,6.698332]]],[[[157.94220000000016,6.71861],[157.93191500000015,6.721944],[157.95245400000013,6.734444],[157.94220000000016,6.71861]]],[[[157.973572,6.738332],[157.964142,6.74111],[157.99273700000018,6.751944000000108],[157.973572,6.738332]]],[[[158.29776,6.786110000000122],[158.120789,6.929721],[158.318848,6.930277],[158.29776,6.786110000000122]]],[[[158.253876,6.983333000000101],[158.241638,6.992777],[158.259979,7.000278],[158.253876,6.983333000000101]]],[[[151.860504,7.31861],[151.839966,7.370276],[151.866638,7.358610000000112],[151.860504,7.31861]]],[[[149.20163,7.363333],[149.194702,7.361388000000105],[149.203033,7.376388],[149.20163,7.363333]]],[[[149.191345,7.375554],[149.177765,7.382499],[149.188019,7.384444],[149.191345,7.375554]]],[[[143.920258,7.37972100000016],[143.911926,7.382499],[143.914154,7.391388],[143.920258,7.37972100000016]]],[[[151.6391600000002,7.326666000000102],[151.5672000000002,7.34111],[151.608307,7.395277000000121],[151.6391600000002,7.326666000000102]]],[[[151.911652,7.444999],[151.85495,7.423888],[151.866638,7.463888000000139],[151.911652,7.444999]]],[[[146.1932980000001,7.504167],[146.179688,7.510833],[146.187195,7.515555000000106],[146.1932980000001,7.504167]]],[[[149.67498800000013,8.575554],[149.6594240000002,8.590275],[149.688873,8.617496],[149.67498800000013,8.575554]]],[[[150.378021,8.617496],[150.373291,8.612776000000125],[150.366638,8.626387],[150.378021,8.617496]]],[[[150.130249,8.978331],[150.118286,8.976387],[150.128021,8.992496],[150.130249,8.978331]]],[[[138.209137,9.523888000000127],[138.060242,9.41527600000012],[138.133606,9.571943],[138.209137,9.523888000000127]]]]}},{"type":"Feature","properties":{"name":"French Polynesia","iso2":"PF","iso3":"PYF"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-143.482483,-27.914448],[-143.508911,-27.890839],[-143.483917,-27.900276],[-143.482483,-27.914448]]],[[[-144.307526,-27.642776],[-144.324738,-27.553333],[-144.285553,-27.577499],[-144.307526,-27.642776]]],[[[-147.689758,-23.881668],[-147.720306,-23.865276],[-147.648621,-23.853336],[-147.689758,-23.881668]]],[[[-149.483337,-23.401943],[-149.52533,-23.373894],[-149.457214,-23.361671],[-149.483337,-23.401943]]],[[[-135.051941,-23.163887],[-135.06308,-23.156113],[-135.031708,-23.143333],[-135.051941,-23.163887]]],[[[-134.985535,-23.139442],[-135.015564,-23.12167],[-134.941406,-23.085838],[-134.985535,-23.139442]]],[[[-152.860016,-22.656387],[-152.845551,-22.605003],[-152.826416,-22.634171],[-152.860016,-22.656387]]],[[[-151.36557,-22.518616],[-151.387817,-22.425835],[-151.350281,-22.464725],[-151.36557,-22.518616]]],[[[-138.714722,-22.271667],[-138.796661,-22.22028],[-138.743591,-22.204449],[-138.714722,-22.271667]]],[[[-140.609467,-21.71917],[-140.66864,-21.708332],[-140.666687,-21.655834],[-140.609467,-21.71917]]],[[[-144.956146,-19.923332],[-144.965027,-19.929169],[-144.958344,-19.895283],[-144.956146,-19.923332]]],[[[-150.648071,-17.662498],[-150.669464,-17.645283],[-150.645294,-17.642498],[-150.648071,-17.662498]]],[[[-149.211426,-17.733891],[-149.179199,-17.870834],[-149.632507,-17.549999],[-149.211426,-17.733891]]],[[[-149.848602,-17.573612],[-149.937256,-17.484165],[-149.786133,-17.46917],[-149.848602,-17.573612]]],[[[-149.532257,-16.974445],[-149.54306,-16.974998],[-149.544189,-16.964443],[-149.532257,-16.974445]]],[[[-149.572266,-16.969723],[-149.59198,-16.980003],[-149.586121,-16.956108],[-149.572266,-16.969723]]],[[[-150.998322,-16.824169],[-151.040039,-16.786118],[-150.994476,-16.762505],[-150.998322,-16.824169]]],[[[-151.40033,-16.888332],[-151.476654,-16.895283],[-151.475037,-16.740276],[-151.40033,-16.888332]]],[[[-151.03833,-16.769726],[-151.037537,-16.693054],[-151.007233,-16.74472],[-151.03833,-16.769726]]],[[[-151.458344,-16.673332],[-151.532257,-16.589443],[-151.441101,-16.599171],[-151.458344,-16.673332]]],[[[-151.748627,-16.534451],[-151.775879,-16.473331],[-151.742249,-16.490833],[-151.748627,-16.534451]]],[[[-146.335846,-16.164722],[-146.38446,-16.110279],[-146.334991,-16.113056],[-146.335846,-16.164722]]],[[[-148.23526,-15.848612],[-148.26532,-15.846947],[-148.28363,-15.800835],[-148.23526,-15.848612]]],[[[-144.621948,-15.74861],[-144.646393,-15.73889],[-144.633667,-15.708055],[-144.621948,-15.74861]]],[[[-138.656708,-10.549725],[-138.695587,-10.431112],[-138.618347,-10.465555],[-138.656708,-10.549725]]],[[[-139.107483,-9.978058],[-139.125824,-9.906113],[-139.047791,-9.914167],[-139.107483,-9.978058]]],[[[-138.9552609999999,-9.743055],[-138.809479,-9.744999],[-139.1725459999999,-9.780281],[-138.9552609999999,-9.743055]]],[[[-140.07724,-9.450556],[-140.147827,-9.380556],[-140.086121,-9.324724],[-140.07724,-9.450556]]],[[[-139.58252,-8.87361],[-139.504181,-8.917225],[-139.611969,-8.95639],[-139.58252,-8.87361]]],[[[-140.026428,-8.901112],[-140.189453,-8.954166],[-140.249756,-8.802778],[-140.026428,-8.901112]]],[[[-140.704712,-8.044168],[-140.709747,-7.965556],[-140.637817,-7.959446],[-140.704712,-8.044168]]],[[[-140.584991,-7.92389],[-140.60614,-7.913611],[-140.56308,-7.888333],[-140.584991,-7.92389]]]]}},{"type":"Feature","properties":{"name":"France","iso2":"FR","iso3":"FRA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[9.485832000000187,42.61527300000013],[9.49472,42.60360700000014],[9.457777,42.643326],[9.485832000000187,42.61527300000013]]],[[[9.44666500000011,42.678886],[9.553333000000123,42.1155550000001],[9.18083200000018,41.364716000000115],[8.78916500000011,41.558052],[8.575832,42.383606],[9.293888,42.675552],[9.353054000000128,43.003883],[9.44666500000011,42.678886]]],[[[-1.194445,45.8224950000001],[-1.401667,46.05055200000011],[-1.233056,45.964722],[-1.194445,45.8224950000001]]],[[[-1.260834,46.156387],[-1.553056,46.24499500000012],[-1.474445,46.255829],[-1.260834,46.156387]]],[[[-2.270832999999868,46.69332900000013],[-2.363889,46.698051],[-2.384999999999877,46.725555],[-2.270832999999868,46.69332900000013]]],[[[-2.196945,47.017220000000165],[-2.145,46.90583],[-2.284722,47.02055400000013],[-2.196945,47.017220000000165]]],[[[-3.066666999999882,47.306664],[-3.215834,47.302498000000114],[-3.258610999999888,47.376106],[-3.066666999999882,47.306664]]],[[[-5.055,48.454163],[-5.134723,48.458328],[-5.064723,48.48305500000011],[-5.055,48.454163]]],[[[-3.576667,48.803886],[-3.575556,48.812492],[-3.563334,48.808609],[-3.576667,48.803886]]],[[[2.541667000000103,51.09111],[4.165,50.283051],[4.149238,49.978371],[4.832503,50.16861],[4.873055000000107,49.797218],[5.80788,49.545044],[6.36217,49.459389],[8.226078,48.964417000000125],[7.578888,48.11972000000016],[7.588268,47.58448],[6.990555000000143,47.497215],[5.966666,46.209442],[6.791389000000152,46.434166],[7.038054,45.93193800000013],[6.798970000000168,45.78067],[7.127777,45.257774],[6.61976,45.110138],[7.031666000000115,44.831383000000116],[6.976388,44.284164],[7.662222,44.17083000000012],[7.528055,43.788605],[7.439293000000106,43.75752300000015],[7.416111,43.770554],[7.387777,43.748604],[7.391609,43.727547],[6.165277000000117,43.050552],[5.031388,43.556664],[3.964722,43.540833],[3.081388,43.069443],[3.177655000000158,42.436806],[1.723611,42.509438],[1.78172,42.569962],[1.445833,42.601944],[-0.562222,42.781387],[-1.780876999999862,43.359924],[-1.036110999999892,44.675278],[-1.250278,44.662498],[-1.083888999999886,45.564438],[-0.536667,44.89555400000013],[-0.776667,45.461105],[-1.240834,45.70166],[-1.067778,45.908882000000105],[-1.114635,46.316582],[-2.130834,46.838333000000105],[-1.984167,47.034439],[-2.170834,47.126663],[-2.134167,47.278053],[-1.728610999999887,47.210831],[-2.003334,47.31916000000011],[-2.289167,47.238884],[-2.540278,47.296661],[-2.361111,47.504166],[-2.698056,47.637215],[-3.106388999999865,47.472221],[-4.366389,47.80416100000012],[-4.726142,48.040581],[-4.186111,48.29999500000012],[-4.777779,48.509438],[-3.220834,48.8705520000001],[-2.685277999999869,48.501663],[-1.368889,48.643608],[-1.941667,49.723885],[-1.264167,49.684166],[-1.113889,49.365273],[0.424722,49.45166],[0.074167,49.526665],[1.461111,50.124161],[1.625000000000114,50.87777700000011],[2.541667000000103,51.09111]]]]}},{"type":"Feature","properties":{"name":"Gambia","iso2":"GM","iso3":"GMB"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-16.73167,13.44972],[-16.200836,13.251665],[-16.162224,13.425278],[-15.295834,13.491665],[-16.14389,13.454166],[-16.394726,13.330555],[-16.56567,13.589998],[-15.070278,13.826387],[-13.798613,13.406387],[-14.351112,13.237778],[-15.111668,13.595833],[-15.285002,13.374443],[-15.803612,13.347776],[-15.809723,13.159721],[-16.750874,13.059977],[-16.73167,13.44972]]]]}},{"type":"Feature","properties":{"name":"Gabon","iso2":"GA","iso3":"GAB"},"geometry":{"type":"MultiPolygon","coordinates":[[[[9.007776260375977,-0.767778396606445],[8.946664810180664,-0.658332824707031],[9.00666618347168,-0.598888397216797],[9.007776260375977,-0.767778396606445]]],[[[12.523611068725586,2.283334732055664],[13.293889999389648,2.163610458374023],[13.186784744262695,1.222475051879883],[14.18889045715332,1.391389846801758],[14.487222671508789,0.913610458374023],[13.848333358764648,-0.198610305786133],[14.518610000610352,-0.609167098999023],[14.429723739624023,-1.891666412353516],[14.110834121704102,-2.49305534362793],[13.76222038269043,-2.088888168334961],[13.482778549194336,-2.4375],[13.001508712768555,-2.367671966552734],[12.649999618530273,-1.822500228881836],[12.478055953979492,-2.327220916748047],[11.574167251586914,-2.333332061767578],[11.925832748413086,-3.636943817138672],[11.496946334838867,-3.50694465637207],[11.140661239624023,-3.925275802612305],[9.700834274291992,-2.445554733276367],[10.130556106567383,-2.520000457763672],[9.615278244018555,-2.376667022705078],[8.983057022094727,-1.234167098999023],[9.513887405395508,-1.59666633605957],[8.710000991821289,-0.641111373901367],[9.013887405395508,-0.81916618347168],[9.298334121704102,-0.371665954589844],[9.347501754760742,0.363058090209961],[9.921110153198242,0.185277938842773],[9.303609848022461,0.52833366394043],[9.600000381469727,0.481111526489258],[9.564722061157227,0.983057022094727],[9.803976058959961,1.002607345581055],[11.353887557983398,1.001943588256836],[11.339765548706055,2.168611526489258],[12.523611068725586,2.283334732055664]],[[9.554445266723633,0.274446487426758],[9.544443130493164,0.285001754760742],[9.538057327270508,0.270833969116211],[9.554445266723633,0.274446487426758]]]]}},{"type":"Feature","properties":{"name":"Georgia","iso2":"GE","iso3":"GEO"},"geometry":{"type":"MultiPolygon","coordinates":[[[[41.547623,42.405777],[41.428596,42.738045],[40.002968,43.379265],[40.253387,43.582520000000116],[42.849991,43.17915300000011],[43.911934000000116,42.583321],[44.934708,42.76027700000013],[46.451752,41.897057],[46.194427000000104,41.6858220000001],[46.693871,41.312202],[46.520821,41.049988],[45.336655,41.462494],[45.022942,41.29705000000014],[43.46077,41.112961],[42.827492,41.584991],[41.531559,41.523876],[41.776093,41.841927],[41.547623,42.405777]]]]}},{"type":"Feature","properties":{"name":"Ghana","iso2":"GH","iso3":"GHA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[0.63953,5.845486],[0.662222,5.754167],[0.255833,5.757777],[-0.795556,5.208055],[-1.613333,5.020833],[-2.058889,4.730833],[-3.103041,5.085022],[-3.102272,5.109545000000125],[-2.928128,5.100222],[-2.764445,5.579166],[-3.249166999999886,6.611388],[-2.487778,8.197777000000116],[-2.685561,9.481817],[-2.834048,11.002007],[-0.618333,10.911665],[-0.149762,11.13854],[0.368333,10.259443],[0.2175,9.457222],[0.550833,9.411388],[0.382735,8.760756],[0.727222,8.321388],[0.525,6.947778],[1.198891,6.100546],[0.692222,5.748055],[0.634444,5.948055],[0.51209,6.055245],[0.208197,6.089699],[0.488889,6.043611],[0.63953,5.845486]]]]}},{"type":"Feature","properties":{"name":"Grenada","iso2":"GD","iso3":"GRD"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-61.74694799999986,11.997499],[-61.611946,12.23111],[-61.628616,12.048054],[-61.74694799999986,11.997499]]],[[[-61.580002,12.295555],[-61.589172,12.298054],[-61.578896,12.323055],[-61.580002,12.295555]]],[[[-61.428337,12.453609],[-61.496948,12.443609],[-61.434448,12.529165],[-61.428337,12.453609]]]]}},{"type":"Feature","properties":{"name":"Greenland","iso2":"GL","iso3":"GRL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-43.64805603027344,59.847490310668945],[-44.11555480957031,59.82916450500488],[-43.95805358886719,59.97971534729004],[-43.64805603027344,59.847490310668945]]],[[[-43.295005798339844,59.92083168029785],[-43.327781677246094,59.99721717834473],[-43.20417022705078,59.96832466125488],[-43.295005798339844,59.92083168029785]]],[[[-44.31388854980469,59.87193489074707],[-44.244163513183594,60.011667251586914],[-43.992225646972656,60.00833320617676],[-44.31388854980469,59.87193489074707]]],[[[-43.399993896484375,59.926103591918945],[-43.50917053222656,59.912492752075195],[-43.453330993652344,60.03804969787598],[-43.399993896484375,59.926103591918945]]],[[[-43.35417175292969,60.08443641662598],[-43.13111114501953,60.05526924133301],[-44.132774353027344,60.14083290100098],[-43.35417175292969,60.08443641662598]]],[[[-44.40943908691406,59.947771072387695],[-44.49749755859375,60.00860786437988],[-44.43444061279297,60.14138221740723],[-44.20166778564453,60.04610633850098],[-44.40943908691406,59.947771072387695]]],[[[-45.23249816894531,60.143327713012695],[-45.29999542236328,60.145830154418945],[-45.26611328125,60.1874942779541],[-45.23249816894531,60.143327713012695]]],[[[-45.36500358581543,60.18526649475098],[-45.35388946533203,60.38249397277832],[-45.1522216796875,60.37638282775879],[-45.36500358581543,60.18526649475098]]],[[[-45.95471954345703,60.615549087524414],[-45.9969482421875,60.626657485961914],[-45.98277282714844,60.67276954650879],[-45.961387634277344,60.68387794494629],[-45.78333282470703,60.66082191467285],[-45.95471954345703,60.615549087524414]]],[[[-45.88861083984375,60.69582557678223],[-45.98520278930664,60.69222831726074],[-46.091941833496094,60.63555335998535],[-46.20471954345703,60.67276954650879],[-46.00695037841797,60.70638465881348],[-45.88861083984375,60.69582557678223]]],[[[-46.345550537109375,60.66805458068848],[-46.49944305419922,60.69915962219238],[-46.2772216796875,60.77221870422363],[-46.345550537109375,60.66805458068848]]],[[[-47.754173278808594,60.80471229553223],[-47.90277862548828,60.6763858795166],[-48.2388916015625,60.795549392700195],[-47.754173278808594,60.80471229553223]]],[[[-46.98027801513672,60.77276802062988],[-47.04944610595703,60.80526924133301],[-47.01111602783203,60.80804634094238],[-46.98027801513672,60.77276802062988]]],[[[-47.16138458251953,60.798051834106445],[-47.22694396972656,60.81805610656738],[-47.15277862548828,60.816667556762695],[-47.16138458251953,60.798051834106445]]],[[[-47.23138427734375,60.841936111450195],[-47.25861358642578,60.8558292388916],[-47.17833709716797,60.87193489074707],[-47.23138427734375,60.841936111450195]]],[[[-47.10194396972656,60.822771072387695],[-47.19249725341797,60.835824966430664],[-47.08361053466797,60.874711990356445],[-47.10194396972656,60.822771072387695]]],[[[-46.75361633300781,60.75027656555176],[-46.845001220703125,60.76055335998535],[-46.16444396972656,60.922494888305664],[-46.75361633300781,60.75027656555176]]],[[[-47.029441833496094,60.89721870422363],[-47.05027770996094,60.895273208618164],[-46.95805358886719,60.925554275512695],[-47.029441833496094,60.89721870422363]]],[[[-47.140838623046875,60.879159927368164],[-47.171669006347656,60.88360786437988],[-47.073333740234375,60.92666053771973],[-47.140838623046875,60.879159927368164]]],[[[-46.466392517089844,60.92222023010254],[-46.51416778564453,60.930551528930664],[-46.52666473388672,60.9888858795166],[-46.51860809326172,60.993608474731445],[-46.429443359375,60.9758243560791],[-46.466392517089844,60.92222023010254]]],[[[-48.07361602783203,61.05388069152832],[-48.37055206298828,61.0786075592041],[-48.24333190917969,61.09860420227051],[-48.07361602783203,61.05388069152832]]],[[[-48.93444061279297,61.249162673950195],[-48.874168395996094,61.3013858795166],[-48.72416687011719,61.29138374328613],[-48.93444061279297,61.249162673950195]]],[[[-48.58332824707031,61.31276893615723],[-48.83306121826172,61.33499336242676],[-48.52333068847656,61.36110877990723],[-48.58332824707031,61.31276893615723]]],[[[-42.45305633544922,61.44137763977051],[-42.496665954589844,61.45499610900879],[-42.38972473144531,61.4888858795166],[-42.45305633544922,61.44137763977051]]],[[[-49.0897216796875,61.63333320617676],[-49.19444274902344,61.66221046447754],[-49.149444580078125,61.70054817199707],[-49.0897216796875,61.63333320617676]]],[[[-49.39222717285156,61.70694160461426],[-49.48527526855469,61.75139045715332],[-49.349998474121094,61.743051528930664],[-49.39222717285156,61.70694160461426]]],[[[-42.2691650390625,61.75027656555176],[-42.084442138671875,61.8749942779541],[-42.12110900878906,61.77276802062988],[-42.2691650390625,61.75027656555176]]],[[[-49.4405517578125,61.874711990356445],[-49.63417053222656,61.93082618713379],[-49.41944885253906,61.930551528930664],[-49.4405517578125,61.874711990356445]]],[[[-49.663330078125,62.18027687072754],[-49.79833984375,62.213884353637695],[-49.65027618408203,62.23777198791504],[-49.663330078125,62.18027687072754]]],[[[-42.2772216796875,62.577219009399414],[-42.13111114501953,62.564714431762695],[-42.12555694580078,62.49638557434082],[-42.2772216796875,62.577219009399414]]],[[[-41.99610900878906,62.77499580383301],[-41.86194610595703,62.73472023010254],[-42.447776794433594,62.75139045715332],[-41.99610900878906,62.77499580383301]]],[[[-41.56138610839844,62.873605728149414],[-41.58860778808594,63.00249671936035],[-41.458335876464844,63.01638984680176],[-41.56138610839844,62.873605728149414]]],[[[-50.63666534423828,63.07388496398926],[-50.67028045654297,63.02527046203613],[-50.7550048828125,63.06193733215332],[-50.63666534423828,63.07388496398926]]],[[[-41.333885192871094,63.05027198791504],[-41.526390075683594,63.08138465881348],[-41.373329162597656,63.109994888305664],[-41.333885192871094,63.05027198791504]]],[[[-41.209442138671875,63.15777015686035],[-41.18444061279297,63.12276649475098],[-41.466392517089844,63.1713809967041],[-41.209442138671875,63.15777015686035]]],[[[-50.79972839355469,63.08166694641113],[-50.788055419921875,63.186655044555664],[-50.682777404785156,63.11666297912598],[-50.79972839355469,63.08166694641113]]],[[[-50.61805725097656,63.11471748352051],[-50.612220764160156,63.20166206359863],[-50.468605041503906,63.15332221984863],[-50.61805725097656,63.11471748352051]]],[[[-41.09583282470703,63.22110176086426],[-41.43083190917969,63.23137855529785],[-41.87194061279297,63.46666145324707],[-41.09583282470703,63.22110176086426]]],[[[-51.27361297607422,63.476938247680664],[-51.358055114746094,63.48333168029785],[-51.20471954345703,63.499162673950195],[-51.27361297607422,63.476938247680664]]],[[[-52.00083923339844,64.12776374816895],[-52.06361389160156,64.16388130187988],[-51.90583038330078,64.18887519836426],[-52.00083923339844,64.12776374816895]]],[[[-40.674171447753906,64.29136848449707],[-40.679443359375,64.20860481262207],[-41.05278015136719,64.23275947570801],[-40.674171447753906,64.29136848449707]]],[[[-41.12555694580078,64.28831672668457],[-41.374168395996094,64.28499031066895],[-41.29695129394531,64.31721687316895],[-41.12555694580078,64.28831672668457]]],[[[-51.567222595214844,64.25610542297363],[-51.439720153808594,64.36248970031738],[-51.321388244628906,64.32638740539551],[-51.567222595214844,64.25610542297363]]],[[[-51.239723205566406,64.21470832824707],[-51.341941833496094,64.25332832336426],[-51.025001525878906,64.54942512512207],[-50.81916809082031,64.54165840148926],[-51.239723205566406,64.21470832824707]]],[[[-51.32361602783203,64.37359809875488],[-51.42138671875,64.41331672668457],[-51.091941833496094,64.5666675567627],[-51.32361602783203,64.37359809875488]]],[[[-52.08306121826172,64.59137153625488],[-52.141944885253906,64.59776496887207],[-52.149169921875,64.62719917297363],[-52.1199951171875,64.62915229797363],[-52.08306121826172,64.59137153625488]]],[[[-40.18000030517578,64.43109321594238],[-40.864723205566406,64.90860176086426],[-40.54277801513672,64.84414863586426],[-40.18000030517578,64.43109321594238]]],[[[-40.49583435058594,65.0152759552002],[-40.625274658203125,65.0385913848877],[-40.55638885498047,65.07388496398926],[-40.49583435058594,65.0152759552002]]],[[[-52.39666557312012,65.10942268371582],[-52.36138916015625,65.18692207336426],[-52.24500274658203,65.1816577911377],[-52.39666557312012,65.10942268371582]]],[[[-39.49444580078125,65.31999397277832],[-39.564443588256836,65.26582527160645],[-39.804443359375,65.3338794708252],[-39.49444580078125,65.31999397277832]]],[[[-39.27777862548828,65.46138191223145],[-39.38694763183594,65.50193977355957],[-39.2388916015625,65.50860786437988],[-39.27777862548828,65.46138191223145]]],[[[-52.92833709716797,65.42526435852051],[-53.08777618408203,65.49247932434082],[-52.87194061279297,65.51361274719238],[-52.92833709716797,65.42526435852051]]],[[[-38.84916687011719,65.51860237121582],[-38.95861053466797,65.51776313781738],[-38.76111602783203,65.54165840148926],[-38.84916687011719,65.51860237121582]]],[[[-37.037506103515625,65.53276252746582],[-37.19153594970703,65.53262519836426],[-37.21333312988281,65.57805061340332],[-37.037506103515625,65.53276252746582]]],[[[-52.99500274658203,65.54887580871582],[-53.23249816894531,65.59832954406738],[-52.848052978515625,65.64415168762207],[-52.99500274658203,65.54887580871582]]],[[[-36.99555206298828,65.58442878723145],[-37.212501525878906,65.68441963195801],[-36.992225646972656,65.70109748840332],[-36.99555206298828,65.58442878723145]]],[[[-37.3941650390625,65.81360054016113],[-37.48500061035156,65.60721015930176],[-37.989166259765625,65.69832038879395],[-37.3941650390625,65.81360054016113]]],[[[-36.79833984375,65.75055122375488],[-36.942771911621094,65.8197193145752],[-36.776947021484375,65.86387825012207],[-36.79833984375,65.75055122375488]]],[[[-36.319725036621094,65.82193183898926],[-36.37110900878906,65.87747383117676],[-36.18305969238281,65.87803840637207],[-36.319725036621094,65.82193183898926]]],[[[-36.6199951171875,65.79525947570801],[-36.736663818359375,65.8016529083252],[-36.74833679199219,65.90971565246582],[-36.507225036621094,65.95694160461426],[-36.6199951171875,65.79525947570801]]],[[[-53.52527618408203,66.04248237609863],[-53.679725646972656,66.08194160461426],[-53.423057556152344,66.08442878723145],[-53.52527618408203,66.04248237609863]]],[[[-35.499725341796875,66.17415046691895],[-35.537506103515625,66.22554206848145],[-35.38500213623047,66.24081611633301],[-35.499725341796875,66.17415046691895]]],[[[-33.86194610595703,66.79387092590332],[-33.970550537109375,66.83970832824707],[-33.88444519042969,66.87248420715332],[-33.86194610595703,66.79387092590332]]],[[[-53.070838928222656,66.86609077453613],[-52.86823272705078,66.89721870422363],[-53.46416473388672,66.79887580871582],[-53.070838928222656,66.86609077453613]]],[[[-33.431114196777344,67.14221382141113],[-33.476104736328125,67.18054389953613],[-33.34222412109375,67.20471382141113],[-33.431114196777344,67.14221382141113]]],[[[-33.252227783203125,67.29525947570801],[-33.327781677246094,67.33610725402832],[-33.25695037841797,67.37608528137207],[-33.252227783203125,67.29525947570801]]],[[[-53.65888977050781,67.67581367492676],[-53.7630615234375,67.77693367004395],[-53.58777618408203,67.73359870910645],[-53.65888977050781,67.67581367492676]]],[[[-53.34722137451172,68.00999641418457],[-53.473052978515625,68.06915473937988],[-53.22527313232422,68.05859565734863],[-53.34722137451172,68.00999641418457]]],[[[-51.2933349609375,68.10081672668457],[-52.00750732421875,68.07666206359863],[-51.20527458190918,68.12164497375488],[-51.2933349609375,68.10081672668457]]],[[[-29.838054656982422,68.14082527160645],[-30.011669158935547,68.20749092102051],[-29.694721221923828,68.20860481262207],[-29.838054656982422,68.14082527160645]]],[[[-52.070838928222656,68.11526679992676],[-52.315834045410156,68.16887092590332],[-51.45417022705078,68.25776863098145],[-52.070838928222656,68.11526679992676]]],[[[-52.9888916015625,68.35775947570801],[-53.211944580078125,68.4013843536377],[-53.01972198486328,68.49443244934082],[-52.85417175292969,68.43332099914551],[-52.9888916015625,68.35775947570801]]],[[[-52.64167022705078,68.52998542785645],[-52.69471740722656,68.54609870910645],[-52.43943786621094,68.5608081817627],[-52.64167022705078,68.52998542785645]]],[[[-52.749725341796875,68.48471260070801],[-52.88417053222656,68.54887580871582],[-52.80944061279297,68.56860542297363],[-52.749725341796875,68.48471260070801]]],[[[-51.94194030761719,68.59443855285645],[-52.42138671875,68.57138252258301],[-51.80332946777344,68.62719917297363],[-51.94194030761719,68.59443855285645]]],[[[-51.0352783203125,68.63943672180176],[-51.23277282714844,68.66665840148926],[-51.12944030761719,68.6827564239502],[-51.0352783203125,68.63943672180176]]],[[[-52.13472557067871,68.70109748840332],[-53.12055206298828,68.56414985656738],[-52.63417053222656,68.71026802062988],[-52.13472557067871,68.70109748840332]]],[[[-23.286666870117188,69.64109992980957],[-23.593055725097656,69.71304512023926],[-23.289443969726562,69.73831367492676],[-23.286666870117188,69.64109992980957]]],[[[-50.505279541015625,69.81053352355957],[-50.60639190673828,69.85637092590332],[-50.40972137451172,69.8611011505127],[-50.505279541015625,69.81053352355957]]],[[[-50.92333221435547,69.89276313781738],[-50.65388488769531,69.83665657043457],[-50.958335876464844,69.55053901672363],[-51.38805389404297,69.70526313781738],[-50.92333221435547,69.89276313781738]]],[[[-52.69305419921875,69.91748237609863],[-51.83332824707031,69.62608528137207],[-53.57472229003906,69.22943305969238],[-54.2691650390625,69.40220832824707],[-53.347496032714844,69.57971382141113],[-54.99444580078125,69.69470405578613],[-54.389442443847656,69.67526435852051],[-54.93611145019531,69.84553718566895],[-54.22943878173828,69.91304206848145],[-54.82972717285156,70.07832527160645],[-54.429168701171875,70.3097095489502],[-52.69305419921875,69.91748237609863]]],[[[-54.66138458251953,70.37248420715332],[-54.934722900390625,70.37553596496582],[-55.02777862548828,70.4830493927002],[-54.66138458251953,70.37248420715332]]],[[[-51.512779235839844,70.65387153625488],[-51.861671447753906,70.72221565246582],[-51.69249725341797,70.72776985168457],[-51.512779235839844,70.65387153625488]]],[[[-27.68527603149414,70.73387336730957],[-27.736942291259766,70.88220405578613],[-27.276111602783203,70.87498664855957],[-27.68527603149414,70.73387336730957]]],[[[-25.39472198486328,70.91165351867676],[-25.294445037841797,70.65971565246582],[-26.02972412109375,70.52110481262207],[-28.13666534423828,70.45471382141113],[-27.14958953857422,70.87439155578613],[-25.39472198486328,70.91165351867676]]],[[[-51.565834045410156,70.86470222473145],[-52.16221618652344,70.88665962219238],[-52.02305603027344,70.97915840148926],[-51.565834045410156,70.86470222473145]]],[[[-25.30889129638672,71.01443672180176],[-25.579166412353516,71.10220527648926],[-25.460556030273438,71.10415840148926],[-25.30889129638672,71.01443672180176]]],[[[-25.282501220703125,71.13192939758301],[-25.472774505615234,71.15054512023926],[-25.359722137451172,71.20526313781738],[-25.282501220703125,71.13192939758301]]],[[[-53.649169921875,71.02415657043457],[-53.99028015136719,71.1313648223877],[-53.598052978515625,71.31331062316895],[-53.37638854980469,71.11499214172363],[-53.649169921875,71.02415657043457]]],[[[-52.571388244628906,71.34610176086426],[-52.328338623046875,71.28776741027832],[-53.18444061279297,71.32138252258301],[-52.571388244628906,71.34610176086426]]],[[[-53.13361358642578,71.66192817687988],[-52.75611114501953,71.66026496887207],[-53.47444152832031,71.6524829864502],[-53.13361358642578,71.66192817687988]]],[[[-55.559165954589844,71.81915473937988],[-55.80555725097656,71.87886238098145],[-55.409996032714844,71.8902759552002],[-55.559165954589844,71.81915473937988]]],[[[-55.796112060546875,72.07054328918457],[-55.93860626220703,72.07943916320801],[-55.72527313232422,72.12608528137207],[-55.796112060546875,72.07054328918457]]],[[[-55.374168395996094,72.15971565246582],[-55.68888854980469,72.19859504699707],[-55.015281677246094,72.37719917297363],[-55.374168395996094,72.15971565246582]]],[[[-55.06500244140625,72.52527046203613],[-55.383331298828125,72.54525947570801],[-55.030555725097656,72.5888843536377],[-55.06500244140625,72.52527046203613]]],[[[-55.65027618408203,72.58249092102051],[-55.994720458984375,72.55748176574707],[-55.94305419921875,72.59359931945801],[-55.65027618408203,72.58249092102051]]],[[[-55.13194274902344,72.60081672668457],[-55.26222229003906,72.59776496887207],[-54.94666290283203,72.67221260070801],[-55.13194274902344,72.60081672668457]]],[[[-54.83250427246094,72.69552803039551],[-55.0625,72.71832466125488],[-54.87249755859375,72.75694465637207],[-54.83250427246094,72.69552803039551]]],[[[-55.70417022705078,72.71499824523926],[-56.226104736328125,72.70610237121582],[-55.639442443847656,72.77777290344238],[-55.70417022705078,72.71499824523926]]],[[[-55.285560607910156,72.68109321594238],[-55.84944152832031,72.61137580871582],[-54.9647216796875,72.81137275695801],[-55.285560607910156,72.68109321594238]]],[[[-55.94666290283203,72.82361030578613],[-55.801666259765625,72.79248237609863],[-55.992225646972656,72.78665351867676],[-55.94666290283203,72.82361030578613]]],[[[-23.608612060546875,72.83499336242676],[-21.932498931884766,72.39915657043457],[-22.756946563720703,72.44136238098145],[-22.134166717529297,72.27165412902832],[-22.56277847290039,72.13888740539551],[-24.48444366455078,72.8258228302002],[-23.608612060546875,72.83499336242676]]],[[[-55.586387634277344,72.8902759552002],[-55.352500915527344,72.85220527648926],[-55.53666687011719,72.82249641418457],[-55.586387634277344,72.8902759552002]]],[[[-24.896665573120117,72.77777290344238],[-25.210830688476562,72.85165596008301],[-24.77138900756836,72.91081428527832],[-24.896665573120117,72.77777290344238]]],[[[-22.54916763305664,73.0072193145752],[-21.865833282470703,72.7138843536377],[-24.588890075683594,72.95749092102051],[-22.54916763305664,73.0072193145752]]],[[[-55.753334045410156,73.01138496398926],[-55.88972473144531,73.02581977844238],[-55.693885803222656,73.03221321105957],[-55.753334045410156,73.01138496398926]]],[[[-55.0755615234375,72.96554756164551],[-55.68916320800781,72.99359321594238],[-55.51860809326172,73.04582405090332],[-55.0755615234375,72.96554756164551]]],[[[-21.35333251953125,73.09137153625488],[-21.46277618408203,73.11859321594238],[-21.173053741455078,73.13443183898926],[-21.35333251953125,73.09137153625488]]],[[[-56.201942443847656,73.15555000305176],[-56.33167266845703,73.17221260070801],[-56.27333068847656,73.21887397766113],[-56.201942443847656,73.15555000305176]]],[[[-56.0977783203125,73.08638191223145],[-56.01721954345703,73.22859382629395],[-55.8155517578125,73.22470283508301],[-56.0977783203125,73.08638191223145]]],[[[-55.68638610839844,73.28276252746582],[-55.871665954589844,73.3277759552002],[-55.65416717529297,73.35637092590332],[-55.68638610839844,73.28276252746582]]],[[[-55.953887939453125,73.29915046691895],[-56.15332794189453,73.30415534973145],[-55.830833435058594,73.3733081817627],[-55.953887939453125,73.29915046691895]]],[[[-55.53166961669922,73.31805610656738],[-55.59388732910156,73.34414863586426],[-55.328338623046875,73.39499092102051],[-55.53166961669922,73.31805610656738]]],[[[-24.360000610351562,73.41192817687988],[-23.209999084472656,73.23359870910645],[-25.01028060913086,73.30941963195801],[-22.938610076904297,73.13472175598145],[-25.71277618408203,73.18637275695801],[-25.290836334228516,73.3277759552002],[-25.243053436279297,73.40582466125488],[-24.360000610351562,73.41192817687988]]],[[[-55.5897216796875,73.38109016418457],[-56.11583709716797,73.55664253234863],[-55.47083282470703,73.43193244934082],[-55.5897216796875,73.38109016418457]]],[[[-56.4102783203125,73.54193305969238],[-56.55860900878906,73.55636787414551],[-56.18860626220703,73.62747383117676],[-56.4102783203125,73.54193305969238]]],[[[-56.34416198730469,73.67248725891113],[-56.83332824707031,73.61137580871582],[-56.965553283691406,73.65803718566895],[-56.34416198730469,73.67248725891113]]],[[[-56.36860656738281,73.76609992980957],[-56.20555877685547,73.71832466125488],[-56.43694305419922,73.76805305480957],[-56.36860656738281,73.76609992980957]]],[[[-55.9566650390625,73.83471870422363],[-56.323333740234375,73.78332710266113],[-56.7772216796875,73.87581062316895],[-55.9566650390625,73.83471870422363]]],[[[-20.01611328125,73.88443183898926],[-20.234722137451172,73.92637825012207],[-20.11361312866211,73.9327564239502],[-20.01611328125,73.88443183898926]]],[[[-20.926944732666016,74.41998481750488],[-20.123889923095703,74.20109748840332],[-21.990833282470703,74.22720527648926],[-20.926944732666016,74.41998481750488]]],[[[-56.53083038330078,74.53055000305176],[-56.46277618408203,74.5041675567627],[-57.556663513183594,74.48831367492676],[-56.53083038330078,74.53055000305176]]],[[[-56.98277282714844,74.55359077453613],[-57.095550537109375,74.55748176574707],[-56.83860778808594,74.59166145324707],[-56.98277282714844,74.55359077453613]]],[[[-57.185272216796875,74.57609748840332],[-57.281944274902344,74.58166694641113],[-57.08306121826172,74.61303901672363],[-57.185272216796875,74.57609748840332]]],[[[-18.838611602783203,74.53831672668457],[-19.21999740600586,74.58110237121582],[-18.75278091430664,74.65609931945801],[-18.838611602783203,74.53831672668457]]],[[[-18.53000259399414,74.71220588684082],[-18.300556182861328,74.70526313781738],[-18.383056640625,74.6202564239502],[-18.53000259399414,74.71220588684082]]],[[[-57.47638702392578,74.70610237121582],[-57.72721862792969,74.72192573547363],[-57.431114196777344,74.71748542785645],[-57.47638702392578,74.70610237121582]]],[[[-20.166942596435547,74.89749336242676],[-19.729164123535156,74.85859870910645],[-20.08444595336914,74.7027759552002],[-20.68777847290039,74.81164741516113],[-20.493053436279297,75.03082466125488],[-19.960556030273438,74.99247932434082],[-20.166942596435547,74.89749336242676]]],[[[-17.808334350585938,75.30609321594238],[-18.215274810791016,75.22526741027832],[-17.319721221923828,75.13109016418457],[-18.91555404663086,75.0041675567627],[-18.839168548583984,75.32832527160645],[-17.808334350585938,75.30609321594238]]],[[[-65.0494384765625,76.01388740539551],[-65.22111511230469,76.04553413391113],[-64.95556640625,76.05497932434082],[-65.0494384765625,76.01388740539551]]],[[[-64.05555725097656,76.05941963195801],[-64.1461181640625,76.09305000305176],[-64.01472473144531,76.11053657531738],[-64.05555725097656,76.05941963195801]]],[[[-61.899444580078125,76.12970161437988],[-61.96221923828125,76.17859077453613],[-61.88166809082031,76.18664741516113],[-61.899444580078125,76.12970161437988]]],[[[-20.343055725097656,76.26416206359863],[-20.660831451416016,76.3388843536377],[-20.158611297607422,76.3469409942627],[-20.343055725097656,76.26416206359863]]],[[[-69.97610473632812,76.39415168762207],[-70.18832397460938,76.43914985656738],[-69.89445495605469,76.43692207336426],[-69.97610473632812,76.39415168762207]]],[[[-20.38805389404297,76.45166206359863],[-20.496109008789062,76.4749927520752],[-20.267780303955078,76.4952564239502],[-20.38805389404297,76.45166206359863]]],[[[-21.35305404663086,76.47249031066895],[-21.48971939086914,76.48970222473145],[-21.24944305419922,76.49971199035645],[-21.35305404663086,76.47249031066895]]],[[[-20.7933349609375,76.38998603820801],[-21.141109466552734,76.44748115539551],[-20.72083282470703,76.51388740539551],[-20.7933349609375,76.38998603820801]]],[[[-69.66944885253906,76.53055000305176],[-70.03639221191406,76.56331062316895],[-69.4647216796875,76.57943916320801],[-69.66944885253906,76.53055000305176]]],[[[-20.71277618408203,76.5608081817627],[-20.939441680908203,76.52331733703613],[-20.62555694580078,76.57943916320801],[-20.71277618408203,76.5608081817627]]],[[[-21.083057403564453,76.56915473937988],[-21.547500610351562,76.61526679992676],[-20.963886260986328,76.62915229797363],[-21.083057403564453,76.56915473937988]]],[[[-19.648056030273438,76.69832038879395],[-19.857223510742188,76.73193550109863],[-19.605554580688477,76.72638130187988],[-19.648056030273438,76.69832038879395]]],[[[-18.653053283691406,76.60165596008301],[-18.635276794433594,75.88998603820801],[-19.141944885253906,76.5294361114502],[-18.763057708740234,76.58777046203613],[-19.019168853759766,76.75943183898926],[-18.653053283691406,76.60165596008301]]],[[[-19.691944122314453,76.78193855285645],[-19.809165954589844,76.7885913848877],[-19.59000015258789,76.81164741516113],[-19.691944122314453,76.78193855285645]]],[[[-20.19277572631836,76.82249641418457],[-20.389442443847656,76.84721565246582],[-20.210556030273438,76.86859321594238],[-20.19277572631836,76.82249641418457]]],[[[-71.94221496582031,77.30443000793457],[-72.57389831542969,77.41388130187988],[-71.34584045410156,77.37581062316895],[-71.94221496582031,77.30443000793457]]],[[[-70.66777038574219,77.45776557922363],[-70.05638122558594,77.39915657043457],[-71.2994384765625,77.44775581359863],[-70.66777038574219,77.45776557922363]]],[[[-66.19638061523438,77.50444221496582],[-66.66082763671875,77.48858833312988],[-66.73138427734375,77.5072193145752],[-66.19638061523438,77.50444221496582]]],[[[-19.83444595336914,77.50555610656738],[-20.041667938232422,77.5658130645752],[-19.830280303955078,77.5547046661377],[-19.83444595336914,77.50555610656738]]],[[[-66.90055847167969,77.59166145324707],[-66.97084045410156,77.59942817687988],[-66.62582397460938,77.63638496398926],[-66.90055847167969,77.59166145324707]]],[[[-18.03722381591797,77.66609382629395],[-18.24222183227539,77.67997932434082],[-17.584165573120117,77.83777046203613],[-18.03722381591797,77.66609382629395]]],[[[-19.940555572509766,77.96666145324707],[-19.229164123535156,77.82971382141113],[-19.775833129882812,77.83055305480957],[-20.490833282470703,77.95471382141113],[-19.940555572509766,77.96666145324707]]],[[[-19.542224884033203,77.91609382629395],[-19.699722290039062,77.96499824523926],[-19.61361312866211,77.97192573547363],[-19.542224884033203,77.91609382629395]]],[[[-21.310279846191406,77.88554573059082],[-21.428054809570312,77.9236011505127],[-21.11111068725586,78.01220893859863],[-21.310279846191406,77.88554573059082]]],[[[-20.536113739013672,78.01582527160645],[-20.631942749023438,78.0324878692627],[-20.362777709960938,78.0516529083252],[-20.536113739013672,78.01582527160645]]],[[[-19.276668548583984,78.11775398254395],[-19.383331298828125,78.12719917297363],[-19.29888916015625,78.17581367492676],[-19.276668548583984,78.11775398254395]]],[[[-19.0433349609375,78.07693672180176],[-19.191944122314453,78.11775398254395],[-18.829723358154297,78.17637825012207],[-19.0433349609375,78.07693672180176]]],[[[-20.91583251953125,78.14610481262207],[-21.043054580688477,78.18136787414551],[-20.855554580688477,78.16526985168457],[-20.91583251953125,78.14610481262207]]],[[[-20.526668548583984,78.16137886047363],[-20.78333282470703,78.19136238098145],[-20.302223205566406,78.21331977844238],[-20.526668548583984,78.16137886047363]]],[[[-19.490554809570312,78.24136543273926],[-19.595001220703125,78.2472095489502],[-19.422775268554688,78.27665901184082],[-19.490554809570312,78.24136543273926]]],[[[-19.158889770507812,78.24026679992676],[-19.35333251953125,78.28332710266113],[-18.885555267333984,78.29525947570801],[-19.158889770507812,78.24026679992676]]],[[[-19.633331298828125,78.27665901184082],[-19.67749786376953,78.38638496398926],[-19.490554809570312,78.33055305480957],[-19.633331298828125,78.27665901184082]]],[[[-19.288333892822266,78.31387519836426],[-19.40250015258789,78.39444160461426],[-19.08194351196289,78.36303901672363],[-19.288333892822266,78.31387519836426]]],[[[-18.96999740600586,78.39248847961426],[-19.0977783203125,78.42526435852051],[-18.88111114501953,78.42886543273926],[-18.96999740600586,78.39248847961426]]],[[[-19.126110076904297,78.45526313781738],[-19.254169464111328,78.4458179473877],[-18.96416473388672,78.4749927520752],[-19.126110076904297,78.45526313781738]]],[[[-18.571945190429688,78.57805061340332],[-18.738887786865234,78.6060962677002],[-18.31472396850586,78.6736011505127],[-18.571945190429688,78.57805061340332]]],[[[-18.243053436279297,78.75082588195801],[-18.297222137451172,78.8560962677002],[-18.075557708740234,78.8177661895752],[-18.243053436279297,78.75082588195801]]],[[[-19.346946716308594,78.81137275695801],[-19.756668090820312,78.79525947570801],[-19.190834045410156,78.95305061340332],[-19.346946716308594,78.81137275695801]]],[[[-18.03722381591797,78.99275398254395],[-17.849998474121094,79.21554756164551],[-17.55638885498047,79.16415596008301],[-18.03722381591797,78.99275398254395]]],[[[-19.375,79.12637519836426],[-19.496665954589844,79.1958179473877],[-19.314443588256836,79.23137092590332],[-19.375,79.12637519836426]]],[[[-19.90833282470703,80.05914497375488],[-20.01416778564453,80.09665107727051],[-19.756946563720703,80.24136543273926],[-19.018890380859375,80.16360664367676],[-19.90833282470703,80.05914497375488]]],[[[-66.59527587890625,80.60859870910645],[-66.8961181640625,80.67109870910645],[-66.53167724609375,80.61693000793457],[-66.59527587890625,80.60859870910645]]],[[[-20.59722137451172,81.67248725891113],[-20.971111297607422,81.71443367004395],[-20.164443969726562,81.68193244934082],[-20.59722137451172,81.67248725891113]]],[[[-18.585556030273438,81.64665412902832],[-19.245830535888672,81.77777290344238],[-18.304447174072266,81.66220283508301],[-18.585556030273438,81.64665412902832]]],[[[-19.77777862548828,81.8702564239502],[-20.781944274902344,82.13388252258301],[-20.30666732788086,82.13054084777832],[-19.77777862548828,81.8702564239502]]],[[[-18.858333587646484,81.97442817687988],[-19.41388702392578,82.20555305480957],[-18.792224884033203,81.99193000793457],[-18.858333587646484,81.97442817687988]]],[[[-51.46888732910156,81.96832466125488],[-53.357505798339844,82.2249927520752],[-51.19194030761719,81.99359321594238],[-51.46888732910156,81.96832466125488]]],[[[-51.88861083984375,82.2088794708252],[-52.29389190673828,82.2774829864502],[-51.79528045654297,82.21415901184082],[-51.88861083984375,82.2088794708252]]],[[[-48.212501525878906,82.39583015441895],[-48.86444854736328,82.53915596008301],[-48.03472900390625,82.46443367004395],[-48.212501525878906,82.39583015441895]]],[[[-46.00305938720703,82.64444160461426],[-44.41889190673828,82.36609077453613],[-45.067222595214844,82.21666145324707],[-44.737220764160156,82.09582710266113],[-45.07666778564453,82.05581855773926],[-47.749168395996094,82.62498664855957],[-46.00305938720703,82.64444160461426]]],[[[-40.17444610595703,82.66026496887207],[-40.472496032714844,82.68637275695801],[-40.28916931152344,82.69803047180176],[-40.17444610595703,82.66026496887207]]],[[[-49.95471954345703,82.76999092102051],[-50.067222595214844,82.77554512023926],[-49.723052978515625,82.77998542785645],[-49.95471954345703,82.76999092102051]]],[[[-47.56861114501953,82.7824878692627],[-48.415550231933594,82.8480396270752],[-47.44249725341797,82.80386543273926],[-47.56861114501953,82.7824878692627]]],[[[-46.443885803222656,82.83249092102051],[-47.26250457763672,82.93081855773926],[-46.407501220703125,82.83610725402832],[-46.443885803222656,82.83249092102051]]],[[[-39.570556640625,82.99664497375488],[-40.546112060546875,83.15332221984863],[-39.277496337890625,83.08137702941895],[-39.570556640625,82.99664497375488]]],[[[-38.31861114501953,83.13360786437988],[-38.65972137451172,83.16470527648926],[-38.00917053222656,83.1524829864502],[-38.31861114501953,83.13360786437988]]],[[[-39.904998779296875,82.99887275695801],[-41.48277282714844,83.16499519348145],[-40.836944580078125,83.16360664367676],[-39.904998779296875,82.99887275695801]]],[[[-40.15777587890625,83.20332527160645],[-40.57917022705078,83.21971321105957],[-40.086944580078125,83.21165657043457],[-40.15777587890625,83.20332527160645]]],[[[-41.03722381591797,83.20860481262207],[-41.60639190673828,83.22442817687988],[-41.001670837402344,83.21220588684082],[-41.03722381591797,83.20860481262207]]],[[[-42.0977783203125,83.2422046661377],[-42.418060302734375,83.25387763977051],[-41.959442138671875,83.25166511535645],[-42.0977783203125,83.2422046661377]]],[[[-39.64611053466797,83.26220893859863],[-38.63972473144531,83.11581611633301],[-40.67333221435547,83.28027534484863],[-39.64611053466797,83.26220893859863]]],[[[-41.24444580078125,83.28776741027832],[-41.68444061279297,83.31360054016113],[-41.456390380859375,83.32721138000488],[-41.24444580078125,83.28776741027832]]],[[[-38.90277862548828,83.2905445098877],[-39.62194061279297,83.3369312286377],[-39.22388458251953,83.39694404602051],[-38.90277862548828,83.2905445098877]]],[[[-32.30027770996094,83.57026863098145],[-25.650554656982422,83.29165840148926],[-35.617774963378906,82.90109443664551],[-25.142223358154297,83.16276741027832],[-24.751113891601562,83.00082588195801],[-25.901111602783203,82.7774829864502],[-23.992774963378906,82.91165351867676],[-21.314167022705078,82.60803413391113],[-25.068889617919922,82.1524829864502],[-31.61888885498047,82.20749092102051],[-29.904720306396484,82.09332466125488],[-33.09833526611328,81.77388191223145],[-25.202499389648438,81.98942756652832],[-27.63083267211914,81.4861011505127],[-27.32861328125,81.38081550598145],[-24.210556030273438,81.70833015441895],[-24.00222396850586,82.00972175598145],[-22.016944885253906,81.93304634094238],[-22.231109619140625,81.46582221984863],[-24.511669158935547,80.54081916809082],[-19.940834045410156,81.68304634094238],[-20.305557250976562,81.45109748840332],[-18.017223358154297,81.46805000305176],[-17.35388946533203,81.70193672180176],[-17.534725189208984,81.85359382629395],[-16.70055389404297,81.93193244934082],[-12.155000686645508,81.60331916809082],[-16.005001068115234,80.72859382629395],[-21.24749755859375,80.57554817199707],[-16.113887786865234,80.50248908996582],[-17.113887786865234,80.23692512512207],[-19.70083236694336,80.28581428527832],[-20.55472183227539,80.10582160949707],[-20.755001068115234,79.86499214172363],[-20.326946258544922,79.76054573059082],[-19.289443969726562,80.10331916809082],[-17.44916534423828,80.05581855773926],[-19.631389617919922,79.66137886047363],[-19.86888885498047,79.15304756164551],[-19.573612213134766,79.33110237121582],[-19.078887939453125,79.20054817199707],[-19.378334045410156,79.27499580383301],[-20.091110229492188,79.06360054016113],[-19.914722442626953,78.96415901184082],[-20.01805877685547,78.87719917297363],[-21.182498931884766,78.80998420715332],[-20.926387786865234,78.68997383117676],[-21.426944732666016,78.64444160461426],[-20.906387329101562,78.62414741516113],[-22.039443969726562,77.68831062316895],[-21.57833480834961,77.56414985656738],[-20.866390228271484,78.0152759552002],[-20.311946868896484,77.87082099914551],[-19.23999786376953,77.76304817199707],[-18.9566650390625,77.62886238098145],[-21.053611755371094,77.54387092590332],[-18.395832061767578,77.34276008605957],[-18.120555877685547,76.94832038879395],[-18.305278778076172,76.80609321594238],[-20.723052978515625,76.98831367492676],[-21.728885650634766,76.88360786437988],[-20.939441680908203,76.84248542785645],[-21.604999542236328,76.64471626281738],[-22.738887786865234,76.70443916320801],[-21.814443588256836,76.59027290344238],[-22.506946563720703,76.44803047180176],[-21.573055267333984,76.43664741516113],[-21.682220458984375,76.2391529083252],[-19.805835723876953,76.22859382629395],[-21.982219696044922,75.99193000793457],[-19.825000762939453,75.90915107727051],[-19.335556030273438,75.40498542785645],[-19.88277816772461,75.14583015441895],[-22.251113891601562,75.66415596008301],[-21.406387329101562,75.45555305480957],[-22.511390686035156,75.53082466125488],[-20.515003204345703,75.14082527160645],[-22.43555450439453,75.16388130187988],[-20.63888931274414,75.06192207336426],[-20.762779235839844,74.8469409942627],[-20.606109619140625,74.73692512512207],[-21.119720458984375,74.66165351867676],[-18.97777557373047,74.48166084289551],[-19.68499755859375,74.23748970031738],[-22.082778930664062,74.59832954406738],[-21.765003204345703,74.41943550109863],[-22.479164123535156,74.31192207336426],[-22.053054809570312,74.28387641906738],[-22.492494583129883,74.07443428039551],[-21.980552673339844,73.99803352355957],[-21.821666717529297,73.65109443664551],[-21.748607635498047,74.05832099914551],[-20.283058166503906,73.87997627258301],[-20.501113891601562,73.4527759552002],[-22.379165649414062,73.25055122375488],[-24.032222747802734,73.70248603820801],[-22.178333282470703,73.62469673156738],[-24.044166564941406,73.81469917297363],[-24.463054656982422,73.53581428527832],[-25.68694305419922,73.95248603820801],[-24.67416763305664,73.5133228302002],[-25.31500244140625,73.46165657043457],[-25.721385955810547,73.26361274719238],[-26.012500762939453,73.2422046661377],[-27.337501525878906,73.49247932434082],[-26.387500762939453,73.24136543273926],[-27.72861099243164,73.12970161437988],[-27.49749755859375,72.92442512512207],[-26.44916534423828,73.19359016418457],[-25.053890228271484,73.08276557922363],[-27.38833236694336,72.83665657043457],[-26.30472183227539,72.72776985168457],[-26.46277618408203,72.57222175598145],[-24.842498779296875,72.71943855285645],[-24.60944366455078,72.52331733703613],[-25.90833282470703,72.41388130187988],[-25.289169311523438,72.38443183898926],[-25.526668548583984,72.12137031555176],[-24.588333129882812,72.42109870910645],[-22.494441986083984,71.89276313781738],[-23.12555694580078,71.62608528137207],[-21.895832061767578,71.74081611633301],[-22.506389617919922,71.54971504211426],[-22.473331451416016,71.26304817199707],[-21.805557250976562,71.50943183898926],[-21.60361099243164,71.32304573059082],[-21.961666107177734,71.26388740539551],[-21.6875,71.14915657043457],[-22.33388900756836,71.05359077453613],[-21.681110382080078,71.06833076477051],[-21.92916488647461,70.80220222473145],[-21.474720001220703,70.53997993469238],[-22.37722396850586,70.44165229797363],[-22.506946563720703,70.85054206848145],[-22.62277603149414,70.44664192199707],[-23.34583282470703,70.43914985656738],[-24.73999786376953,71.33221626281738],[-28.639720916748047,72.12442207336426],[-27.325000762939453,71.70971870422363],[-28.466941833496094,71.55247688293457],[-25.411388397216797,71.34915351867676],[-26.478885650634766,70.96026802062988],[-28.409164428710938,70.97581672668457],[-27.91416358947754,70.8672046661377],[-29.20694351196289,70.39415168762207],[-26.322223663330078,70.37303352355957],[-28.54277801513672,70.04471015930176],[-27.34194564819336,69.96249580383301],[-25.229164123535156,70.41443061828613],[-22.079166412353516,70.12970161437988],[-23.930553436279297,69.7552661895752],[-23.579166412353516,69.62359809875488],[-24.343334197998047,69.60443305969238],[-24.072776794433594,69.4780445098877],[-26.36333465576172,68.66748237609863],[-29.378055572509766,68.1988697052002],[-29.862220764160156,68.41360664367676],[-30.196945190429688,68.24247932434082],[-30.03028106689453,68.11165046691895],[-31.571666717529297,68.06694221496582],[-31.745830535888672,68.21081733703613],[-31.53583526611328,68.23942756652832],[-32.007225036621094,68.26193428039551],[-32.48500061035156,68.61998176574707],[-32.133331298828125,68.19609260559082],[-32.40027618408203,68.19941902160645],[-31.999164581298828,68.09526252746582],[-32.122772216796875,67.85775947570801],[-33.1986083984375,67.68803596496582],[-33.600555419921875,67.37137031555176],[-33.36583709716797,67.24693489074707],[-33.973052978515625,66.99054145812988],[-34.26721954345703,66.5758228302002],[-34.429725646972656,66.74136543273926],[-34.406944274902344,66.54081916809082],[-34.719993591308594,66.33831977844238],[-35.85166931152344,66.43359565734863],[-35.587501525878906,66.11026191711426],[-36.331947326660156,65.90721321105957],[-36.343055725097656,66.07998847961426],[-36.56666564941406,66.07666206359863],[-36.52111053466797,65.98471260070801],[-36.98027801513672,65.83749580383301],[-37.07749938964844,66.06219673156738],[-37.19305419921875,65.76915168762207],[-37.81138610839844,66.03055000305176],[-37.184722900390625,66.34166145324707],[-38.106109619140625,66.38693428039551],[-37.69166564941406,66.25972175598145],[-38.05194091796875,65.9124927520752],[-38.483612060546875,66.0102710723877],[-38.10083770751953,65.80304145812988],[-38.241943359375,65.62942695617676],[-40.09638977050781,65.56721687316895],[-39.75556182861328,65.24275398254395],[-41.155555725097656,64.96443367004395],[-40.35889434814453,64.34832954406738],[-40.788055419921875,64.38443183898926],[-41.09166717529297,64.30220222473145],[-41.325836181640625,64.34137153625488],[-41.50695037841797,64.3258228302002],[-41.56945037841797,64.26555061340332],[-40.567779541015625,64.1091480255127],[-40.83860778808594,63.94554328918457],[-40.51805877685547,63.697214126586914],[-41.617774963378906,63.79222297668457],[-40.74833679199219,63.509164810180664],[-41.17066955566406,63.51360511779785],[-40.99888610839844,63.40749549865723],[-41.11333465576172,63.385271072387695],[-41.3941650390625,63.55221748352051],[-41.23833465576172,63.404436111450195],[-41.580833435058594,63.48777198791504],[-41.11333465576172,63.30721473693848],[-41.687217712402344,63.52499580383301],[-41.907501220703125,63.4647159576416],[-41.429168701171875,63.12638282775879],[-42.17444610595703,63.20166206359863],[-41.61528015136719,62.987497329711914],[-41.75556182861328,62.839433670043945],[-43.14722442626953,62.75777626037598],[-42.16221618652344,62.38388252258301],[-42.979164123535156,62.515275955200195],[-42.26111602783203,62.24249458312988],[-42.54084014892578,61.94360542297363],[-42.11583709716797,62.006662368774414],[-42.86944580078125,61.77305030822754],[-42.434722900390625,61.55721473693848],[-43.07917022705078,61.59360694885254],[-42.50750732421875,61.35527229309082],[-43.24610900878906,61.33915901184082],[-42.62999725341797,61.09832954406738],[-43.61277770996094,61.12777137756348],[-42.70471954345703,61.05777168273926],[-43.48444366455078,60.93332862854004],[-42.79084014892578,60.801103591918945],[-43.52666473388672,60.83721351623535],[-42.74944305419922,60.683603286743164],[-44.20249938964844,60.59332466125488],[-43.168609619140625,60.39749336242676],[-43.13750457763672,60.07943916320801],[-44.10083770751953,60.384164810180664],[-44.08055877685547,60.286386489868164],[-44.4566650390625,60.148332595825195],[-44.60417175292969,59.982492446899414],[-45.15277862548828,60.074167251586914],[-44.47083282470703,60.55721473693848],[-45.18999481201172,60.129159927368164],[-44.62610626220703,60.73333168029785],[-45.203330993652344,60.43526649475098],[-45.09916687011719,60.645830154418945],[-45.491943359375,60.48999214172363],[-45.313331604003906,60.69999885559082],[-45.97833251953125,60.57388496398926],[-45.671775817871094,60.67632865905762],[-45.84972381591797,60.69748878479004],[-45.25305938720703,60.901933670043945],[-46.22138214111328,60.753610610961914],[-45.19972229003906,61.18998908996582],[-46.0655517578125,60.92110633850098],[-45.65361022949219,61.142221450805664],[-45.76972198486328,61.33360481262207],[-46.00972557067871,61.22304725646973],[-45.839996337890625,61.164995193481445],[-45.915000915527344,61.09027290344238],[-46.22943878173828,60.97471046447754],[-46.406105041503906,61.08416175842285],[-46.380279541015625,61.04110908508301],[-46.442222595214844,60.999162673950195],[-46.52333068847656,61.015275955200195],[-46.58167266845703,60.90582466125488],[-46.83527374267578,60.93027687072754],[-46.70527458190918,60.88138008117676],[-46.85722351074219,60.797494888305664],[-46.95861053466797,60.86332893371582],[-46.91444396972656,60.93332862854004],[-47.02305603027344,60.97609901428223],[-47.80944061279297,60.879159927368164],[-47.31945037841797,60.86776924133301],[-47.447776794433594,60.82027626037598],[-48.2388916015625,60.819719314575195],[-47.68943786621094,61.0049991607666],[-48.40638732910156,60.98832893371582],[-47.83361053466797,61.041940689086914],[-48.21888732910156,61.18499183654785],[-47.91722106933594,61.324167251586914],[-48.4102783203125,61.132211685180664],[-48.63722229003906,61.238046646118164],[-48.37860870361328,61.3638858795166],[-49.06610870361328,61.39805030822754],[-48.34416198730469,61.604997634887695],[-49.29750061035156,61.55749702453613],[-48.599212646484375,61.63633918762207],[-49.148887634277344,61.71859931945801],[-48.7630615234375,61.98472023010254],[-49.440277099609375,61.84221839904785],[-48.840553283691406,62.07694435119629],[-49.66944885253906,61.99554634094238],[-49.29389190673828,62.17222023010254],[-50.317779541015625,62.49527168273926],[-49.94749450683594,62.827219009399414],[-50.28028106689453,62.70471382141113],[-50.317222595214844,62.743051528930664],[-50.15083312988281,62.93082618713379],[-49.701393127441406,63.05749702453613],[-50.19150161743164,62.93366050720215],[-50.37999725341797,62.784440994262695],[-50.149993896484375,63.015275955200195],[-50.60639190673828,63.094438552856445],[-50.059844970703125,63.2287540435791],[-51.10778045654297,63.339433670043945],[-50.27610778808594,63.401384353637695],[-51.22138214111328,63.43943214416504],[-50.504722595214844,63.66721534729004],[-51.55944061279297,63.70916175842285],[-50.924171447753906,63.93249702453613],[-51.443328857421875,63.80499458312988],[-51.60194396972656,64.03471565246582],[-50.04833984375,64.19413948059082],[-51.761390686035156,64.18193244934082],[-50.950836181640625,64.21805000305176],[-50.843055725097656,64.2541675567627],[-51.04194641113281,64.27554512023926],[-50.85639190673828,64.4155445098877],[-50.35222625732422,64.38275337219238],[-50.173057556152344,64.44832038879395],[-50.856666564941406,64.63304328918457],[-49.58429718017578,64.33764839172363],[-50.0655517578125,64.52916145324707],[-49.99888610839844,64.86914253234863],[-50.56055450439453,64.76805305480957],[-50.978607177734375,65.21971321105957],[-50.63666534423828,64.75305366516113],[-51.22416687011719,64.76220893859863],[-52.00695037841797,64.20359992980957],[-52.03916931152344,64.39915657043457],[-52.105560302734375,64.38720893859863],[-52.05750274658203,64.59908485412598],[-52.120277404785156,64.72026252746582],[-51.2469482421875,65.01748847961426],[-52.211387634277344,64.80664253234863],[-52.09972381591797,65.2391529083252],[-52.55889129638672,65.32748603820801],[-51.72083282470703,65.58221626281738],[-51.90110778808594,65.62387275695801],[-51.69444274902344,65.69859504699707],[-51.24388885498047,65.75972175598145],[-50.54583740234375,65.70694160461426],[-51.20916557312012,65.79609870910645],[-51.48472595214844,65.76304817199707],[-51.94805145263672,65.65887641906738],[-51.93444061279297,65.54637336730957],[-52.497779846191406,65.38720893859863],[-52.46916198730469,65.64082527160645],[-52.80194091796875,65.53888130187988],[-52.68888854980469,65.80554389953613],[-53.268333435058594,65.74693489074707],[-51.831947326660156,66.05581855773926],[-53.46221923828125,66.03415107727051],[-51.271385192871094,66.84387397766113],[-50.32917022705078,66.83305549621582],[-50.956390380859375,66.9347095489502],[-49.997779846191406,66.98082160949707],[-50.63221740722656,67.01582527160645],[-50.33472442626953,67.07193183898926],[-51.18943786621094,66.91775703430176],[-53.476661682128906,66.09887886047363],[-53.11833190917969,66.28581428527832],[-53.619720458984375,66.24331855773926],[-53.633331298828125,66.50444221496582],[-52.41638946533203,66.54637336730957],[-53.451942443847656,66.63749885559082],[-52.2288818359375,66.8399829864502],[-53.965553283691406,67.07470893859863],[-53.81666564941406,67.17886543273926],[-53.37999725341797,67.20221138000488],[-53.588890075683594,67.21499824523926],[-53.47721862792969,67.2391529083252],[-52.151390075683594,67.36998176574707],[-51.52471923828125,67.32304573059082],[-51.18943786621094,67.12359809875488],[-50.351112365722656,67.18054389953613],[-51.52583312988281,67.3510913848877],[-51.15166473388672,67.42331123352051],[-53.252227783203125,67.32054328918457],[-53.79833984375,67.2027759552002],[-53.88111114501953,67.26388740539551],[-52.49610900878906,67.76971626281738],[-51.80944061279297,67.62581062316895],[-51.330284118652344,67.67581367492676],[-50.70055389404297,67.49165534973145],[-50.07194519042969,67.50999641418457],[-50.85222625732422,67.59082221984863],[-50.274444580078125,67.7310962677002],[-49.93666076660156,67.6938648223877],[-50.288612365722656,67.74498176574707],[-50.65027618408203,67.65165901184082],[-50.96971893310547,67.6222095489502],[-51.23082733154297,67.69720649719238],[-50.417503356933594,67.84443855285645],[-51.33111572265625,67.86886787414551],[-51.05999755859375,67.97415351867676],[-53.75361633300781,67.6010913848877],[-52.954559326171875,67.97898292541504],[-53.187217712402344,68.04332160949707],[-52.05999755859375,67.97526741027832],[-53.32111358642578,68.18441963195801],[-52.41444396972656,68.0627613067627],[-52.802223205566406,68.16887092590332],[-51.85778045654297,68.04193305969238],[-51.18860626220703,68.06360054016113],[-50.56945037841797,67.90081977844238],[-50.153053283691406,67.93332099914551],[-51.434165954589844,68.19832038879395],[-50.9566650390625,68.1827564239502],[-51.18360900878906,68.39888191223145],[-50.81999969482422,68.50360298156738],[-52.419166564941406,68.18054389953613],[-53.38916778564453,68.3277759552002],[-53.07972717285156,68.32304573059082],[-52.461669921875,68.54498481750488],[-50.86583709716797,68.61470222473145],[-50.65638732910156,68.82554817199707],[-51.292503356933594,68.74832344055176],[-51.069725036621094,69.13109016418457],[-50.209442138671875,68.96081733703613],[-50.687774658203125,69.11775398254395],[-50.13861083984375,69.17747688293457],[-50.380828857421875,69.3388843536377],[-51.122772216796875,69.20138740539551],[-50.20471954345703,69.52192878723145],[-50.883056640625,69.49136543273926],[-50.19166564941406,69.75749397277832],[-50.31361389160156,69.8733081817627],[-50.58916473388672,69.92192268371582],[-50.21416473388672,70.02165412902832],[-52.312774658203125,70.0466480255127],[-54.62638854980469,70.65193367004395],[-54.063331604003906,70.82971382141113],[-52.72222137451172,70.74470710754395],[-50.6763916015625,70.3227710723877],[-50.49055480957031,70.50972175598145],[-51.03722381591797,70.43081855773926],[-50.939720153808594,70.46776008605957],[-51.345001220703125,70.5666675567627],[-50.61888885498047,70.62858772277832],[-51.43860626220703,70.74775886535645],[-50.633056640625,70.74026679992676],[-51.95249938964844,71.02110481262207],[-50.92888641357422,70.98858833312988],[-51.48527526855469,71.06303596496582],[-51.226661682128906,71.14166450500488],[-52.24944305419922,71.1233081817627],[-51.64555358886719,71.36137580871582],[-52.55555725097656,71.17137336730957],[-51.348052978515625,71.4861011505127],[-52.983612060546875,71.41526985168457],[-51.64055633544922,71.71110725402832],[-53.25055694580078,71.7027759552002],[-52.68444061279297,72.00166511535645],[-53.32194519042969,71.82222175598145],[-53.857505798339844,72.32165718078613],[-53.560279846191406,72.35803413391113],[-53.95500183105469,72.32249641418457],[-53.39666557312012,71.85193061828613],[-54.10028076171875,71.70749092102051],[-53.915550231933594,71.44192695617676],[-55.32361602783203,71.38693428039551],[-55.90583038330078,71.67859077453613],[-54.38444519042969,72.22249031066895],[-55.29833984375,71.92859077453613],[-55.58000183105469,71.99887275695801],[-54.682777404785156,72.36638069152832],[-55.62638854980469,72.45749092102051],[-54.29639434814453,72.47998237609863],[-55.016395568847656,72.51999092102051],[-54.627220153808594,72.62164497375488],[-54.87055206298828,72.64248847961426],[-54.60472106933594,72.82805061340332],[-54.850555419921875,73.01443672180176],[-55.697776794433594,73.0666675567627],[-55.08583068847656,73.36276435852051],[-56.075836181640625,73.64860725402832],[-55.60778045654297,73.72026252746582],[-56.40972137451172,74.06608772277832],[-56.12916564941406,74.27832221984863],[-57.32500457763672,74.10775947570801],[-56.309165954589844,74.28720283508301],[-56.71333312988281,74.34082221984863],[-56.13111114501953,74.38388252258301],[-56.79722595214844,74.44331550598145],[-56.19249725341797,74.5516529083252],[-58.697776794433594,75.34637641906738],[-58.208892822265625,75.44192695617676],[-58.408050537109375,75.71527290344238],[-60.87860870361328,76.1524829864502],[-63.440834045410156,76.3733081817627],[-65.47972106933594,76.01860237121582],[-65.88833618164062,76.09832954406738],[-65.55332946777344,76.23387336730957],[-65.76945495605469,76.27554512023926],[-67.30610656738281,76.16748237609863],[-66.4586181640625,75.90971565246582],[-68.50056457519531,76.0869312286377],[-69.63333129882812,76.38081550598145],[-67.98222351074219,76.67943000793457],[-71.37527465820312,77.05609321594238],[-66.4486083984375,77.13388252258301],[-66.17083740234375,77.19331550598145],[-69.10166931152344,77.27192878723145],[-66.23832702636719,77.24859809875488],[-66.65916442871094,77.41443061828613],[-66.05555725097656,77.49136543273926],[-66.725830078125,77.68081855773926],[-68.3447265625,77.49859809875488],[-68.69943237304688,77.66388130187988],[-69.25028991699219,77.45305061340332],[-70.28999328613281,77.56360054016113],[-69.48361206054688,77.75360298156738],[-70.602783203125,77.67804145812988],[-69.96861267089844,77.83360481262207],[-71.32000732421875,77.76361274719238],[-73.05360412597656,78.15721321105957],[-72.4566650390625,78.28637886047363],[-72.84944152832031,78.31414985656738],[-72.55221557617188,78.52110481262207],[-65.97666931152344,79.10165596008301],[-64.82333374023438,79.53360176086426],[-65.06889343261719,80.00915718078613],[-63.78446960449219,80.1483325958252],[-67.04972839355469,80.05748176574707],[-67.4808349609375,80.32554817199707],[-63.68055725097656,81.14387702941895],[-62.79444885253906,80.75110054016113],[-63.371665954589844,81.15582466125488],[-61.056663513183594,81.11970710754395],[-61.313331604003906,81.35582160949707],[-60.770835876464844,81.50055122375488],[-61.45222473144531,81.75305366516113],[-60.806663513183594,81.87997627258301],[-58.899444580078125,81.86470222473145],[-56.47833251953125,81.33249092102051],[-59.466941833496094,81.99693489074707],[-54.505279541015625,82.36554145812988],[-53.559722900390625,82.11609077453613],[-53.82361602783203,81.69359016418457],[-53.63444519042969,81.5133228302002],[-52.899169921875,82.03415107727051],[-49.614723205566406,81.6402759552002],[-51.0655517578125,81.93220710754395],[-49.432220458984375,81.92776679992676],[-51.11888885498047,82.49414253234863],[-50.3175048828125,82.5183277130127],[-44.63999938964844,81.7541675567627],[-44.183326721191406,81.83415412902832],[-44.92527770996094,81.98970222473145],[-44.50250244140625,82.08970832824707],[-44.79528045654297,82.18997383117676],[-44.1905517578125,82.31248664855957],[-42.299171447753906,82.21666145324707],[-45.765838623046875,82.76443672180176],[-42.14277458190918,82.76165962219238],[-41.682777404785156,82.4780445098877],[-41.89805603027344,82.73275947570801],[-41.55027770996094,82.73665046691895],[-39.752784729003906,82.39888191223145],[-40.135276794433594,82.71443367004395],[-46.88999938964844,82.96110725402832],[-43.38666534423828,82.91443061828613],[-45.52471923828125,83.1222095489502],[-42.69499969482422,83.2744312286377],[-38.57444763183594,82.74414253234863],[-39.15027618408203,82.98027229309082],[-36.87749481201172,83.14721870422363],[-38.85639190673828,83.4316577911377],[-32.30027770996094,83.57026863098145]],[[-20.11333465576172,77.65332221984863],[-20.438331604003906,77.62886238098145],[-20.00833511352539,77.60693550109863],[-20.11333465576172,77.65332221984863]]]]}},{"type":"Feature","properties":{"name":"Germany","iso2":"DE","iso3":"DEU"},"geometry":{"type":"MultiPolygon","coordinates":[[[[8.710256576538086,47.69680976867676],[8.678594589233398,47.69334602355957],[8.670557022094727,47.71110725402832],[8.710256576538086,47.69680976867676]]],[[[6.806390762329102,53.60222053527832],[6.746946334838867,53.56027412414551],[6.658334732055664,53.58610725402832],[6.806390762329102,53.60222053527832]]],[[[6.939443588256836,53.669443130493164],[6.87639045715332,53.67027473449707],[7.088335037231445,53.68416786193848],[6.939443588256836,53.669443130493164]]],[[[7.242498397827148,53.70443916320801],[7.135835647583008,53.70611000061035],[7.346944808959961,53.72110939025879],[7.242498397827148,53.70443916320801]]],[[[8.191110610961914,53.72471809387207],[8.120000839233398,53.71305274963379],[8.142778396606445,53.73360633850098],[8.191110610961914,53.72471809387207]]],[[[7.622224807739258,53.75444221496582],[7.467779159545898,53.73305702209473],[7.485834121704102,53.75750160217285],[7.622224807739258,53.75444221496582]]],[[[7.758890151977539,53.76055335998535],[7.664445877075195,53.761667251586914],[7.812780380249023,53.77555274963379],[7.758890151977539,53.76055335998535]]],[[[8.42527961730957,53.928056716918945],[8.411664962768555,53.95555305480957],[8.454999923706055,53.96305274963379],[8.42527961730957,53.928056716918945]]],[[[13.940279006958008,54.02499580383301],[13.925832748413086,54.018327713012695],[13.934446334838867,54.02777290344238],[13.940279006958008,54.02499580383301]]],[[[8.695554733276367,54.04110908508301],[8.671388626098633,54.077775955200195],[8.693334579467773,54.08249855041504],[8.695554733276367,54.04110908508301]]],[[[14.001317977905273,54.06536293029785],[14.225557327270508,53.928606033325195],[14.218889236450195,53.86902046203613],[13.823431015014648,53.85374641418457],[14.056005477905273,53.98486518859863],[13.759164810180664,54.15999794006348],[14.001317977905273,54.06536293029785]]],[[[10.97944450378418,54.38055610656738],[11.017778396606445,54.38027381896973],[11.003053665161133,54.37693977355957],[10.97944450378418,54.38055610656738]]],[[[8.893056869506836,54.46193885803223],[8.815000534057617,54.50083351135254],[8.960554122924805,54.51916694641113],[8.893056869506836,54.46193885803223]]],[[[11.312776565551758,54.40694618225098],[11.006387710571289,54.4616641998291],[11.184167861938477,54.51999855041504],[11.312776565551758,54.40694618225098]]],[[[8.662778854370117,54.49416542053223],[8.59111213684082,54.52777290344238],[8.710832595825195,54.55166816711426],[8.662778854370117,54.49416542053223]]],[[[13.073610305786133,54.48861122131348],[13.09666633605957,54.59055519104004],[13.151388168334961,54.6027774810791],[13.073610305786133,54.48861122131348]]],[[[13.383054733276367,54.63888740539551],[13.730833053588867,54.275835037231445],[13.11833381652832,54.33388710021973],[13.267499923706055,54.38250160217285],[13.146963119506836,54.54560661315918],[13.503091812133789,54.49309730529785],[13.244722366333008,54.55916786193848],[13.383054733276367,54.63888740539551]]],[[[8.364442825317383,54.61332893371582],[8.294443130493164,54.66666603088379],[8.353887557983398,54.7116641998291],[8.364442825317383,54.61332893371582]]],[[[8.567777633666992,54.68527412414551],[8.396944046020508,54.713884353637695],[8.551111221313477,54.75388526916504],[8.567777633666992,54.68527412414551]]],[[[10.97944450378418,54.38055610656738],[10.818536758422852,53.89005470275879],[12.526945114135742,54.47416114807129],[12.924165725708008,54.42694282531738],[12.369722366333008,54.26500129699707],[13.023889541625977,54.39972114562988],[13.455831527709961,54.09610939025879],[13.718332290649414,54.16971778869629],[13.813055038452148,53.84527778625488],[14.275629043579102,53.69906806945801],[14.149168014526367,52.86277961730957],[14.640275955200195,52.57249641418457],[14.599443435668945,51.81860542297363],[15.03639030456543,51.28555488586426],[14.828332901000977,50.86583137512207],[14.309720993041992,51.053606033325195],[12.093706130981445,50.32253456115723],[12.674444198608398,49.424997329711914],[13.833612442016602,48.77360725402832],[12.758333206176758,48.12388801574707],[13.016668319702148,47.47027778625488],[12.735555648803711,47.68416786193848],[11.095556259155273,47.3961124420166],[10.478055953979492,47.59194374084473],[10.173334121704102,47.27472114562988],[9.56672477722168,47.54045295715332],[8.566110610961914,47.80694007873535],[8.576421737670898,47.59137153625488],[7.697225570678711,47.5433292388916],[7.58827018737793,47.584482192993164],[7.578889846801758,48.11972236633301],[8.226079940795898,48.96441841125488],[6.36216926574707,49.45939064025879],[6.524446487426758,49.808610916137695],[6.134416580200195,50.12784767150879],[6.39820671081543,50.32317543029785],[6.011800765991211,50.757272720336914],[5.864721298217773,51.04610633850098],[6.222223281860352,51.465829849243164],[5.962499618530273,51.80777931213379],[6.828889846801758,51.96555519104004],[7.065557479858398,52.38582801818848],[6.68889045715332,52.54916572570801],[7.051668167114258,52.64361000061035],[7.208364486694336,53.242807388305664],[7.015554428100586,53.41472053527832],[7.295835494995117,53.68527412414551],[8.008333206176758,53.71000099182129],[8.503053665161133,53.35416603088379],[8.665555953979492,53.89388465881348],[9.832498550415039,53.536386489868164],[8.899721145629883,53.94082832336426],[8.883611679077148,54.29416847229004],[8.599443435668945,54.33388710021973],[9.016942977905273,54.49833106994629],[8.580549240112305,54.86787986755371],[8.281110763549805,54.7469425201416],[8.393331527709961,55.053056716918945],[8.664545059204102,54.913095474243164],[9.44536018371582,54.82540321350098],[9.972776412963867,54.76111030578613],[9.870279312133789,54.45443916320801],[10.97944450378418,54.38055610656738]],[[11.459165573120117,53.96110725402832],[11.488611221313477,54.02305030822754],[11.37388801574707,53.98861122131348],[11.459165573120117,53.96110725402832]],[[11.544168472290039,54.06138801574707],[11.612421035766602,54.10458564758301],[11.511110305786133,54.04860877990723],[11.544168472290039,54.06138801574707]],[[12.72972297668457,54.41666603088379],[12.702775955200195,54.42833137512207],[12.68610954284668,54.4183292388916],[12.72972297668457,54.41666603088379]]]]}},{"type":"Feature","properties":{"name":"Guam","iso2":"GU","iso3":"GUM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[144.709412,13.234997],[144.655243,13.427776],[144.875244,13.65361],[144.709412,13.234997]]]]}},{"type":"Feature","properties":{"name":"Greece","iso2":"GR","iso3":"GRC"},"geometry":{"type":"MultiPolygon","coordinates":[[[[24.128609,34.856667000000144],[24.128609,34.808884],[24.04472,34.849998],[24.128609,34.856667000000144]]],[[[26.900555,35.358887],[26.89805200000012,35.419998],[27.019997000000103,35.430832],[26.900555,35.358887]]],[[[23.858608,35.52166],[26.290554,35.131104],[24.752777,34.942215],[23.521111,35.288055000000114],[23.606388000000123,35.613327],[23.858608,35.52166]]],[[[27.15749700000012,35.445831000000126],[27.066109,35.60499600000013],[27.228054,35.826385000000144],[27.15749700000012,35.445831000000126]]],[[[23.332222,35.825272],[23.273052,35.899994],[23.325832,35.872215],[23.332222,35.825272]]],[[[23.049442000000113,36.13694],[22.929443,36.37944],[23.107220000000154,36.243889000000124],[23.049442000000113,36.13694]]],[[[25.838882,36.348053],[25.730270000000104,36.369713],[25.771111,36.401932],[25.838882,36.348053]]],[[[25.399162,36.39444],[25.391388,36.408051],[25.406666,36.410553],[25.399162,36.39444]]],[[[27.786663,35.890549],[27.719719,36.1661000000001],[28.225826,36.45304900000012],[27.786663,35.890549]]],[[[27.400272,36.372498],[27.297771,36.464432000000116],[27.445827,36.4086],[27.400272,36.372498]]],[[[25.457771,36.333611],[25.371941,36.472488],[25.486382,36.408051],[25.457771,36.333611]]],[[[26.342216,36.506386],[26.262497,36.59166],[26.460548000000188,36.598053],[26.342216,36.506386]]],[[[27.854717,36.527222],[27.764996,36.574997],[27.859718,36.650269],[27.854717,36.527222]]],[[[24.950275,36.590553],[24.840832,36.658882],[24.938332,36.632774],[24.950275,36.590553]]],[[[25.089722,36.633881],[25.102219,36.693329],[25.187775,36.71666],[25.089722,36.633881]]],[[[21.785831000000115,36.736938],[21.774998,36.697777],[21.75055300000011,36.71249400000012],[21.76055500000018,36.754997],[21.785831000000115,36.736938]]],[[[24.413609000000122,36.66027100000015],[24.349163,36.746109],[24.548054,36.75943800000012],[24.413609000000122,36.66027100000015]]],[[[25.385551,36.651665],[25.275829,36.78138000000017],[25.407219,36.717766],[25.385551,36.651665]]],[[[24.662777000000148,36.747498],[24.609722,36.778328],[24.665276000000148,36.77638200000017],[24.662777000000148,36.747498]]],[[[21.69860800000015,36.739166],[21.704441000000145,36.7966610000001],[21.728333,36.79277],[21.69860800000015,36.739166]]],[[[24.558609000000132,36.775551000000135],[24.521111000000133,36.823883],[24.562496,36.848610000000136],[24.558609000000132,36.775551000000135]]],[[[25.459995000000106,36.822220000000115],[25.420830000000194,36.83194],[25.4741590000001,36.869164],[25.459995000000106,36.822220000000115]]],[[[25.826664,36.779709],[25.73693800000018,36.784431],[25.976662,36.874161],[25.826664,36.779709]]],[[[26.965832,36.681664],[27.064159000000103,36.838875],[27.35277600000012,36.872208],[26.965832,36.681664]]],[[[25.680832,36.878052],[25.609161,36.886658],[25.651939,36.906097],[25.680832,36.878052]]],[[[25.076664000000108,36.951935],[25.023605000000146,36.999146],[25.083881,37.04248000000014],[25.076664000000108,36.951935]]],[[[24.711941,36.903053],[24.641109000000142,37.042221],[24.765274,36.958328],[24.711941,36.903053]]],[[[26.975552,36.924431],[26.890831,37.076378],[27.04832800000014,36.993607],[26.975552,36.924431]]],[[[25.834438,37.09304],[25.782494,37.11998700000011],[25.825554,37.125542],[25.834438,37.09304]]],[[[25.250275,37.008324],[25.09832800000015,37.027489],[25.268604,37.138611],[25.250275,37.008324]]],[[[26.886662,37.09665700000015],[26.769161000000167,37.17638400000011],[26.85833000000011,37.181107],[26.886662,37.09665700000015]]],[[[25.461388,36.91943400000012],[25.341106,37.074997],[25.54472,37.198044],[25.461388,36.91943400000012]]],[[[24.535000000000196,37.182495],[24.509163,37.11277800000012],[24.414719,37.12722000000012],[24.535000000000196,37.182495]]],[[[26.767494,37.186935],[26.772221,37.206657],[26.787495,37.20694],[26.767494,37.186935]]],[[[23.156666,37.240273],[23.09694300000018,37.277496],[23.150555,37.272774000000126],[23.156666,37.240273]]],[[[23.410831,37.300827],[23.373886,37.299721],[23.583332,37.364166],[23.410831,37.300827]]],[[[24.379444,37.30583200000014],[24.442776,37.481667],[24.48333,37.398048000000145],[24.379444,37.30583200000014]]],[[[25.359161,37.407776],[25.313889,37.488045],[25.463608,37.469719],[25.359161,37.407776]]],[[[24.952499000000103,37.38555100000015],[24.884441,37.363609],[24.889721,37.512497],[24.952499000000103,37.38555100000015]]],[[[23.497776,37.504715],[23.432777,37.526665],[23.522499,37.524162],[23.497776,37.504715]]],[[[25.228333,37.534431],[24.97583,37.675552],[25.238888000000145,37.621941],[25.228333,37.534431]]],[[[24.298611,37.526382],[24.298332,37.654999],[24.394165,37.673332],[24.298611,37.526382]]],[[[26.020828,37.514435],[26.06805,37.631943],[26.361111000000108,37.68666100000017],[26.020828,37.514435]]],[[[23.51305400000018,37.691666],[23.425552,37.762497],[23.563889,37.762772],[23.51305400000018,37.691666]]],[[[27.069443,37.711937],[26.57166300000017,37.730553],[26.748608000000104,37.811378],[27.069443,37.711937]]],[[[20.898052,37.80527500000012],[20.831108000000143,37.646385000000166],[20.621944000000155,37.860832],[20.898052,37.80527500000012]]],[[[24.79166400000014,37.99832900000014],[24.96027800000016,37.68555500000012],[24.713333,37.872772],[24.79166400000014,37.99832900000014]]],[[[23.462498,37.878609],[23.437496,37.985832000000144],[23.538887,37.985832000000144],[23.462498,37.878609]]],[[[20.612499,38.394165],[20.792500000000103,38.060272],[20.341389,38.177216],[20.612499,38.394165]]],[[[20.735554,38.309998],[20.644722000000115,38.39804800000012],[20.648888000000113,38.500275000000116],[20.735554,38.309998]]],[[[26.025555,38.176941],[25.861664000000133,38.583611],[26.159443,38.544434],[26.025555,38.176941]]],[[[20.903053,38.545555],[20.899166,38.566383],[20.93888900000013,38.605270000000175],[20.903053,38.545555]]],[[[25.59999500000012,38.531937],[25.52916,38.59970900000012],[25.613331,38.589989],[25.59999500000012,38.531937]]],[[[20.643608000000114,38.5811080000001],[20.557777,38.683884],[20.701385,38.834717],[20.643608000000114,38.5811080000001]]],[[[24.683052000000117,38.79805],[24.553333,38.768326],[24.458332,38.962776],[24.683052000000117,38.79805]]],[[[23.461941,38.853333],[24.153889000000106,38.64666],[24.564163,37.987221],[22.829998,38.829163],[23.461941,38.853333]]],[[[23.736664,39.074715],[23.590832,39.204437],[23.786663,39.124161],[23.736664,39.074715]]],[[[23.50861,39.159721],[23.392498000000103,39.152222],[23.461388000000113,39.208328],[23.50861,39.159721]]],[[[20.198330000000112,39.174438],[20.136665,39.200554],[20.123608000000104,39.23638200000012],[20.198330000000112,39.174438]]],[[[23.862499,39.13666500000012],[23.953609000000142,39.289719],[23.978054000000157,39.2602770000001],[23.862499,39.13666500000012]]],[[[26.377216,39.273598],[26.614441,39.012497],[25.832222,39.183601],[26.377216,39.273598]]],[[[24.99249600000013,39.466385],[25.006386,39.563309],[25.05360800000014,39.530823],[24.99249600000013,39.466385]]],[[[19.926109,39.794441],[19.846664,39.649162],[20.111664000000133,39.363052],[19.641388,39.744438],[19.926109,39.794441]]],[[[19.404163,39.843605],[19.378887,39.868607000000125],[19.430553,39.86749300000015],[19.404163,39.843605]]],[[[25.441666,40.004715],[25.355827,39.78638500000015],[25.05444,39.86055],[25.441666,40.004715]]],[[[25.601662,40.398041],[25.443886,40.475822],[25.694717000000168,40.4661030000001],[25.601662,40.398041]]],[[[24.773331,40.63166000000014],[24.509441,40.658051],[24.64527500000011,40.797775],[24.773331,40.63166000000014]]],[[[26.294167,41.708054],[26.361095,41.711052],[26.63388400000011,41.35443900000014],[26.044720000000154,40.735825],[25.138054000000125,41.011375],[23.735275000000115,40.7549970000001],[24.398331,40.151939],[23.72777600000012,40.350555],[23.93222000000017,39.943054],[23.353611,40.245277000000115],[23.709999,39.91194200000011],[22.94138700000019,40.63055400000012],[22.59111,40.476662],[22.594997,40.012215],[23.344997,39.17805500000013],[22.9377750000001,39.358604],[23.072777000000144,39.036942],[22.523331,38.857216],[24.073887000000127,38.196938],[24.034443,37.651665],[23.515553000000182,38.040550000000124],[22.991386,37.88055400000012],[23.513611,37.429443],[22.72583,37.568329],[23.19833,36.431938],[22.634163,36.804443],[22.488888,36.386108],[22.152775,37.02166],[21.704441000000145,36.81527700000011],[21.649719000000175,37.44194],[21.106388,37.85443900000011],[21.85833,38.340828],[22.868053,37.938049],[23.226109,38.153053],[22.403332,38.448051],[21.147778,38.304161],[20.989441,38.669998],[20.73222,38.801109],[21.149998,39.00193800000012],[20.731941,38.95249900000012],[20.010029,39.6912],[20.671944,40.09805300000012],[20.98349,40.855888],[22.935604,41.342125],[24.263885,41.570549],[25.28500000000014,41.24305],[26.139996,41.354713],[26.066109,41.69749500000013],[26.294167,41.708054]]]]}},{"type":"Feature","properties":{"name":"Guatemala","iso2":"GT","iso3":"GTM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-90.627625,13.930555],[-91.384735,13.978888],[-92.24677999999989,14.550547],[-91.729172,16.074997],[-90.441956,16.088333],[-90.406403,16.416386],[-91.43749999999989,17.241108],[-90.98390199999989,17.256107],[-90.982422,17.820652],[-89.141953,17.818886],[-89.216171,15.88985100000015],[-88.910568,15.893610000000123],[-88.214737,15.724443],[-89.150375,15.073481],[-89.348312,14.431982],[-90.09639,13.745832],[-90.627625,13.930555]]]]}},{"type":"Feature","properties":{"name":"Guinea","iso2":"GN","iso3":"GIN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-13.602783,9.734441],[-14.664446,10.476665],[-14.693056,11.035276],[-15.016847999999868,10.956451000000143],[-14.686944999999895,11.509722],[-13.709167,11.715277],[-13.971035,12.154758],[-13.713139,12.677221],[-12.345404,12.301748],[-11.373058,12.407774],[-11.315556,12.022774],[-10.92889,12.224442],[-10.652748,11.892609],[-10.323893,12.224997],[-9.701946,12.029163],[-9.155556,12.486111],[-8.53388,11.49391],[-8.357779,11.305555],[-8.680557,10.966389],[-8.289722,11.007776],[-7.973984,10.165611],[-8.143612,9.533888000000104],[-7.732779,9.088055],[-7.957778,8.813332],[-7.646536,8.378416],[-8.198056999999892,8.496666],[-7.946838,8.018505],[-8.469749,7.561325],[-8.660557,7.695],[-9.106945,7.198889],[-9.485161,7.361989],[-9.48365,8.346931],[-10.266651,8.488377],[-10.695835,8.298611],[-10.571526,9.059532],[-11.214444999999898,9.997499],[-12.456112,9.888332],[-13.29561,9.032143],[-13.602783,9.734441]]]]}},{"type":"Feature","properties":{"name":"Guyana","iso2":"GY","iso3":"GUY"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-58.450562,6.896944000000119],[-58.4133379999999,6.969166],[-58.328056,6.956666],[-58.450562,6.896944000000119]]],[[[-59.789169,8.34111],[-58.472778,7.349999000000139],[-58.646118,6.42611],[-58.314728,6.894722000000129],[-57.199722,6.147499],[-57.248505,5.486111],[-57.327225,5.026111],[-57.92333999999988,4.821944],[-58.047226,4.008333000000107],[-57.642227,3.356389000000107],[-57.301392,3.3775],[-56.470634,1.944499000000135],[-57.324721999999895,1.975278],[-58.806946,1.185555000000107],[-59.642784,1.731111],[-59.989448999999865,2.693611],[-59.568611,3.899444],[-59.675835,4.388888],[-60.147507,4.5175],[-60.098335,5.217222],[-60.73037,5.204799],[-61.389725,5.940000000000126],[-61.134026,6.711042],[-60.288612,7.057221000000112],[-60.71917,7.535555],[-59.825562,8.236111],[-59.9902799999999,8.535276],[-59.789169,8.34111]]]]}},{"type":"Feature","properties":{"name":"Haiti","iso2":"HT","iso3":"HTI"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-73.58473205566406,18.056943893432617],[-73.66751098632812,18.057222366333008],[-73.70611572265625,18.101388931274414],[-73.58473205566406,18.056943893432617]]],[[[-72.81556701660156,18.698888778686523],[-73.30000305175781,18.927221298217773],[-72.85722351074219,18.83500099182129],[-72.81556701660156,18.698888778686523]]],[[[-72.67361450195312,19.91666603088379],[-71.75418090820312,19.70583152770996],[-71.71583557128906,18.749723434448242],[-72.00306701660156,18.600831985473633],[-71.76786804199219,18.038503646850586],[-73.38639831542969,18.261945724487305],[-73.88166809082031,18.02277946472168],[-74.44667053222656,18.34193992614746],[-74.26806640625,18.665834426879883],[-72.35000610351562,18.5302791595459],[-72.80029296875,19.033056259155273],[-72.72334289550781,19.454999923706055],[-73.46528625488281,19.687776565551758],[-72.67361450195312,19.91666603088379]],[[-73.73945617675781,18.584165573120117],[-73.71528625488281,18.62444496154785],[-73.79806518554688,18.624723434448242],[-73.73945617675781,18.584165573120117]]],[[[-72.62834167480469,19.9869441986084],[-72.95639038085938,20.056665420532227],[-72.81195068359375,20.092222213745117],[-72.62834167480469,19.9869441986084]]]]}},{"type":"Feature","properties":{"name":"Honduras","iso2":"HN","iso3":"HND"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-87.622513,13.246387000000169],[-87.66972399999986,13.278332],[-87.614731,13.28611],[-87.622513,13.246387000000169]]],[[[-87.571945,13.36861],[-87.58168,13.30361000000012],[-87.65834,13.335833],[-87.571945,13.36861]]],[[[-85.841949,16.010555],[-84.26472499999988,15.828609],[-83.85555999999985,15.459999],[-84.208618,15.549999],[-84.07751499999989,15.351387],[-83.131851,14.992979000000105],[-83.239731,14.98249800000012],[-84.482788,14.617777],[-84.906677,14.808611],[-85.732315,13.829235],[-86.015839,14.065832000000114],[-86.763016,13.751621],[-86.695007,13.296944000000124],[-87.301392,12.986599],[-87.396393,13.410831],[-87.815582,13.405386000000107],[-87.75029,13.864166],[-88.47084,13.855276],[-89.339737,14.416111],[-89.348312,14.431982],[-89.150375,15.073481],[-88.214737,15.724443],[-85.841949,16.010555]]],[[[-86.883621,16.086666000000108],[-86.991669,16.087219],[-86.876114,16.121666],[-86.883621,16.086666000000108]]],[[[-86.599731,16.296108],[-86.410278,16.421665000000147],[-86.263336,16.423332],[-86.599731,16.296108]]],[[[-85.944733,16.409721],[-85.900284,16.494720000000157],[-85.83555599999988,16.498886],[-85.944733,16.409721]]],[[[-83.946671,17.405277],[-83.955292,17.417774],[-83.944458,17.414165],[-83.946671,17.405277]]],[[[-83.910568,17.409721],[-83.926392,17.416664],[-83.910004,17.41861000000013],[-83.910568,17.409721]]]]}},{"type":"Feature","properties":{"name":"Croatia","iso2":"HR","iso3":"HRV"},"geometry":{"type":"MultiPolygon","coordinates":[[[[16.90389060974121,42.72610664367676],[16.81389045715332,42.76805305480957],[16.939722061157227,42.768327713012695],[16.90389060974121,42.72610664367676]]],[[[17.7450008392334,42.69194221496582],[17.321664810180664,42.78805732727051],[17.399442672729492,42.79777717590332],[17.7450008392334,42.69194221496582]]],[[[16.820554733276367,42.96000099182129],[17.183610916137695,42.91861152648926],[16.633054733276367,42.98111152648926],[16.820554733276367,42.96000099182129]]],[[[17.298887252807617,43.00694465637207],[17.649843215942383,42.88907814025879],[18.455556869506836,42.56582832336426],[18.503198623657227,42.44944190979004],[17.004167556762695,43.04666328430176],[17.298887252807617,43.00694465637207]]],[[[16.20833396911621,43.02221870422363],[16.050554275512695,43.06305122375488],[16.251943588256836,43.07249641418457],[16.20833396911621,43.02221870422363]]],[[[16.562036514282227,43.230852127075195],[17.19008445739746,43.126054763793945],[16.373056411743164,43.194162368774414],[16.562036514282227,43.230852127075195]]],[[[16.851667404174805,43.26916694641113],[16.404722213745117,43.329721450805664],[16.753053665161133,43.36277961730957],[16.851667404174805,43.26916694641113]]],[[[16.390554428100586,43.332773208618164],[16.198331832885742,43.41166114807129],[16.326387405395508,43.39416694641113],[16.390554428100586,43.332773208618164]]],[[[15.687498092651367,43.63083076477051],[15.606668472290039,43.674997329711914],[15.662221908569336,43.66583442687988],[15.687498092651367,43.63083076477051]]],[[[15.34638786315918,43.80888557434082],[15.376668930053711,43.77592658996582],[15.225000381469727,43.873056411743164],[15.34638786315918,43.80888557434082]]],[[[15.446664810180664,43.887216567993164],[15.260831832885742,44.006662368774414],[15.376943588256836,43.96805000305176],[15.446664810180664,43.887216567993164]]],[[[15.250555038452148,44.01666450500488],[15.062498092651367,44.1572208404541],[15.24305534362793,44.053056716918945],[15.250555038452148,44.01666450500488]]],[[[14.855276107788086,44.17527961730957],[15.226388931274414,43.90110969543457],[15.13749885559082,43.89638710021973],[14.855276107788086,44.17527961730957]]],[[[14.838655471801758,44.6095027923584],[14.732778549194336,44.69805335998535],[15.24888801574707,44.327775955200195],[14.838655471801758,44.6095027923584]]],[[[14.521944046020508,44.47416114807129],[14.367498397827148,44.59027290344238],[14.337499618530273,44.710275650024414],[14.521944046020508,44.47416114807129]]],[[[14.75731086730957,44.803754806518555],[14.865278244018555,44.70666694641113],[14.65925407409668,44.79473686218262],[14.75731086730957,44.803754806518555]]],[[[14.455076217651367,44.90970039367676],[14.49333381652832,44.60638618469238],[14.294137954711914,44.90724754333496],[14.400278091430664,44.9152774810791],[14.315279006958008,45.174997329711914],[14.455076217651367,44.90970039367676]]],[[[14.755834579467773,44.94138526916504],[14.428888320922852,45.07833290100098],[14.539167404174805,45.23944282531738],[14.755834579467773,44.94138526916504]]],[[[16.572500228881836,46.47527503967285],[16.607873916625977,46.47623634338379],[17.669443130493164,45.83500099182129],[18.8170223236084,45.91296577453613],[18.98032569885254,45.37862586975098],[19.423887252807617,45.22583198547363],[19.03972053527832,44.86138343811035],[18.251943588256836,45.13888740539551],[15.786664962768555,45.171945571899414],[16.143056869506836,44.19944190979004],[17.578527450561523,42.94382667541504],[16.884443283081055,43.40305519104004],[15.988332748413086,43.50444221496582],[14.482778549194336,45.311105728149414],[14.292776107788086,45.32499885559082],[13.899168014526367,44.77443885803223],[13.591741561889648,45.481698989868164],[14.601388931274414,45.67527961730957],[15.174459457397461,45.42582130432129],[15.697778701782227,45.84416389465332],[15.654722213745117,46.21944618225098],[16.572500228881836,46.47527503967285]]]]}},{"type":"Feature","properties":{"name":"Hungary","iso2":"HU","iso3":"HUN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[18.81702,45.912964],[17.669441,45.834999],[16.607872,46.476234],[16.111805,46.86972],[16.510555,47.00666],[16.713886,47.543884],[16.450554,47.698051],[17.053886,47.709442],[17.166386,48.012497],[17.251656,48.024994],[18.655277,47.758606],[20.660553,48.563332],[22.151442,48.411919],[22.894804,47.95454],[22.032497,47.530273],[21.176666,46.295555],[20.726955,46.17556],[20.261024,46.114853],[18.81702,45.912964]]]]}},{"type":"Feature","properties":{"name":"Iceland","iso2":"IS","iso3":"ISL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-15.070835,66.1436],[-14.618891,65.994431],[-14.848333,65.731384],[-14.336668,65.783051],[-14.563612,65.494995],[-13.611389,65.509995],[-13.570278,65.25943],[-14.034723,65.193054],[-13.499445,65.069153],[-14.511112,64.797485],[-14.539167,64.406097],[-14.925001,64.26416],[-15.383335,64.371933],[-18.710003,63.391106],[-21.053612,63.945],[-22.689167,63.80555],[-22.703335,64.080826],[-21.36278,64.384987],[-22.102501,64.314438],[-21.508057,64.645554],[-22.170834,64.453888],[-22.407223,64.812485],[-24.059532,64.890884],[-21.835835,65.030273],[-22.56139,65.171097],[-21.698612,65.449158],[-24.542225,65.497772],[-23.805557,65.530548],[-24.105835,65.806656],[-23.226391,65.741653],[-23.873058,65.866653],[-23.213337,65.837494],[-23.81889,66.013321],[-23.371113,65.986664],[-23.665558,66.111099],[-23.473614,66.199158],[-22.424725,65.847488],[-22.972225,66.221375],[-22.43417,66.267776],[-23.188614,66.349716],[-22.9375,66.466385],[-21.399445,66.027222],[-21.603058,65.953323],[-21.33778,65.733322],[-21.777779,65.765823],[-21.084446,65.159164],[-20.927223,65.588882],[-20.446667,65.494995],[-20.424446,66.083054],[-20.179169,66.12944],[-19.451668,65.72583],[-19.453056,66.056381],[-18.784168,66.191101],[-18.069447,65.643326],[-18.299446,66.174713],[-16.594723,66.09111],[-16.527779,66.508041],[-15.381945,66.142776],[-14.710835,66.367218],[-15.070835,66.1436]]]]}},{"type":"Feature","properties":{"name":"India","iso2":"IN","iso3":"IND"},"geometry":{"type":"MultiPolygon","coordinates":[[[[93.91276741027832,7.02861213684082],[93.8238697052002,6.745553970336914],[93.67109870910645,7.181943893432617],[93.91276741027832,7.02861213684082]]],[[[93.66220283508301,7.405832290649414],[93.6544361114502,7.417501449584961],[93.66415596008301,7.41472053527832],[93.66220283508301,7.405832290649414]]],[[[93.63943672180176,7.247220993041992],[93.69359016418457,7.43889045715332],[93.72831916809082,7.32472038269043],[93.63943672180176,7.247220993041992]]],[[[93.45471382141113,7.868890762329102],[93.34942817687988,7.879999160766602],[93.31749153137207,7.997499465942383],[93.45471382141113,7.868890762329102]]],[[[93.57361030578613,7.927778244018555],[93.50277900695801,7.97722053527832],[93.5405445098877,8.015554428100586],[93.57361030578613,7.927778244018555]]],[[[93.48803901672363,7.988889694213867],[93.44304084777832,8.15361213684082],[93.5133228302002,8.226388931274414],[93.48803901672363,7.988889694213867]]],[[[73.03221321105957,8.246664047241211],[73.02083015441895,8.268610000610352],[73.0788745880127,8.310277938842773],[73.03221321105957,8.246664047241211]]],[[[93.16914558410645,8.201387405395508],[93.05998420715332,8.271665573120117],[93.07388496398926,8.348054885864258],[93.16914558410645,8.201387405395508]]],[[[93.60942268371582,8.429998397827148],[93.60193061828613,8.565275192260742],[93.62608528137207,8.508054733276367],[93.60942268371582,8.429998397827148]]],[[[92.7744312286377,9.124719619750977],[92.7088794708252,9.163610458374023],[92.76165962219238,9.263612747192383],[92.7744312286377,9.124719619750977]]],[[[73.63749885559082,10.052778244018555],[73.6302661895752,10.071111679077148],[73.64554023742676,10.097497940063477],[73.63749885559082,10.052778244018555]]],[[[72.63360786437988,10.550832748413086],[72.62469673156738,10.552778244018555],[72.65054512023926,10.577497482299805],[72.63360786437988,10.550832748413086]]],[[[73.68414497375488,10.823053359985352],[73.66220283508301,10.827775955200195],[73.68525886535645,10.829999923706055],[73.68414497375488,10.823053359985352]]],[[[72.17997932434082,10.817499160766602],[72.17053413391113,10.809720993041992],[72.19748115539551,10.872774124145508],[72.17997932434082,10.817499160766602]]],[[[92.49275398254395,10.518331527709961],[92.34665107727051,10.69416618347168],[92.49498176574707,10.90110969543457],[92.49275398254395,10.518331527709961]]],[[[72.29915046691895,10.938055038452148],[72.28943061828613,10.942777633666992],[72.30137825012207,10.954164505004883],[72.29915046691895,10.938055038452148]]],[[[72.74942207336426,11.108888626098633],[72.73665046691895,11.107221603393555],[72.7472095489502,11.120553970336914],[72.74942207336426,11.108888626098633]]],[[[72.10748481750488,11.202775955200195],[72.09971809387207,11.201108932495117],[72.10803413391113,11.215555191040039],[72.10748481750488,11.202775955200195]]],[[[72.77832221984863,11.188886642456055],[72.77083015441895,11.201108932495117],[72.78915596008301,11.25694465637207],[72.77832221984863,11.188886642456055]]],[[[73.00694465637207,11.476663589477539],[73.00444221496582,11.507501602172852],[73.0133228302002,11.502222061157227],[73.00694465637207,11.476663589477539]]],[[[92.63304328918457,11.354166030883789],[92.64360237121582,11.514165878295898],[92.70332527160645,11.385557174682617],[92.63304328918457,11.354166030883789]]],[[[92.2713794708252,11.524442672729492],[92.2169361114502,11.594720840454102],[92.27581977844238,11.582220077514648],[92.2713794708252,11.524442672729492]]],[[[72.71249580383301,11.68861198425293],[72.7008228302002,11.68638801574707],[72.71527290344238,11.69999885559082],[72.71249580383301,11.68861198425293]]],[[[93.05832099914551,11.888612747192383],[92.94331550598145,11.98277473449707],[92.97859382629395,12.033609390258789],[93.05832099914551,11.888612747192383]]],[[[93.13611030578613,12.131940841674805],[93.12553596496582,12.133890151977539],[93.1313648223877,12.149168014526367],[93.13611030578613,12.131940841674805]]],[[[92.7170581817627,12.182806015014648],[92.71859931945801,11.491109848022461],[92.5244312286377,11.854166030883789],[92.7170581817627,12.182806015014648]]],[[[93.09387397766113,12.088052749633789],[93.0608081817627,12.143888473510742],[93.08665657043457,12.207220077514648],[93.09387397766113,12.088052749633789]]],[[[93.86554145812988,12.259164810180664],[93.84860420227051,12.27583122253418],[93.8733081817627,12.277498245239258],[93.86554145812988,12.259164810180664]]],[[[92.78253364562988,12.287679672241211],[92.77415657043457,12.290555953979492],[92.78332710266113,12.293889999389648],[92.78253364562988,12.287679672241211]]],[[[92.83161354064941,12.316526412963867],[92.90165901184082,12.265832901000977],[92.75427436828613,12.07133674621582],[92.83161354064941,12.316526412963867]]],[[[92.90498542785645,12.380830764770508],[92.87275886535645,12.405832290649414],[92.91081428527832,12.404165267944336],[92.90498542785645,12.380830764770508]]],[[[92.92859077453613,12.90916633605957],[92.98748970031738,12.508611679077148],[92.75888252258301,12.304998397827148],[92.92859077453613,12.90916633605957]]],[[[92.69108772277832,12.796110153198242],[92.66887092590332,12.855276107788086],[92.71443367004395,12.989999771118164],[92.69108772277832,12.796110153198242]]],[[[92.87581062316895,13.391389846801758],[92.86665534973145,13.400556564331055],[92.87608528137207,13.403886795043945],[92.87581062316895,13.391389846801758]]],[[[94.27693367004395,13.413610458374023],[94.26388740539551,13.430276870727539],[94.28415107727051,13.44416618347168],[94.27693367004395,13.413610458374023]]],[[[93.06442451477051,13.237497329711914],[92.81341743469238,12.897920608520508],[93.00387763977051,13.571111679077148],[93.06442451477051,13.237497329711914]]],[[[93.04942512512207,13.639444351196289],[92.99304389953613,13.661664962768555],[93.03637886047363,13.679998397827148],[93.04942512512207,13.639444351196289]]],[[[80.94803047180176,15.736665725708008],[80.87858772277832,15.843332290649414],[80.99193000793457,15.765832901000977],[80.94803047180176,15.736665725708008]]],[[[82.3708667755127,16.86777687072754],[82.37082099914551,16.85833168029785],[82.36886787414551,16.871110916137695],[82.3708667755127,16.86777687072754]]],[[[88.89721870422363,21.524999618530273],[88.8449878692627,21.526945114135742],[88.82554817199707,21.5594425201416],[88.83638191223145,21.605833053588867],[88.90860176086426,21.5686092376709],[88.89721870422363,21.524999618530273]]],[[[72.71805000305176,21.606386184692383],[72.60331916809082,21.64361000061035],[72.76609992980957,21.655275344848633],[72.71805000305176,21.606386184692383]]],[[[88.13472175598145,21.619997024536133],[88.04498481750488,21.660829544067383],[88.13247871398926,21.876108169555664],[88.13472175598145,21.619997024536133]]],[[[88.6463794708252,21.8255558013916],[88.64499092102051,21.78472328186035],[88.59359931945801,21.79777717590332],[88.57916450500488,21.82694435119629],[88.64193916320801,21.921663284301758],[88.6463794708252,21.8255558013916]]],[[[88.08859443664551,21.849443435668945],[88.11303901672363,21.948606491088867],[88.1352710723877,21.907499313354492],[88.08859443664551,21.849443435668945]]],[[[78.07554817199707,35.44582557678223],[78.30914497375488,34.64249610900879],[78.98535346984863,34.35001564025879],[78.81164741516113,33.525827407836914],[79.53027534484863,32.754167556762695],[78.97110176086426,32.35083198547363],[78.76054573059082,32.63555335998535],[78.39776802062988,32.54860877990723],[78.76721382141113,31.309999465942383],[79.09248542785645,31.437498092651367],[81.02536201477051,30.204355239868164],[80.37692451477051,29.748605728149414],[80.05581855773926,28.836111068725586],[82.0664005279541,27.914155960083008],[83.29136848449707,27.337778091430664],[84.14721870422363,27.511388778686523],[85.85554695129395,26.570276260375977],[88.01471138000488,26.364721298217773],[88.14279365539551,27.866056442260742],[88.83166694641113,28.013334274291992],[88.91772651672363,27.32032585144043],[88.89387702941895,26.975553512573242],[89.64305305480957,26.715272903442383],[92.06999397277832,26.8619441986084],[92.11360359191895,27.29749870300293],[91.65776252746582,27.76472282409668],[92.54498481750488,27.861940383911133],[94.64750862121582,29.333459854125977],[95.38777351379395,29.035276412963867],[96.07748603820801,29.46860694885254],[96.39526557922363,29.255277633666992],[96.16914558410645,28.903608322143555],[96.47082710266113,29.056665420532227],[96.61581611633301,28.7902774810791],[96.40193367004395,28.351110458374023],[97.34887886047363,28.2227725982666],[96.88665962219238,27.606107711791992],[97.13665962219238,27.085832595825195],[96.19413948059082,27.27083396911621],[95.1413745880127,26.612497329711914],[95.17804145812988,26.058889389038086],[94.62553596496582,25.397775650024414],[94.73442268371582,25.024721145629883],[94.15109443664551,23.855276107788086],[93.33873176574707,24.077917098999023],[93.19664192199707,22.25638771057129],[92.60081672668457,21.98221778869629],[92.28332710266113,23.70527458190918],[91.94999885559082,23.73221778869629],[91.61360359191895,22.943052291870117],[91.15942573547363,23.640554428100586],[91.37329292297363,24.10194206237793],[92.12137031555176,24.39333152770996],[92.40637397766113,25.030553817749023],[89.84526252746582,25.288610458374023],[89.7391529083252,26.15638542175293],[89.34277534484863,26.017030715942383],[88.43304634094238,26.551389694213867],[88.11053657531738,25.835554122924805],[89.00943183898926,25.288331985473633],[88.4508228302002,25.187776565551758],[88.04332160949707,24.68416404724121],[88.75053596496582,24.220983505249023],[88.56387519836426,23.652219772338867],[88.9861011505127,23.208330154418945],[89.0630054473877,22.115476608276367],[89.00555610656738,21.903608322143555],[89.0888843536377,21.628053665161133],[89.00749397277832,21.600000381469727],[88.85554695129395,21.632776260375977],[88.78442573547363,21.556943893432617],[88.70721626281738,21.566389083862305],[88.66775703430176,22.202219009399414],[88.55693244934082,21.81333351135254],[88.62858772277832,21.749162673950195],[88.57222175598145,21.559999465942383],[88.49609565734863,21.950273513793945],[88.2541675567627,21.548608779907227],[88.19941902160645,22.155275344848633],[87.90776252746582,22.421663284301758],[88.16804695129395,22.091665267944336],[87.79637336730957,21.698884963989258],[86.96331977844238,21.381940841674805],[87.02556037902832,20.674829483032227],[86.42025947570801,19.98277473449707],[85.45138740539551,19.660276412963867],[85.43488502502441,19.88701057434082],[84.10637092590332,18.29222297668457],[82.36442756652832,17.100831985473633],[82.30169868469238,16.58305549621582],[81.3133716583252,16.363332748413086],[81.01727485656738,15.775556564331055],[80.89193916320801,16.02610969543457],[80.82527351379395,15.751943588256836],[80.2794361114502,15.699167251586914],[80.04887580871582,15.048887252807617],[80.31303596496582,13.439165115356445],[80.04942512512207,13.617776870727539],[80.34971809387207,13.334165573120117],[79.76304817199707,11.648889541625977],[79.85971260070801,10.288888931274414],[79.32499885559082,10.280832290649414],[78.90803718566895,9.479719161987305],[79.45138740539551,9.149999618530273],[78.39665412902832,9.089719772338867],[78.06053352355957,8.364164352416992],[77.53610420227051,8.071943283081055],[76.5758228302002,8.876943588256836],[75.68887519836426,11.435277938842773],[74.81025886535645,12.864721298217773],[74.41192817687988,14.483331680297852],[73.44775581359863,16.05583381652832],[72.85386848449707,18.660554885864258],[73.05554389953613,19.011945724487305],[72.76999092102051,18.943052291870117],[72.78055000305176,19.312498092651367],[73.04722785949707,19.217256546020508],[72.66415596008301,19.870832443237305],[72.93441963195801,20.774721145629883],[72.56414985656738,21.378053665161133],[73.13081550598145,21.753610610961914],[72.54165840148926,21.66388511657715],[72.73442268371582,21.98638343811035],[72.50082588195801,21.97666358947754],[72.91914558410645,22.267778396606445],[72.15193367004395,22.28388786315918],[72.11053657531738,21.201940536499023],[70.81888008117676,20.69749641418457],[68.94442939758301,22.294164657592773],[70.1655445098877,22.5483341217041],[70.50694465637207,23.10222053527832],[69.21582221984863,22.84027671813965],[68.43304634094238,23.42999839782715],[68.74136543273926,23.84416389465332],[68.32138252258301,23.58083152770996],[68.19780158996582,23.766687393188477],[68.7472095489502,23.969995498657227],[68.78305244445801,24.33277702331543],[70.01471138000488,24.16971778869629],[71.10582160949707,24.4163875579834],[70.66638374328613,25.698331832885742],[70.08804512023926,25.98277473449707],[70.18359565734863,26.53611183166504],[69.50610542297363,26.754446029663086],[69.58027839660645,27.173330307006836],[70.36831855773926,28.02083396911621],[70.82943916320801,27.706384658813477],[71.89694404602051,27.961942672729492],[73.39749336242676,29.942773818969727],[73.93340492248535,30.136003494262695],[73.87249946594238,30.390100479125977],[74.69458961486816,31.0539608001709],[74.60532569885254,31.877119064331055],[75.38128852844238,32.214242935180664],[74.01638984680176,33.18860054016113],[73.99054145812988,33.74388313293457],[74.29582405090332,33.977487564086914],[73.91331672668457,34.06860542297363],[73.94165229797363,34.64638710021973],[76.86998176574707,34.658884048461914],[77.04248237609863,35.09916114807129],[77.82393074035645,35.50132942199707],[78.07554817199707,35.44582557678223]],[[86.28360176086426,20.038053512573242],[86.27609443664551,20.05000114440918],[86.25139045715332,20.045000076293945],[86.28360176086426,20.038053512573242]]]]}},{"type":"Feature","properties":{"name":"Iran (Islamic Republic of)","iso2":"IR","iso3":"IRN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[54.034439000000106,26.484718],[53.903603,26.536110000000107],[54.0188830000001,26.554165],[54.034439000000106,26.484718]]],[[[53.31805400000016,26.79777500000013],[53.203323,26.802498000000114],[53.151657,26.846386],[53.31805400000016,26.79777500000013]]],[[[56.346657,26.822220000000144],[56.34388,26.884163],[56.4086,26.885551],[56.346657,26.822220000000144]]],[[[55.734993,26.838051000000135],[55.63276700000014,26.794720000000112],[55.688599,26.929161],[55.734993,26.838051000000135]]],[[[56.24527000000015,26.927494],[55.283607,26.558609],[55.769989,26.792774],[55.75222000000011,26.951939],[56.24527000000015,26.927494]]],[[[56.470825,27.037777],[56.434715,27.086941],[56.469986,27.108608000000103],[56.509163,27.071663],[56.470825,27.037777]]],[[[50.32888000000017,29.20805],[50.291382,29.278053],[50.338326,29.268887],[50.32888000000017,29.20805]]],[[[45.004433,39.416382],[46.1782460000002,38.841148],[46.54037500000018,38.875587],[47.976662,39.719231],[48.359787,39.385216],[48.020821,38.835541],[48.88828300000014,38.442406],[49.10248600000014,37.64304400000013],[50.191376,37.38916000000016],[51.10110500000022,36.728874],[53.943321,36.799995],[53.90564,37.35085300000016],[54.681107,37.443604],[55.442764,38.08610500000013],[57.21221200000011,38.28193700000013],[57.45027200000018,37.939156000000125],[59.338882,37.539162],[60.333054000000146,36.656097000000116],[61.1572110000001,36.649994],[61.27655800000011,35.60724600000013],[60.721657,34.522217],[60.87887600000013,34.319717],[60.50833100000014,34.140274],[60.527771,33.64415700000011],[60.94304700000012,33.51944],[60.582497,33.06610100000013],[60.84388,31.498329],[61.713608,31.383331],[61.8511050000001,31.021111],[60.86859900000016,29.863884],[61.90554800000015,28.554996],[62.78138,28.266941],[62.782494000000185,27.260555],[63.34193400000012,27.122498],[63.17638400000013,26.631107],[61.858047,26.234718],[61.61103100000017,25.197647],[57.3180540000001,25.770832],[56.690544,27.148331],[56.132767,27.160275],[54.794716000000136,26.489994],[53.7477720000002,26.70916],[52.440269,27.640831],[51.430275,27.937775000000116],[50.048607,30.207222],[49.551384,30.0075],[48.98499300000017,30.513054000000167],[48.92054700000014,30.043053000000114],[48.545555,29.96303],[48.032494,30.491383],[48.036385,30.997494000000117],[47.693878,31.00111],[47.864441,31.798607000000104],[47.434158,32.397774000000126],[46.107216,32.967491],[46.181938,33.260277],[45.401054,33.9795680000001],[45.797733,34.91404],[46.171364,35.113411],[45.979988,35.584717],[46.346939000000106,35.817215],[45.405823,35.99082900000012],[44.787338,37.149712],[44.61805,37.727768],[44.223969,37.899151],[44.484154,38.345543],[44.034157,39.3849950000001],[44.4161,39.425262],[44.605820000000136,39.78054],[44.813042,39.630814],[45.004433,39.416382]]]]}},{"type":"Feature","properties":{"name":"Israel","iso2":"IL","iso3":"ISR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[35.25972000000016,31.78722000000012],[35.251663,31.788055000000114],[35.24888600000011,31.808887000000155],[35.25972000000016,31.78722000000012]]],[[[35.623634,33.245728],[35.648888,32.685272],[35.552567,32.394196],[35.282494,32.516937],[34.884995,31.391388],[35.47819500000011,31.497322],[34.97998,29.545753000000147],[34.903801,29.486706],[34.26757800000021,31.216541],[34.33416,31.25972],[34.490547,31.596096000000117],[35.10083,33.093605000000125],[35.623634,33.245728]]]]}},{"type":"Feature","properties":{"name":"Italy","iso2":"IT","iso3":"ITA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[12.127777,47.00166300000011],[12.440554000000134,46.69082600000014],[13.718655,46.526611],[13.383055,46.297218],[13.669167,46.177498],[13.480000000000103,46.011108],[13.919167,45.637497],[13.716944,45.596107],[13.193333,45.778053],[12.281387000000166,45.46804800000017],[12.16111,45.263885],[12.539165,44.961105],[12.245554,44.715828000000116],[12.368332000000123,44.246666],[13.621666,43.553886],[14.016666,42.66999800000015],[14.739721,42.085548000000145],[16.141941,41.914162],[15.932499000000178,41.47805],[18.011665,40.6444400000001],[18.512218,40.13666500000012],[18.349442,39.79193900000014],[17.859165000000132,40.283607],[16.913609000000122,40.44554900000013],[16.486664000000133,39.767494],[17.151108000000193,39.389999],[17.16916700000013,38.963333],[16.59499700000015,38.800827000000154],[16.062496,37.92416400000012],[15.631666000000166,38.011665],[16.2225,38.910828],[15.666666,40.03083],[11.098888,42.39305100000011],[10.107498,44.00750000000015],[8.748888000000136,44.42916100000018],[7.528055,43.788605],[7.662222,44.17083000000012],[6.976388,44.284164],[7.031666000000115,44.831383000000116],[6.61976,45.110138],[7.127777,45.257774],[6.798970000000168,45.78067],[7.038054,45.93193800000013],[7.855742,45.91905200000012],[8.436388000000136,46.463333000000105],[9.036665,45.837776],[9.281944000000124,46.49582700000015],[10.129999000000112,46.22721900000015],[10.050278000000105,46.539993],[10.465277000000128,46.546387],[10.471235,46.871353],[12.127777,47.00166300000011]],[[12.459166,43.896111],[12.509998,43.986938],[12.415798,43.957954],[12.459166,43.896111]],[[12.445090330888661,41.90311752178489],[12.456660170953796,41.901426024699205],[12.45165333958056,41.907989033391274],[12.445090330888661,41.90311752178489]]],[[[12.422777,45.420555],[12.323610000000144,45.343887],[12.373333,45.42805500000013],[12.422777,45.420555]]],[[[9.844166,43.03443900000012],[9.80694400000013,43.00972],[9.804165,43.063889],[9.8316650000001,43.07555400000011],[9.844166,43.03443900000012]]],[[[10.441111,42.84444400000011],[10.423054000000121,42.708885],[10.101944000000174,42.772499],[10.441111,42.84444400000011]]],[[[10.088333,42.57222],[10.081944000000135,42.618889],[10.101665,42.593605],[10.088333,42.57222]]],[[[10.915833000000134,42.325272],[10.866388,42.35860400000011],[10.877777000000123,42.388054],[10.915833000000134,42.325272]]],[[[10.316666000000112,42.3174970000001],[10.293055,42.349998],[10.326111,42.34333],[10.316666000000112,42.3174970000001]]],[[[9.513332,41.14666],[9.825832000000105,40.526108],[9.569166000000166,39.15055100000011],[9.018332,39.266388],[8.859165000000132,38.879166],[8.406944,38.958611],[8.556665,39.86610400000016],[8.192499,40.913605],[9.513332,41.14666]]],[[[8.339167,41.06249200000012],[8.215277,40.992493],[8.321110000000147,41.121384],[8.339167,41.06249200000012]]],[[[12.964167000000145,40.883888],[12.950277000000199,40.91777],[12.988054,40.931389000000124],[12.964167000000145,40.883888]]],[[[13.951387000000182,40.701385000000144],[13.853888,40.734718],[13.948055000000181,40.742493],[13.951387000000182,40.701385000000144]]],[[[14.210554,40.560555],[14.261944,40.55555],[14.197222000000124,40.536659000000114],[14.210554,40.560555]]],[[[8.292221,39.09360500000018],[8.223888,39.164719],[8.302776,39.189995],[8.292221,39.09360500000018]]],[[[15.21361,38.770554],[15.190277,38.79055],[15.239166,38.806107],[15.21361,38.770554]]],[[[13.17333200000013,38.690277],[13.162222,38.714439],[13.198332000000136,38.711388],[13.17333200000013,38.690277]]],[[[14.868332000000152,38.531387],[14.794722,38.567772],[14.86861,38.57804900000012],[14.868332000000152,38.531387]]],[[[14.955276,38.445549000000184],[14.912222,38.516663],[14.96388800000011,38.517494],[14.955276,38.445549000000184]]],[[[14.988888,38.36416600000014],[14.941111,38.399437000000106],[14.958887,38.431107],[14.988888,38.36416600000014]]],[[[15.528889,38.13694],[15.086666,37.47943900000011],[15.316666,37.008888],[15.081388000000118,36.649162],[12.422222,37.796104],[13.316666,38.21833],[13.768888,37.970551],[15.528889,38.13694]]],[[[12.073889000000179,37.953606],[12.029999,37.986938],[12.059166,37.98916600000014],[12.073889000000179,37.953606]]],[[[12.354166,37.906105],[12.271387000000175,37.936386],[12.339167,37.934441],[12.354166,37.906105]]],[[[12.015833,36.738327],[11.93083200000018,36.82972],[12.048332,36.796944],[12.015833,36.738327]]]]}},{"type":"Feature","properties":{"name":"Cote d'Ivoire","iso2":"CI","iso3":"CIV"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-3.102272,5.109545000000125],[-3.103041,5.085022],[-3.168334,5.117222],[-3.102272,5.109545000000125]]],[[[-4.787278,5.1683120000001],[-4.146389,5.277222],[-4.004445,5.231667],[-4.787278,5.1683120000001]]],[[[-4.787278,5.1683120000001],[-5.319723,5.230833],[-5.002929,5.129237],[-7.525402,4.352806000000101],[-7.423334,5.839444],[-8.606383999999878,6.507815],[-8.308334,6.860833000000113],[-8.469749,7.561325],[-7.946838,8.018505],[-8.198056999999892,8.496666],[-7.646536,8.378416],[-7.957778,8.813332],[-7.732779,9.088055],[-8.143612,9.533888000000104],[-7.973984,10.165611],[-7.635555999999895,10.448332000000107],[-6.988056,10.147499],[-6.243402,10.735256],[-6.111389,10.197777],[-5.51985,10.436272],[-4.704445,9.698055],[-3.633611,9.954443000000111],[-2.685561,9.481817],[-2.487778,8.197777000000116],[-3.249166999999886,6.611388],[-2.764445,5.579166],[-2.928128,5.100222],[-3.1425,5.367777],[-3.29722299999986,5.118055],[-4.004168,5.253611],[-3.807778,5.375555000000119],[-4.787278,5.1683120000001]]]]}},{"type":"Feature","properties":{"name":"Iraq","iso2":"IQ","iso3":"IRQ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[45.797733,34.91404],[45.401054,33.9795680000001],[46.181938,33.260277],[46.107216,32.967491],[47.434158,32.397774000000126],[47.864441,31.798607000000104],[47.693878,31.00111],[48.036385,30.997494000000117],[48.032494,30.491383],[48.545555,29.96303],[48.54332,29.926662],[48.443047,29.927498],[48.158875,30.038052],[47.943474,30.017555],[47.9310990000001,30.018887],[47.169991,30.015270000000115],[46.546944,29.104198],[44.72166100000018,29.198330000000126],[42.084999,31.11166000000013],[40.41333,31.94833],[39.196743,32.154942],[38.794701,33.377594],[41.003876,34.419434],[41.290276,36.355553],[42.355614,37.106926],[42.790825000000126,37.384720000000144],[44.116379,37.316376],[44.317215,36.970543],[44.787338,37.149712],[45.405823,35.99082900000012],[46.346939000000106,35.817215],[45.979988,35.584717],[46.171364,35.113411],[45.797733,34.91404]]]]}},{"type":"Feature","properties":{"name":"Japan","iso2":"JP","iso3":"JPN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[153.958589553833,24.295000076293945],[153.93969917297363,24.300832748413086],[153.95276069641113,24.321386337280273],[153.958589553833,24.295000076293945]]],[[[123.87082099914551,24.252500534057617],[123.67886543273926,24.316110610961914],[123.92192268371582,24.371110916137695],[123.87082099914551,24.252500534057617]]],[[[122.99693489074707,24.438886642456055],[122.93525886535645,24.458051681518555],[123.00943183898926,24.46693992614746],[122.99693489074707,24.438886642456055]]],[[[131.26416206359863,24.45499610900879],[131.243013381958,24.48444175720215],[131.27359199523926,24.475828170776367],[131.26416206359863,24.45499610900879]]],[[[124.26165962219238,24.45749855041504],[124.21914863586426,24.335275650024414],[124.0758228302002,24.424718856811523],[124.32443428039551,24.587499618530273],[124.26165962219238,24.45749855041504]]],[[[141.30914497375488,24.7480525970459],[141.2902545928955,24.77805519104004],[141.35745429992676,24.788888931274414],[141.30914497375488,24.7480525970459]]],[[[125.35637092590332,24.77666664123535],[125.45110511779785,24.739717483520508],[125.2572193145752,24.729162216186523],[125.2633228302002,24.884164810180664],[125.35637092590332,24.77666664123535]]],[[[141.29358100891113,25.4183292388916],[141.26831245422363,25.445276260375977],[141.29358100891113,25.451387405395508],[141.29358100891113,25.4183292388916]]],[[[131.24383735656738,25.816667556762695],[131.20800971984863,25.83333396911621],[131.250825881958,25.872220993041992],[131.24383735656738,25.816667556762695]]],[[[126.76193428039551,26.38694190979004],[126.78720283508301,26.296945571899414],[126.69220161437988,26.36055564880371],[126.76193428039551,26.38694190979004]]],[[[142.17776679992676,26.622499465942383],[142.11136054992676,26.715272903442383],[142.1530475616455,26.687219619750977],[142.17776679992676,26.622499465942383]]],[[[128.252779006958,26.638887405395508],[127.65277290344238,26.08305549621582],[127.88388252258301,26.667497634887695],[128.287202835083,26.854997634887695],[128.252779006958,26.638887405395508]]],[[[142.23245429992676,27.033334732055664],[142.178316116333,27.07527732849121],[142.23330879211426,27.08916664123535],[142.23245429992676,27.033334732055664]]],[[[142.19470405578613,27.148332595825195],[142.17859077453613,27.15666389465332],[142.19412422180176,27.19110679626465],[142.19470405578613,27.148332595825195]]],[[[140.878023147583,27.225828170776367],[140.86413764953613,27.21944236755371],[140.87219429016113,27.243051528930664],[140.878023147583,27.225828170776367]]],[[[128.60913276672363,27.358888626098633],[128.52359199523926,27.413610458374023],[128.70190620422363,27.445829391479492],[128.60913276672363,27.358888626098633]]],[[[142.1955280303955,27.599164962768555],[142.16998481750488,27.624719619750977],[142.19330024719238,27.61777687072754],[142.1955280303955,27.599164962768555]]],[[[142.08914375305176,27.717775344848633],[142.06884956359863,27.72666358947754],[142.08691596984863,27.73221778869629],[142.08914375305176,27.717775344848633]]],[[[128.95108222961426,27.67582893371582],[128.9474811553955,27.907499313354492],[129.02997016906738,27.774442672729492],[128.95108222961426,27.67582893371582]]],[[[129.33609199523926,28.07527732849121],[129.21911811828613,28.097776412963867],[129.19107246398926,28.188608169555664],[129.33609199523926,28.07527732849121]]],[[[129.99218940734863,28.281667709350586],[129.91497993469238,28.296110153198242],[130.02746772766113,28.36638832092285],[129.99218940734863,28.281667709350586]]],[[[129.71551704406738,28.451108932495117],[129.37552070617676,28.11527442932129],[129.14358711242676,28.250276565551758],[129.71551704406738,28.451108932495117]]],[[[129.73303413391113,29.60972023010254],[129.70608711242676,29.647497177124023],[129.74133491516113,29.663331985473633],[129.73303413391113,29.60972023010254]]],[[[129.89636421203613,29.87416648864746],[129.92190742492676,29.819719314575195],[129.851900100708,29.85222053527832],[129.89636421203613,29.87416648864746]]],[[[129.96301460266113,29.95722007751465],[129.9274616241455,29.97443962097168],[129.92859077453613,30.000001907348633],[129.96301460266113,29.95722007751465]]],[[[130.55859565734863,30.23638343811035],[130.38272285461426,30.393888473510742],[130.66638374328613,30.381940841674805],[130.55859565734863,30.23638343811035]]],[[[140.33026313781738,30.462495803833008],[140.30304145812988,30.47527503967285],[140.32913398742676,30.479162216186523],[140.33026313781738,30.462495803833008]]],[[[130.906099319458,30.354719161987305],[130.86941719055176,30.469717025756836],[131.05359077453613,30.84027671813965],[130.906099319458,30.354719161987305]]],[[[129.72134590148926,31.632219314575195],[129.67053413391113,31.6583309173584],[129.78274726867676,31.793333053588867],[129.72134590148926,31.632219314575195]]],[[[140.02554512023926,31.933053970336914],[139.99939155578613,31.942495346069336],[140.00970649719238,31.946664810180664],[140.02554512023926,31.933053970336914]]],[[[130.15774726867676,32.10888862609863],[130.11636543273926,32.21666145324707],[130.1955280303955,32.17694282531738],[130.15774726867676,32.10888862609863]]],[[[130.36941719055176,32.374711990356445],[130.20941352844238,32.44304847717285],[130.44803047180176,32.50527381896973],[130.36941719055176,32.374711990356445]]],[[[130.02997016906738,32.19499397277832],[130.1571979522705,32.54361152648926],[130.208589553833,32.33499336242676],[130.02997016906738,32.19499397277832]]],[[[128.90081977844238,32.64305305480957],[128.60107612609863,32.618600845336914],[128.66079902648926,32.781938552856445],[128.90081977844238,32.64305305480957]]],[[[139.841646194458,33.03499794006348],[139.74356269836426,33.13804817199707],[139.86413764953613,33.10166358947754],[139.841646194458,33.03499794006348]]],[[[129.10052680969238,32.97860145568848],[129.05554389953613,32.81638526916504],[129.11773872375488,33.14554786682129],[129.10052680969238,32.97860145568848]]],[[[129.39221382141113,33.16471290588379],[129.45413398742676,33.33166694641113],[129.56469917297363,33.38694190979004],[129.39221382141113,33.16471290588379]]],[[[132.2760944366455,33.75943946838379],[132.1855182647705,33.783334732055664],[132.23053169250488,33.79527473449707],[132.2760944366455,33.75943946838379]]],[[[129.75470161437988,33.726938247680664],[129.65887641906738,33.74499702453613],[129.7016315460205,33.856943130493164],[129.75470161437988,33.726938247680664]]],[[[139.61828804016113,33.83221626281738],[139.5827350616455,33.84360694885254],[139.60107612609863,33.887773513793945],[139.61828804016113,33.83221626281738]]],[[[132.32608222961426,33.89471626281738],[132.184419631958,33.90749549865723],[132.4516315460205,33.92276954650879],[132.32608222961426,33.89471626281738]]],[[[131.21414375305176,33.59554481506348],[131.66971015930176,33.64749336242676],[131.51638984680176,33.26555061340332],[131.90277290344238,33.25694465637207],[131.98941230773926,32.83055305480957],[131.34301948547363,31.37388801574707],[130.66638374328613,30.99666404724121],[130.80859565734863,31.68416404724121],[130.53442573547363,31.528886795043945],[130.63553047180176,31.178884506225586],[130.22802925109863,31.248884201049805],[130.16247749328613,32.00694465637207],[130.56970405578613,32.44249153137207],[130.58746528625488,32.63193702697754],[130.44607734680176,32.62054634094238],[130.60553169250488,32.79138374328613],[130.21109199523926,33.17083168029785],[130.34607124328613,32.664438247680664],[129.7460651397705,32.561105728149414],[129.67553901672363,33.06999397277832],[129.94412422180176,32.99249458312988],[129.57885932922363,33.35360908508301],[130.69079780578613,33.93582344055176],[131.21414375305176,33.59554481506348]],[[129.83331489562988,33.34110450744629],[129.86108589172363,33.37555122375488],[129.81360054016113,33.397775650024414],[129.83331489562988,33.34110450744629]]],[[[139.5260944366455,34.03249549865723],[139.48217964172363,34.06999397277832],[139.5605182647705,34.10610389709473],[139.5260944366455,34.03249549865723]]],[[[132.54553413391113,34.11110877990723],[132.557466506958,34.061105728149414],[132.456636428833,34.08693885803223],[132.52887153625488,34.18249702453613],[132.54553413391113,34.11110877990723]]],[[[132.44885444641113,34.115549087524414],[132.38553047180176,34.243608474731445],[132.4819049835205,34.27916145324707],[132.44885444641113,34.115549087524414]]],[[[132.97107124328613,34.18582344055176],[133.02969551086426,34.29110908508301],[133.05053901672363,34.20971870422363],[132.97107124328613,34.18582344055176]]],[[[129.236909866333,34.08221626281738],[129.21747016906738,34.32193946838379],[129.34939765930176,34.27999305725098],[129.236909866333,34.08221626281738]]],[[[134.22357368469238,34.344438552856445],[134.75305366516113,33.82610511779785],[134.18774604797363,33.23832893371582],[133.5988483428955,33.50139045715332],[132.80304145812988,32.735551834106445],[132.37246894836426,33.466386795043945],[132.01581001281738,33.33721351623535],[132.8991413116455,34.10777473449707],[133.5241413116455,33.961381912231445],[134.22357368469238,34.344438552856445]]],[[[139.27887153625488,34.32110786437988],[139.24856758117676,34.35083198547363],[139.29608345031738,34.41971778869629],[139.27887153625488,34.32110786437988]]],[[[134.3508014678955,34.43443489074707],[134.19275093078613,34.50999641418457],[134.36856269836426,34.55027198791504],[134.3508014678955,34.43443489074707]]],[[[134.7902545928955,34.19332313537598],[134.66693305969238,34.296945571899414],[135.0180377960205,34.5927677154541],[134.7902545928955,34.19332313537598]]],[[[129.33996772766113,34.29471778869629],[129.3002643585205,34.55694007873535],[129.46386909484863,34.68943214416504],[129.33996772766113,34.29471778869629]]],[[[139.45331001281738,34.672494888305664],[139.369966506958,34.69249153137207],[139.37161445617676,34.78166389465332],[139.45331001281738,34.672494888305664]]],[[[133.0705280303955,35.99027442932129],[133.02221870422363,35.99138069152832],[133.01080513000488,36.01444435119629],[133.0705280303955,35.99027442932129]]],[[[133.0988483428955,36.02999305725098],[133.0746784210205,36.07999610900879],[133.13189888000488,36.10000038146973],[133.0988483428955,36.02999305725098]]],[[[133.00219917297363,36.03305244445801],[132.95303535461426,36.06638526916504],[133.0866413116455,36.12388038635254],[133.00219917297363,36.03305244445801]]],[[[133.29193305969238,36.32499885559082],[133.37857246398926,36.20054817199707],[133.25247383117676,36.15249061584473],[133.29193305969238,36.32499885559082]]],[[[137.057466506958,37.14305305480957],[136.95413398742676,37.089433670043945],[136.9111042022705,37.143327713012695],[137.057466506958,37.14305305480957]]],[[[138.43524360656738,38.047494888305664],[138.21829414367676,37.80082893371582],[138.51638984680176,38.32027626037598],[138.43524360656738,38.047494888305664]]],[[[141.27081489562988,41.34249305725098],[142.06970405578613,39.54666328430176],[141.52581977844238,38.26638984680176],[140.9535846710205,38.14805030822754],[140.97552680969238,36.98777198791504],[140.565523147583,36.24749183654785],[140.83719062805176,35.74332618713379],[140.3346881866455,35.13138008117676],[139.77026557922363,34.953325271606445],[139.96856880187988,35.66082191467285],[139.67663764953613,35.135271072387695],[139.17108345031738,35.23610877990723],[138.84747505187988,34.59249305725098],[138.744966506958,35.12276649475098],[138.21414375305176,34.59916114807129],[137.0361042022705,34.564714431762695],[137.34747505187988,34.72221565246582],[136.87774848937988,34.72027015686035],[136.84692573547363,35.07833290100098],[136.51944160461426,34.69249153137207],[136.8991413116455,34.26693916320801],[136.343843460083,34.189714431762695],[135.77221870422363,33.45499610900879],[135.06329536437988,33.87777137756348],[135.333589553833,34.71832466125488],[132.36773872375488,34.35860633850098],[132.05053901672363,33.77249336242676],[131.74579048156738,34.053606033325195],[130.89331245422363,33.92166328430176],[130.94635200500488,34.41638374328613],[131.40555000305176,34.419443130493164],[133.08801460266113,35.58166694641113],[136.07275581359863,35.64860725402832],[135.95941352844238,35.97332191467285],[136.71246528625488,36.75139045715332],[136.78692817687988,37.36221504211426],[137.35635566711426,37.504716873168945],[137.35522651672363,37.43138313293457],[137.03747749328613,37.18194007873535],[136.9213581085205,37.197214126586914],[136.86328315734863,37.08777046203613],[137.3024616241455,36.74638557434082],[138.5805377960205,37.39860725402832],[139.424409866333,38.15165901184082],[140.02276802062988,39.37860298156738],[140.0383014678955,39.803049087524414],[139.70245552062988,39.93194007873535],[140.02054023742676,40.23082160949707],[139.8527545928955,40.60110664367676],[140.26886177062988,40.806657791137695],[140.34857368469238,41.24804878234863],[140.72497749328613,40.82916450500488],[141.14941596984863,40.86221504211426],[141.228853225708,41.229990005493164],[140.763032913208,41.17276954650879],[140.91885566711426,41.53027534484863],[141.27081489562988,41.34249305725098]]],[[[139.56302070617676,42.22860145568848],[139.428316116333,42.061662673950195],[139.4333209991455,42.20193672180176],[139.56302070617676,42.22860145568848]]],[[[145.290864944458,43.53866004943848],[145.22000312805176,43.60255241394043],[145.36108589172363,43.555551528930664],[145.290864944458,43.53866004943848]]],[[[143.97024726867676,44.1411075592041],[143.87774848937988,44.147775650024414],[143.81192207336426,44.16805458068848],[143.97024726867676,44.1411075592041]]],[[[141.25943183898926,45.09804725646973],[141.13470649719238,45.213884353637695],[141.3083209991455,45.18888282775879],[141.25943183898926,45.09804725646973]]],[[[142.0483112335205,45.40471076965332],[143.77221870422363,44.09415626525879],[144.77942085266113,43.9133243560791],[145.34247016906738,44.34415626525879],[145.06997871398926,43.77471351623535],[145.25610542297363,43.31499671936035],[145.82220649719238,43.36944007873535],[143.98968696594238,42.90665626525879],[143.2399616241455,41.92416572570801],[141.79052925109863,42.60638618469238],[140.98608589172363,42.295000076293945],[140.4616413116455,42.56777381896973],[140.28497505187988,42.25305366516113],[141.19912910461426,41.7983341217041],[140.06970405578613,41.41916084289551],[139.83636665344238,42.61527442932129],[140.52887153625488,43.00055122375488],[140.4677448272705,43.36721229553223],[141.4071979522705,43.29138374328613],[141.797212600708,44.6249942779541],[141.57803535461426,45.232492446899414],[142.0483112335205,45.40471076965332]]],[[[141.03943061828613,45.26693916320801],[140.97357368469238,45.46527290344238],[141.07440376281738,45.41415596008301],[141.03943061828613,45.26693916320801]]]]}},{"type":"Feature","properties":{"name":"Jamaica","iso2":"JM","iso3":"JAM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-77.131958,17.878887],[-77.733337,17.84861],[-78.339737,18.362499],[-76.945282,18.394444],[-76.221115,17.904163],[-77.131958,17.878887]]]]}},{"type":"Feature","properties":{"name":"Jordan","iso2":"JO","iso3":"JOR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[34.961388,29.360832],[34.97998,29.545753000000147],[35.47819500000011,31.497322],[35.552567,32.394196],[35.648888,32.685272],[36.837776,32.313606],[38.794701,33.377594],[39.196743,32.154942],[37.005272,31.505554],[38.001389,30.504166],[37.502777,30.00222],[36.743607,29.864719],[36.07,29.188889],[34.961388,29.360832]]]]}},{"type":"Feature","properties":{"name":"Kenya","iso2":"KE","iso3":"KEN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[41.13805400000015,-2.124444],[40.950272,-2.173611],[41.0638890000001,-2.044167],[41.13805400000015,-2.124444]]],[[[35.940552,4.622499],[37.039719,4.375555000000134],[38.121109,3.611666],[39.524437,3.406389],[40.783768,4.287975],[41.171387,3.9425],[41.905167,3.980322],[40.98659500000011,2.829956],[40.998329,-0.866111],[41.558159,-1.674868],[41.31527700000018,-1.958056],[40.891663,-2.019167],[40.96360800000011,-2.298889],[40.854996000000114,-2.236111],[40.638054,-2.55],[40.236664000000104,-2.663333],[39.20302600000011,-4.669618],[37.613609,-3.504167],[37.602776,-2.995833],[33.920273,-1.001111],[33.907219,0.103056],[35.0097200000001,1.895278],[34.463333,3.671389],[33.996666,4.222777000000136],[34.388191,4.609682],[35.940552,4.622499]]]]}},{"type":"Feature","properties":{"name":"Kyrgyzstan","iso2":"KG","iso3":"KGZ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[80.23402400000012,42.19622],[78.080826,41.04078700000015],[76.873871,41.014107],[76.345825,40.35022],[75.69720500000014,40.29911],[75.5780490000001,40.647995],[74.86026000000018,40.519386],[73.9944310000001,40.046043],[73.655685,39.454826],[72.248596,39.191856],[71.473038,39.6213],[70.997757,39.40094],[69.306091,39.539436],[69.540817,40.131378],[70.498032,39.90683],[70.98204,40.244843],[71.710541,40.145767],[73.173035,40.822998],[72.19548,41.006592],[71.69136,41.556335],[71.418045,41.118553],[70.187195,41.52829],[71.276382,42.195511],[70.97081,42.254669],[71.17109700000012,42.69135300000015],[71.747208,42.823586],[73.5197140000001,42.408005],[73.583878,43.038574],[74.293594,43.216904],[75.664429,42.807457],[79.194702,42.795792],[80.23402400000012,42.19622]]]]}},{"type":"Feature","properties":{"name":"Korea, Democratic People's Republic of","iso2":"KP","iso3":"PRK"},"geometry":{"type":"MultiPolygon","coordinates":[[[[124.8461,39.497215],[124.8891600000002,39.605553000000114],[124.934143,39.60833],[124.8461,39.497215]]],[[[130.6388850000001,42.406937],[130.697418,42.292206],[129.699402,41.648605],[129.70941200000013,40.829994],[127.506943,39.724709000000175],[127.393051,39.200829],[128.3635560000001,38.62524400000011],[128.07995600000018,38.311935],[127.106087,38.287498000000156],[126.688492,37.83390800000011],[125.589157,38.027214],[125.724426,37.91082],[125.342758,37.67137900000013],[125.512207,37.88694],[124.980553,37.924438],[125.268051,38.072769],[124.66470300000017,38.121101],[124.993591,38.58832600000012],[125.65332000000015,38.62721300000011],[125.139977,38.79638700000014],[125.44831800000011,39.576385],[125.12303200000011,39.557213],[124.744431,39.776939],[124.624153,39.594994],[124.3735960000001,40.09362],[126.016937,40.899994],[126.91304000000022,41.796104],[128.155823,41.382492],[128.05886800000016,42.00332600000014],[128.925812,42.024437],[129.71191400000012,42.444153],[129.907532,43.005821],[130.6043700000001,42.42186],[130.6388850000001,42.406937]]]]}},{"type":"Feature","properties":{"name":"Kiribati","iso2":"KI","iso3":"KIR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-151.78363,-11.466391],[-151.808044,-11.449722],[-151.814453,-11.392502],[-151.78363,-11.466391]]],[[[-152.391418,-10.105278],[-152.406708,-10.097221],[-152.395599,-10.095835],[-152.391418,-10.105278]]],[[[-150.224152,-9.954166],[-150.233063,-9.938614],[-150.220551,-9.923891],[-150.224152,-9.954166]]],[[[-150.225281,-9.915834],[-150.228882,-9.890835],[-150.219177,-9.901392],[-150.225281,-9.915834]]],[[[-155.878052,-5.64],[-155.92807,-5.61889],[-155.85614,-5.619445],[-155.878052,-5.64]]],[[[-172.1875,-4.531668],[-172.231384,-4.504446],[-172.196381,-4.491944],[-172.1875,-4.531668]]],[[[-171.231689,-4.46139],[-171.264496,-4.446388],[-171.235535,-4.438055],[-171.231689,-4.46139]]],[[[-154.939209,-4.045555],[-154.95639,-4.102501],[-155.016113,-4.060834],[-154.939209,-4.045555]]],[[[-171.078064,-3.141667],[-171.089722,-3.137501],[-171.086426,-3.108889],[-171.078064,-3.141667]]],[[[-171.627808,-2.8325],[-171.626373,-2.869445],[-171.725586,-2.772778],[-171.627808,-2.8325]]],[[[176.848297,-2.669445],[176.774139,-2.607778],[176.833313,-2.633889],[176.848297,-2.669445]]],[[[175.971893,-2.505],[175.960236,-2.505834],[175.964417,-2.481111],[175.971893,-2.505]]],[[[175.58609,-1.919722],[175.54776,-1.821667],[175.592743,-1.883333],[175.58609,-1.919722]]],[[[175.53137200000012,-1.806111],[175.493561,-1.769722],[175.519714,-1.777778],[175.53137200000012,-1.806111]]],[[[175.041931,-1.5525],[175.001648,-1.528611],[175.046082,-1.434722],[175.041931,-1.5525]]],[[[174.873291,-1.408056],[174.85745199999988,-1.408611],[174.8535769999999,-1.399167],[174.873291,-1.408056]]],[[[176.46469100000022,-1.435278],[176.390533,-1.324445],[176.421356,-1.348333],[176.46469100000022,-1.435278]]],[[[175.954681,-1.279167],[176.018311,-1.389444],[175.934143,-1.3025],[175.954681,-1.279167]]],[[[174.767761,-1.255833],[174.71637,-1.14],[174.767212,-1.207222],[174.767761,-1.255833]]],[[[174.489685,-0.816667],[174.458008,-0.653611],[174.495789,-0.770278],[174.489685,-0.816667]]],[[[174.458862,-0.651667],[174.377167,-0.5975],[174.392487,-0.594722],[174.458862,-0.651667]]],[[[173.618011,0.133611],[173.604126,0.2125],[173.631622,0.216667],[173.618011,0.133611]]],[[[173.40969800000013,0.203611],[173.402191,0.233056],[173.425537,0.215278],[173.40969800000013,0.203611]]],[[[173.38497900000013,0.244167],[173.371338,0.250278],[173.376617,0.266111000000123],[173.38497900000013,0.244167]]],[[[173.931915,0.298055],[173.923584,0.302222],[173.93942300000012,0.320833],[173.931915,0.298055]]],[[[173.830536,0.448333],[173.921631,0.379722],[173.804962,0.431111],[173.830536,0.448333]]],[[[173.021912,1.006667],[173.084137,0.951944000000125],[172.981354,0.821667],[173.021912,1.006667]]],[[[172.93969700000017,1.336111000000116],[172.914154,1.346389],[172.943573,1.345833],[172.93969700000017,1.336111000000116]]],[[[173.126617,1.349166],[173.09857200000013,1.351389],[173.11911,1.373333],[173.126617,1.349166]]],[[[173.062195,1.410278000000119],[173.039703,1.417778],[173.0346980000002,1.444444],[173.062195,1.410278000000119]]],[[[173.012756,1.472500000000153],[173.016388,1.465],[172.99719200000013,1.500556],[173.012756,1.472500000000153]]],[[[172.981903,1.529444000000112],[172.960785,1.553333000000137],[172.955231,1.619166],[172.981903,1.529444000000112]]],[[[172.88470500000014,1.838333],[172.834137,1.863611],[172.85800200000014,1.861666],[172.88470500000014,1.838333]]],[[[173.014984,1.706111000000135],[172.929962,1.936111],[173.027191,1.821111],[173.014984,1.706111000000135]]],[[[172.891663,1.93],[172.8827210000002,1.932777],[172.8855290000001,1.943889000000112],[172.891663,1.93]]],[[[173.328857,1.940278],[173.311096,1.958055],[173.349396,1.965833],[173.328857,1.940278]]],[[[173.343018,1.982777],[173.313599,1.973889],[173.325256,2.015833],[173.343018,1.982777]]],[[[-157.431671,2.021388000000115],[-157.179443,1.714444],[-157.571381,1.858888],[-157.431671,2.021388000000115]]],[[[172.870239,3.064444],[172.774994,3.002222],[172.749115,3.024166],[172.870239,3.064444]]],[[[172.9682920000001,3.24861],[172.95745800000012,3.281388],[172.97662400000016,3.296389],[172.9682920000001,3.24861]]],[[[-159.340027,3.920833],[-159.271698,3.789722],[-159.40448,3.864166],[-159.340027,3.920833]]],[[[-160.394745,4.685554],[-160.405609,4.725276],[-160.37973,4.718332],[-160.394745,4.685554]]]]}},{"type":"Feature","properties":{"name":"Korea, Republic of","iso2":"KR","iso3":"KOR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[126.622208,33.23999],[126.158333,33.314713],[126.898041,33.52332300000013],[126.622208,33.23999]]],[[[126.7655490000001,34.280823],[126.651382,34.316101],[126.701393,34.38694],[126.7655490000001,34.280823]]],[[[127.213608,34.418884],[127.111366,34.460274],[127.222717,34.48362700000011],[127.213608,34.418884]]],[[[127.790817,34.47637900000011],[127.711929,34.5266570000001],[127.77082800000014,34.5383300000001],[127.790817,34.47637900000011]]],[[[126.186653,34.351387],[126.243317,34.573326],[126.380257,34.494713],[126.186653,34.351387]]],[[[127.803864,34.575554],[127.734421,34.613327],[127.76805100000016,34.66415400000015],[127.803864,34.575554]]],[[[125.991364,34.668053],[125.91499300000012,34.692215],[125.981369,34.716934],[125.991364,34.668053]]],[[[125.993042,34.791939],[126.009163,34.759995],[125.890549,34.728043],[125.993042,34.791939]]],[[[128.085785,34.830276],[127.974152,34.85833],[128.024139,34.913879],[128.085785,34.830276]]],[[[126.063599,34.854439],[125.983597,34.864998],[126.06275900000011,34.928329],[126.063599,34.854439]]],[[[127.9561,34.800827],[128.060791,34.701103],[127.857208,34.723877],[127.879967,34.92943600000011],[127.9561,34.800827]]],[[[128.754425,34.87693800000015],[128.594116,34.697769],[128.488556,34.856384],[128.754425,34.87693800000015]]],[[[126.10608700000014,35.046944],[126.05998200000013,35.090828],[126.162201,35.14332600000016],[126.10608700000014,35.046944]]],[[[126.428307,36.399719],[126.33582300000015,36.438599],[126.346939,36.591103],[126.428307,36.399719]]],[[[126.16943400000017,36.82582900000013],[126.16110200000011,36.838043],[126.172447,36.8368380000001],[126.16943400000017,36.82582900000013]]],[[[130.887482,37.453323],[130.807465,37.51832600000013],[130.919434,37.545273],[130.887482,37.453323]]],[[[126.501389,37.594437],[126.373032,37.621658],[126.400543,37.818886],[126.501389,37.594437]]],[[[124.695534,37.9161000000001],[124.615257,37.968597],[124.72554000000011,37.981659],[124.695534,37.9161000000001]]],[[[128.532471,38.330551],[129.433594,37.058884000000106],[129.43942300000018,35.475822],[129.136932,35.11221300000015],[127.593323,34.941658],[127.640823,34.616936],[127.49387400000015,34.851662000000104],[127.389427,34.4711],[127.124687,34.53721600000013],[127.328598,34.74305],[126.889427,34.412491],[126.772491,34.58277100000011],[126.556374,34.300545],[126.266937,34.683327],[126.659714,34.812767000000136],[126.249153,35.11666100000012],[126.431374,35.023323],[126.68775900000017,35.533333],[126.474701,35.635826000000165],[126.872993,36.054718],[126.544418,36.136406],[126.49720800000014,36.723877000000144],[126.1235960000001,36.709160000000125],[126.50248700000012,37.052773],[126.9922030000001,36.91082],[126.661102,37.156097],[126.865807,37.266937],[126.688492,37.83390800000011],[127.106087,38.287498000000156],[128.07995600000018,38.311935],[128.3635560000001,38.62524400000011],[128.532471,38.330551]]]]}},{"type":"Feature","properties":{"name":"Kuwait","iso2":"KW","iso3":"KWT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[48.362488,29.450272],[48.38832900000014,29.395554],[48.266930000000144,29.441109],[48.362488,29.450272]]],[[[48.224709,29.594719],[48.152222,29.991940000000156],[48.359444,29.744999],[48.224709,29.594719]]],[[[48.032219,29.968052],[48.00860600000013,29.973885],[48.037766,30.011105000000114],[48.11166400000016,30.023048],[48.032219,29.968052]]],[[[47.9310990000001,30.018887],[47.943474,30.017555],[48.167213,29.553055],[47.707222,29.37583200000013],[48.028603,29.344994],[48.416588,28.545277],[47.688880999999895,28.538883],[47.4599910000002,28.999439],[46.546944,29.104198],[47.169991,30.015270000000115],[47.9310990000001,30.018887]]]]}},{"type":"Feature","properties":{"name":"Kazakhstan","iso2":"KZ","iso3":"KAZ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[50.116104,44.838043],[49.978867,44.956383],[50.11277,45.077492],[50.116104,44.838043]]],[[[50.291664,44.949997],[50.26554900000022,45.036659],[50.342766,45.08305400000013],[50.291664,44.949997]]],[[[53.024994,46.2286],[52.96027400000011,46.266388],[53.046387,46.367493],[53.097488,46.296661],[53.024994,46.2286]]],[[[69.185532,55.34388000000014],[70.843323,55.301933],[71.27887,54.690269],[70.99693300000015,54.339157],[71.185532,54.10332500000011],[72.19609100000017,54.137497],[72.05165100000013,54.387772],[72.468597,53.908882000000105],[72.61331200000015,54.145271],[73.763885,54.065544000000116],[73.238586,53.64444000000019],[73.437195,53.43610400000016],[74.42915300000018,53.47860000000016],[76.811646,54.447769],[76.521652,53.993881],[77.908035,53.271103],[80.077957,50.75808700000012],[80.687836,51.31472],[81.468048,50.742218],[83.456375,51.00249500000011],[84.363037,50.212212],[85.014435,50.075829000000155],[85.258606,49.591377],[86.19108600000018,49.472488],[86.77499400000013,49.788887],[86.616653,49.587212],[87.348206,49.092621],[86.874695,49.110825000000105],[86.5961,48.53611],[85.75915500000022,48.387772],[85.529312,47.060165],[84.75943,46.826385],[83.040543,47.212212],[82.317764,45.570534],[82.649429,45.43026],[82.561646,45.129417],[81.688309,45.350815],[79.87109400000011,44.904976],[80.520828,44.73247500000012],[80.362762,44.125244],[80.817215,43.156067],[80.37664800000019,43.025238],[80.578598,42.89107500000013],[80.171921,42.660507],[80.23402400000012,42.19622],[79.194702,42.795792],[75.664429,42.807457],[74.293594,43.216904],[73.583878,43.038574],[73.5197140000001,42.408005],[71.747208,42.823586],[71.17109700000012,42.69135300000015],[70.97081,42.254669],[69.05636600000011,41.379433000000105],[68.455261,40.59777100000012],[67.935532,41.183327],[66.7199860000002,41.174995],[66.526382,42.003052],[66.02916,42.003052],[66.123871,42.99694100000012],[65.82193,42.877213],[64.931366,43.73777],[62.025108,43.484787],[58.569717,45.571106],[55.99749,45.001106],[56.000961,41.32845300000015],[55.45694000000017,41.28665900000014],[54.17305,42.337212],[53.014999,42.138885],[52.440071,41.740936],[52.73832700000011,42.710274000000155],[51.26554900000016,43.153046],[50.839989,44.193047],[50.239433,44.576385],[51.57027400000018,44.513885],[50.953049,44.86193800000014],[51.405266,45.37054400000015],[53.228043000000156,45.33776900000011],[52.733047,45.549438],[53.08582300000015,46.007217],[53.164154,46.317215],[52.99665800000017,46.488045],[53.194153,46.714996],[51.189987,47.114716],[49.222527,46.346306000000155],[48.560547,46.564995],[49.027206,46.776093],[48.20443,47.704987000000116],[47.383324,47.688881],[47.122765,48.27166],[46.499161000000214,48.417496],[47.062767,49.142769000000115],[46.79583,49.339714],[46.929436,49.863609],[47.520828,50.436378],[48.251663,49.86971300000012],[48.796944,49.941933000000134],[48.697487,50.591934],[50.77330000000015,51.76918],[51.303047,51.4797130000001],[52.338326,51.782211],[52.603325,51.45694],[53.428604,51.49166100000015],[54.506386,50.856941000000106],[54.523933,50.528839],[54.647217,51.03694200000011],[55.692490000000106,50.532494],[56.510826,51.08332800000012],[57.481934,50.864716],[58.337769,51.156097],[59.542496,50.478325],[60.04361,50.863327],[61.381378,50.783607],[61.685822,51.265831],[60.00222,51.958328],[61.061935000000204,52.342491],[60.694153000000114,52.680824],[61.09915900000013,52.981659],[62.118324000000115,53.004166000000126],[61.184715,53.3066560000001],[61.57749200000015,53.513329],[60.90554800000021,53.62027],[61.226936,53.811935],[61.01416,53.947487],[62.547493,53.879433000000105],[63.172218,54.18637800000012],[65.216385,54.318886],[65.483322,54.6380460000001],[69.185532,55.34388000000014]]]]}},{"type":"Feature","properties":{"name":"Lao People's Democratic Republic","iso2":"LA","iso3":"LAO"},"geometry":{"type":"MultiPolygon","coordinates":[[[[107.5466,14.708618],[106.853592,14.303053],[106.540741,14.598724000000132],[106.004707,14.373053],[106.056641,13.929998],[105.210602,14.349648],[105.536102,14.563332000000116],[105.637772,15.659721],[104.747208,16.528332],[104.71832300000014,17.50333],[103.985527,18.321663],[103.397217,18.434994],[102.683594,17.819996],[102.089394,18.214983000000146],[101.162773,17.459995],[100.921371,17.56721900000015],[101.281097,19.562218],[100.50360100000015,19.526665],[100.58046,20.157768000000104],[100.09137,20.348606],[101.14823900000013,21.572636],[101.281937,21.180275],[101.78720100000012,21.144161],[101.57443200000014,22.20916],[101.738037,22.49694100000012],[102.14074700000012,22.396286],[102.676651,21.65583],[102.976089,21.739437],[103.170532,20.846664],[103.693588,20.657219],[104.109154,20.977219],[104.6436,20.660275000000112],[104.3819270000001,20.444717],[104.979156,20.004997],[104.640266,19.611942],[104.03724700000012,19.69294400000011],[103.87943300000015,19.29361],[105.193863,18.642494],[105.183319,18.334442],[106.561096,16.996941],[106.685532,16.45805],[107.464706,16.078609000000128],[107.1755370000001,15.784164],[107.695251,15.270832],[107.5466,14.708618]]]]}},{"type":"Feature","properties":{"name":"Lebanon","iso2":"LB","iso3":"LBN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[35.623634,33.245728],[35.10083,33.093605000000125],[35.972771,34.647499],[36.459999,34.635277],[36.623741,34.204994],[35.623634,33.245728]]]]}},{"type":"Feature","properties":{"name":"Latvia","iso2":"LV","iso3":"LVA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[21.068607,56.435547],[21.053608,56.83638],[21.73333,57.576942],[22.610275,57.756386],[23.785831,56.970268],[24.407497,57.25666],[24.314980000000105,57.871826],[25.294998000000106,58.084435],[26.511387,57.5261],[27.372059,57.535637],[27.861107,57.302216],[27.70166,56.914711],[28.168011,56.150154],[26.613209,55.674835],[25,56.295547],[22.139439,56.4236070000001],[21.051685,56.077309],[21.068607,56.435547]]]]}},{"type":"Feature","properties":{"name":"Belarus","iso2":"BY","iso3":"BLR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[26.613209,55.674835],[28.168011,56.150154],[30.926247,55.60257],[31.02972,55.043327],[30.781387,54.79361],[31.844162,54.064438],[31.764225,53.80262],[32.741104,53.463051],[31.266941,53.02471200000015],[31.783886,52.108047],[30.94309600000011,52.073792000000125],[30.551414000000108,51.251846],[25.775829000000158,51.939156],[24.396664,51.886658],[23.604633,51.527695],[23.638607,52.079437],[23.1654,52.282276],[23.94083,52.732208],[23.50404,53.947044],[25.785275000000127,54.160545],[25.547497,54.33277100000011],[25.788887,54.870270000000104],[26.81971700000014,55.281105],[26.45583,55.341377],[26.613209,55.674835]]]]}},{"type":"Feature","properties":{"name":"Lithuania","iso2":"LT","iso3":"LTU"},"geometry":{"type":"MultiPolygon","coordinates":[[[[21.044441,55.32638500000017],[20.984814,55.27655],[20.942833,55.287201],[21.089996,55.719986],[21.044441,55.32638500000017]]],[[[25,56.295547],[26.613209,55.674835],[26.45583,55.341377],[26.81971700000014,55.281105],[25.788887,54.870270000000104],[25.547497,54.33277100000011],[25.785275000000127,54.160545],[23.50404,53.947044],[22.785885,54.363838],[22.842495,54.896942],[21.431385,55.251938],[21.263935000000146,55.248985],[21.051685,56.077309],[22.139439,56.4236070000001],[25,56.295547]]]]}},{"type":"Feature","properties":{"name":"Liberia","iso2":"LR","iso3":"LBR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-10.806074,6.403],[-11.492331,6.927091000000132],[-10.266651,8.488377],[-9.48365,8.346931],[-9.485161,7.361989],[-9.106945,7.198889],[-8.660557,7.695],[-8.469749,7.561325],[-8.308334,6.860833000000113],[-8.606383999999878,6.507815],[-7.423334,5.839444],[-7.525402,4.352806000000101],[-9.142778,5.055555],[-10.806074,6.403]]]]}},{"type":"Feature","properties":{"name":"Slovakia","iso2":"SK","iso3":"SVK"},"geometry":{"type":"MultiPolygon","coordinates":[[[[17.251656,48.024994],[17.166386,48.012497],[16.946182,48.619064],[18.851246,49.517357],[19.475555,49.599998],[20.074444,49.175278],[21.618889,49.436386],[22.558052,49.079437],[22.151442,48.411919],[20.660553,48.563332],[18.655277,47.758606],[17.251656,48.024994]]]]}},{"type":"Feature","properties":{"name":"Liechtenstein","iso2":"LI","iso3":"LIE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[9.533569,47.274544],[9.598635,47.063835],[9.474637,47.057457],[9.533569,47.274544]]]]}},{"type":"Feature","properties":{"name":"Libyan Arab Jamahiriya","iso2":"LY","iso3":"LBY"},"geometry":{"type":"MultiPolygon","coordinates":[[[[9.948332,27.824444],[9.766388,29.427776],[9.303888,30.122498],[9.537113,30.23439],[10.21361,30.730831],[10.287222,31.694164],[11.567499,32.442215],[11.526081,33.171135],[15.165833,32.398605],[15.761665,31.385555],[17.370831,31.081665],[19.001389,30.266941],[20.060555,30.855274],[20.084442,32.184715],[21.621387,32.933609],[23.112499,32.6325],[23.247196,32.216225],[24.973888,31.969997],[25.151665,31.646942],[24.706665,30.16861],[24.997776,29.248886],[25.001423,21.999695],[25.000832,19.999119],[24.000832000000116,20.001942],[24.002747,19.499065],[16.000832,23.450554],[14.997889,23.000591],[14.234999,22.614166],[13.543888,23.16861],[11.986475,23.522305],[11.558887,24.302498],[10.252222,24.605831],[9.398333,26.153332],[9.871666,26.514164],[9.948332,27.824444]]]]}},{"type":"Feature","properties":{"name":"Madagascar","iso2":"MG","iso3":"MDG"},"geometry":{"type":"MultiPolygon","coordinates":[[[[49.8336124420166,-17.089723587036133],[49.860551834106445,-16.913890838623047],[50.01055335998535,-16.72555923461914],[49.8336124420166,-17.089723587036133]]],[[[47.2197208404541,-15.436668395996094],[47.207773208618164,-15.434446334838867],[47.2005558013916,-15.427501678466797],[47.20666694641113,-15.420557022094727],[47.21944618225098,-15.420833587646484],[47.2197208404541,-15.436668395996094]]],[[[48.34250068664551,-13.418054580688477],[48.20555305480957,-13.391389846801758],[48.281389236450195,-13.196666717529297],[48.34250068664551,-13.418054580688477]]],[[[49.356943130493164,-12.09083366394043],[49.94333076477051,-13.039445877075195],[50.433610916137695,-15.580001831054688],[50.17277717590332,-15.97972297668457],[49.866106033325195,-15.432500839233398],[49.63360786437988,-15.557500839233398],[49.78860664367676,-16.830280303955078],[47.1330509185791,-24.928058624267578],[45.21472358703613,-25.588336944580078],[44.017221450805664,-24.985279083251953],[43.2388858795166,-22.282501220703125],[43.50055122375488,-21.33388900756836],[44.48221778869629,-19.970279693603516],[43.93721961975098,-17.479446411132812],[44.45916175842285,-16.1844482421875],[46.151384353637695,-15.703611373901367],[46.47722053527832,-15.96611213684082],[46.338335037231445,-15.624723434448242],[46.947221755981445,-15.198890686035156],[46.95944404602051,-15.558055877685547],[47.22361946105957,-15.448465347290039],[47.235647201538086,-15.412919998168945],[47.11194038391113,-15.305557250976562],[47.05832862854004,-15.185001373291016],[47.45499610900879,-14.665279388427734],[47.42721748352051,-15.110555648803711],[47.81127738952637,-14.603889465332031],[48.001665115356445,-14.765556335449219],[47.69944190979004,-14.420557022094727],[48.0483341217041,-14.155555725097656],[47.90527534484863,-13.596389770507812],[48.28721809387207,-13.808055877685547],[48.73971748352051,-13.427223205566406],[48.95944404602051,-12.822223663330078],[48.7308292388916,-12.434167861938477],[49.356943130493164,-12.09083366394043]],[[49.604440689086914,-12.62639045715332],[49.595834732055664,-12.610000610351562],[49.59444618225098,-12.623611450195312],[49.604440689086914,-12.62639045715332]]]]}},{"type":"Feature","properties":{"name":"Martinique","iso2":"MQ","iso3":"MTQ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-60.86084,14.402777],[-61.174728,14.876944],[-60.940834,14.740833],[-60.86084,14.402777]]]]}},{"type":"Feature","properties":{"name":"Mongolia","iso2":"MN","iso3":"MNG"},"geometry":{"type":"MultiPolygon","coordinates":[[[[91.020248,46.600109],[90.074432,47.886383],[88.65332,48.18277000000013],[87.9733120000001,48.57694200000016],[87.840698,49.172951],[92.322769,50.81499500000011],[94.274994,50.569443],[94.63526900000014,50.024437],[97.34082,49.734436],[98.28970300000012,50.293884],[97.82777400000012,51.00110600000012],[98.930267,52.143608],[102.218872,51.333603],[102.327766,50.569717],[102.918587,50.315269],[106.66304,50.3386],[107.977127,49.943626],[107.9491420000002,49.678047],[108.57222,49.33360300000011],[110.788589,49.149437000000106],[113.09082,49.59860200000013],[114.313026,50.284164000000104],[116.7113800000001,49.830467],[115.592194,47.919441000000106],[117.372192,47.653595],[117.80108600000014,48.010551],[118.539337,47.994751],[119.72998,47.16415400000015],[119.89749100000014,46.675552],[117.421097,46.578331],[116.585541,46.29583000000015],[115.701927,45.458603],[114.545258,45.389435],[113.638046,44.74527],[111.98082,45.09166],[111.42137100000011,44.382492],[111.958328,43.692215],[110.440536,42.777771],[109.313599,42.429993000000124],[107.471916,42.466103],[105.012207,41.581383],[100.835541,42.678047],[96.38304100000013,42.731102],[95.336105,44.02082800000015],[95.416656,44.29388400000012],[93.5547030000001,44.957214],[90.896942,45.253052],[90.681931,45.57972],[91.020248,46.600109]]]]}},{"type":"Feature","properties":{"name":"Montserrat","iso2":"MS","iso3":"MSR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-62.171394,16.671387],[-62.236671,16.711941],[-62.20195,16.81361],[-62.171394,16.671387]]]]}},{"type":"Feature","properties":{"name":"The former Yugoslav Republic of Macedonia","iso2":"MK","iso3":"MKD"},"geometry":{"type":"MultiPolygon","coordinates":[[[[20.82111,40.908882],[20.492775,41.331108],[20.589642,41.882187],[22.365276,42.323883],[23.014721,41.762215],[22.935604,41.342125],[20.98349,40.855888],[20.82111,40.908882]]]]}},{"type":"Feature","properties":{"name":"Mali","iso2":"ML","iso3":"MLI"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-8.53388,11.49391],[-9.155556,12.486111],[-9.701946,12.029163],[-10.323893,12.224997],[-10.652748,11.892609],[-10.92889,12.224442],[-11.315556,12.022774],[-11.373058,12.407774],[-11.378056,12.988054],[-12.057222,13.664721],[-12.244833,14.764385],[-11.841391,14.863054],[-11.494167,15.646387],[-10.899637,15.106874],[-10.716387,15.438902000000112],[-9.411112,15.443888],[-9.338057,15.704721000000106],[-9.333612,15.499722000000148],[-5.49505,15.498371],[-5.335,16.328053],[-5.601389,16.507774],[-6.577223,24.999165000000133],[-4.806111,25.000275],[1.169662,21.102543],[1.1675,20.741108],[1.795833,20.308331],[3.233055,19.820274],[3.331944,18.976387],[4.245277,19.146664],[4.245,18.645275],[4.200833,16.393887],[3.523981,15.358152],[1.3125,15.286665],[0.235048,14.915068],[-0.725278,15.082777],[-1.980834,14.474722],[-2.006945,14.187777],[-2.474722,14.287498],[-2.879167,13.655554],[-3.2575,13.696665],[-3.437675,13.166498],[-3.964253,13.50383],[-4.337223,13.121666],[-4.4175,12.300831],[-5.273056,11.843887],[-5.51985,10.436272],[-6.111389,10.197777],[-6.243402,10.735256],[-6.988056,10.147499],[-7.635555999999895,10.448332000000107],[-7.973984,10.165611],[-8.289722,11.007776],[-8.680557,10.966389],[-8.357779,11.305555],[-8.53388,11.49391]]]]}},{"type":"Feature","properties":{"name":"Morocco","iso2":"MA","iso3":"MAR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-9.053169,32.734802],[-6.843056,34.018608],[-5.918744,35.790649],[-5.395557,35.91633600000013],[-5.345834,35.84166000000012],[-4.695834,35.208885],[-2.946945,35.329163],[-2.925278,35.266663],[-2.91472199999987,35.273605],[-2.209445,35.085831],[-1.747222,34.747215],[-1.668056,33.261108],[-1.010278,32.508331],[-1.180556,32.11055],[-2.853889,32.088333],[-3.818334,31.695553],[-3.626667,30.970554],[-4.920556,30.508053],[-5.538334,29.902496],[-7.123889,29.636944],[-8.667223,28.709442],[-8.666668,27.666664],[-13.174961,27.666958],[-11.458057,28.334442],[-10.138056,29.428055],[-9.640278,30.168053],[-9.809168,31.446663],[-9.053169,32.734802]]]]}},{"type":"Feature","properties":{"name":"Mauritius","iso2":"MU","iso3":"MUS"},"geometry":{"type":"MultiPolygon","coordinates":[[[[57.572495000000146,-20.514168],[57.304718,-20.449169],[57.624443,-19.986389],[57.572495000000146,-20.514168]]],[[[63.466385,-19.735836],[63.32860600000012,-19.738056],[63.461105,-19.673058],[63.466385,-19.735836]]],[[[56.564438,-10.397223],[56.511665,-10.346668],[56.51361100000011,-10.316668],[56.564438,-10.397223]]]]}},{"type":"Feature","properties":{"name":"Mauritania","iso2":"MR","iso3":"MRT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-16.42750199999989,19.603611],[-16.460003,19.699718000000146],[-16.344448,19.866386000000105],[-16.42750199999989,19.603611]]],[[[-6.662778,26.129166],[-4.806111,25.000275],[-6.577223,24.999165000000133],[-5.601389,16.507774],[-5.335,16.328053],[-5.49505,15.498371],[-9.333612,15.499722000000148],[-9.338057,15.704721000000106],[-9.411112,15.443888],[-10.716387,15.438902000000112],[-10.899637,15.106874],[-11.494167,15.646387],[-11.841391,14.863054],[-12.244833,14.764385],[-14.345278,16.638611],[-16.280834,16.519722],[-16.527679,16.060249],[-16.039448,17.728054000000114],[-16.51166899999987,19.352219],[-16.19639199999989,20.223053],[-16.919724,21.161663000000104],[-17.05233,20.764095000000125],[-16.953056,21.338333],[-15.741997,21.338284],[-12.999723,21.338055000000125],[-13.105278,22.893055],[-12.000278,23.454441000000102],[-12.000557,26],[-8.666944999999885,26.000275000000116],[-8.66679,27.290459],[-6.662778,26.129166]]]]}},{"type":"Feature","properties":{"name":"Malta","iso2":"MT","iso3":"MLT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[14.562222,35.820274],[14.374998,35.847496],[14.326387000000182,35.978882],[14.562222,35.820274]]],[[[14.2675,36.011383],[14.18111000000016,36.06082900000011],[14.34111,36.033882],[14.2675,36.011383]]]]}},{"type":"Feature","properties":{"name":"Oman","iso2":"OM","iso3":"OMN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[55.874718,17.490833],[55.829163,17.493610000000118],[55.859718,17.516666],[55.874718,17.490833]]],[[[56.024162,17.484165],[55.957497,17.519165],[56.09360500000011,17.514721],[56.024162,17.484165]]],[[[58.84277300000011,20.441109],[58.649719,20.168888],[58.899719,20.693054000000117],[58.84277300000011,20.441109]]],[[[56.037498,24.938889],[56.104164,24.734722000000104],[56.373528,24.979382],[57.16499300000012,23.937775],[58.609444000000195,23.633053000000118],[59.811386,22.226665],[58.515831,20.411663],[58.210831,20.612499],[57.829437,20.218887],[57.803886,18.969444000000138],[56.814484,18.747684],[56.353333000000106,17.934166],[55.436943,17.828888000000134],[55.03999300000012,17.018608],[53.114441,16.642778],[51.99929,18.999344000000136],[55,20],[55.666107,21.999722],[55.199165000000136,22.699718],[55.510277000000116,23.97277500000014],[56.024719,24.076111],[55.7794420000001,24.563889000000145],[56.037498,24.938889]]],[[[56.365368,26.382389],[56.269722,25.636015],[56.183331,25.654989],[56.079941,26.065559],[56.365368,26.382389]]]]}},{"type":"Feature","properties":{"name":"Maldives","iso2":"MV","iso3":"MDV"},"geometry":{"type":"MultiPolygon","coordinates":[[[[73.17637600000015,-0.689722],[73.15637200000012,-0.683889],[73.17192100000014,-0.681667],[73.17637600000015,-0.689722]]],[[[73.201385,-0.680833],[73.188309,-0.684722],[73.20193500000013,-0.667222],[73.201385,-0.680833]]],[[[73.12915000000012,-0.668889],[73.12525900000011,-0.668889],[73.121368,-0.653333],[73.12915000000012,-0.668889]]],[[[73.23082,-0.648056],[73.226089,-0.6325],[73.2422030000001,-0.617778],[73.23082,-0.648056]]],[[[73.1163790000002,-0.635833],[73.09082,-0.606667],[73.09137,-0.5825],[73.1163790000002,-0.635833]]],[[[73.248032,-0.605278],[73.23580900000016,-0.585556],[73.249146,-0.576111],[73.248032,-0.605278]]],[[[73.44693,-0.299444],[73.428314,-0.286389],[73.442474,-0.285278],[73.44693,-0.299444]]],[[[73.106934,0.211944],[73.095535,0.228056],[73.10331700000015,0.228889],[73.106934,0.211944]]],[[[73.214706,0.230833000000118],[73.209152,0.24],[73.22026100000014,0.239167],[73.214706,0.230833000000118]]],[[[73.04498300000014,0.259444],[73.034424,0.261389],[73.033051,0.272778],[73.04498300000014,0.259444]]],[[[73.375809,0.28],[73.367203,0.281389],[73.3797,0.291944],[73.375809,0.28]]],[[[73.51304600000012,0.378333],[73.50471500000012,0.383889],[73.508881,0.3925],[73.51304600000012,0.378333]]],[[[72.943039,0.488611],[72.938034,0.485555],[72.937195,0.499722000000105],[72.943039,0.488611]]],[[[73.498032,0.499722000000105],[73.493042,0.496944000000113],[73.487762,0.508055],[73.498032,0.499722000000105]]],[[[73.374695,1.781667000000141],[73.361374,1.788611],[73.374695,1.79527800000011],[73.374695,1.781667000000141]]],[[[73.399155,1.793889000000107],[73.397766,1.806389],[73.40776100000014,1.805833],[73.399155,1.793889000000107]]],[[[73.28720100000012,1.831944],[73.297211,1.819166],[73.284424,1.823055000000139],[73.28720100000012,1.831944]]],[[[73.50694300000012,1.826667],[73.49498,1.823055000000139],[73.516663,1.847222],[73.50694300000012,1.826667]]],[[[73.25054900000012,1.889166],[73.24192800000012,1.886111],[73.247757,1.898333],[73.25054900000012,1.889166]]],[[[73.549988,1.896389000000141],[73.53997800000016,1.891944],[73.549713,1.937222],[73.549988,1.896389000000141]]],[[[73.55304,1.965],[73.548325,1.964166],[73.54721100000015,1.978333],[73.55304,1.965]]],[[[73.323044,1.985000000000113],[73.3138730000002,1.986388],[73.322495,1.995555],[73.323044,1.985000000000113]]],[[[73.588882,2.1075],[73.559143,2.09611],[73.567764,2.11],[73.588882,2.1075]]],[[[73.123871,2.190555],[73.11026000000012,2.196944],[73.12191800000019,2.196944],[73.123871,2.190555]]],[[[72.930817,2.314444],[72.919983,2.322500000000119],[72.92276000000012,2.328888],[72.930817,2.314444]]],[[[73.366653,2.384444],[73.350266,2.440833000000111],[73.3685909999999,2.409721],[73.366653,2.384444]]],[[[73.319717,2.492499],[73.313599,2.491944],[73.311096,2.504722],[73.319717,2.492499]]],[[[72.876083,2.681388],[72.866379,2.684999],[72.866379,2.69611],[72.876083,2.681388]]],[[[73.025269,2.734444],[73.018875,2.736944],[73.034988,2.747499000000118],[73.025269,2.734444]]],[[[73.356644,2.771666],[73.348877,2.770833],[73.349426,2.781944000000124],[73.356644,2.771666]]],[[[73.0177610000002,2.946944],[73.005829,2.946944],[73.012207,2.954722],[73.0177610000002,2.946944]]],[[[73.5799870000001,2.948888],[73.574432,2.950555],[73.585541,2.967499],[73.5799870000001,2.948888]]],[[[72.98220800000016,3.101944],[72.973877,3.108055],[72.982758,3.110833000000156],[72.98220800000016,3.101944]]],[[[73.587204,3.367777],[73.581665,3.372221],[73.59082,3.376944],[73.587204,3.367777]]],[[[73.753326,3.446388],[73.74775700000012,3.451111000000154],[73.751389,3.452499],[73.753326,3.446388]]],[[[72.80276500000011,3.510278],[72.78804000000011,3.511111],[72.798599,3.516944],[72.80276500000011,3.510278]]],[[[72.92276000000012,3.544167],[72.908035,3.537777000000133],[72.9272,3.559721],[72.92276000000012,3.544167]]],[[[72.69747900000013,3.714166],[72.687759,3.724721],[72.699417,3.724166],[72.69747900000013,3.714166]]],[[[73.47387700000016,3.933055],[73.465546,3.932222],[73.4802700000001,3.940555],[73.47387700000016,3.933055]]],[[[72.70971700000021,3.995555000000138],[72.69775400000017,4.000833],[72.707764,4.003611],[72.70971700000021,3.995555000000138]]],[[[73.512207,4.093611],[73.501938,4.096388],[73.50305200000011,4.106943],[73.512207,4.093611]]],[[[73.503601,4.164165],[73.491089,4.174999],[73.505264,4.17861],[73.503601,4.164165]]],[[[73.5186,4.191387000000134],[73.51915,4.176388],[73.51138300000011,4.182221],[73.5186,4.191387000000134]]],[[[72.959717,4.26861],[72.977768,4.261666],[72.962494,4.262221],[72.959717,4.26861]]],[[[72.96971100000016,4.877776],[72.970261,4.898055],[72.9802700000001,4.901111000000157],[72.96971100000016,4.877776]]],[[[73.589706,5.27361],[73.56694,5.277499],[73.589706,5.286943],[73.589706,5.27361]]],[[[73.320267,5.36111],[73.314987,5.365276],[73.333603,5.366666],[73.320267,5.36111]]],[[[73.635269,5.385555],[73.62025500000013,5.420833000000101],[73.63749700000014,5.412777],[73.635269,5.385555]]],[[[73.3841550000001,5.709722],[73.387772,5.741943],[73.3927610000002,5.72861],[73.3841550000001,5.709722]]],[[[72.99136400000012,5.76111],[72.981659,5.758888],[72.981659,5.771666],[72.99136400000012,5.76111]]],[[[73.436371,5.827222],[73.4297030000001,5.827222],[73.45109600000015,5.849166],[73.436371,5.827222]]],[[[72.96887200000012,5.850832],[72.96499600000013,5.847499],[72.961105,5.867777],[72.96887200000012,5.850832]]],[[[73.433044,5.902222],[73.423599,5.903610000000128],[73.422211,5.911666],[73.433044,5.902222]]],[[[73.398331,5.955277],[73.379425,5.971388],[73.393326,5.96861],[73.398331,5.955277]]],[[[72.933319,5.960833],[72.92831400000014,5.954999],[72.9260860000002,5.97194400000015],[72.933319,5.960833]]],[[[73.270538,6.185276],[73.2686,6.175277000000122],[73.269989,6.193054],[73.270538,6.185276]]],[[[73.248032,6.231943],[73.2397,6.227499],[73.234711,6.23611],[73.248032,6.231943]]],[[[73.204437,6.317499],[73.190811,6.324721000000125],[73.20166,6.327499000000117],[73.204437,6.317499]]],[[[73.05026200000012,6.429166000000151],[73.040817,6.429999000000151],[73.041367,6.444165],[73.05026200000012,6.429166000000151]]],[[[73.0674900000001,6.661388],[73.059982,6.657499],[73.068054,6.672776],[73.0674900000001,6.661388]]],[[[73.101089,6.696943],[73.093323,6.697221],[73.1024780000001,6.715555],[73.101089,6.696943]]],[[[73.136932,6.726388],[73.12915000000012,6.733888],[73.161926,6.784165],[73.136932,6.726388]]],[[[73.18136600000011,6.8325],[73.20166,6.828888],[73.184143,6.81861],[73.18136600000011,6.8325]]],[[[73.2052610000002,6.883611],[73.19552600000011,6.889443000000142],[73.209991,6.926388],[73.2052610000002,6.883611]]],[[[73.198868,6.947498],[73.19165,6.951111],[73.193588,6.978610000000117],[73.198868,6.947498]]],[[[72.985535,7.012221],[72.97998000000021,7.011666000000119],[72.974991,7.029444],[72.985535,7.012221]]],[[[72.91609200000019,7.081666],[72.90277100000012,7.093055000000106],[72.911926,7.094999],[72.91609200000019,7.081666]]]]}},{"type":"Feature","properties":{"name":"Mexico","iso2":"MX","iso3":"MEX"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-114.74278259277344,18.322778701782227],[-114.80307006835938,18.33277702331543],[-114.72389221191406,18.353334426879883],[-114.74278259277344,18.322778701782227]]],[[[-87.37278747558594,18.400278091430664],[-87.33168029785156,18.503053665161133],[-87.32695007324219,18.453332901000977],[-87.37278747558594,18.400278091430664]]],[[[-87.25167846679688,18.641389846801758],[-87.25944519042969,18.627779006958008],[-87.2650146484375,18.733888626098633],[-87.25167846679688,18.641389846801758]]],[[[-91.82861328125,18.6391658782959],[-91.6461181640625,18.753610610961914],[-91.52389526367188,18.77055549621582],[-91.82861328125,18.6391658782959]]],[[[-110.92611694335938,18.72110939025879],[-111.07140350341797,18.76833152770996],[-111.00334167480469,18.864999771118164],[-110.92611694335938,18.72110939025879]]],[[[-110.78861999511719,19.308053970336914],[-110.83585357666016,19.271387100219727],[-110.81333923339844,19.341665267944336],[-110.78861999511719,19.308053970336914]]],[[[-86.7327880859375,20.585554122924805],[-87,20.25638771057129],[-86.93890380859375,20.539445877075195],[-86.7327880859375,20.585554122924805]]],[[[-86.70140075683594,21.197221755981445],[-86.7388916015625,21.239999771118164],[-86.74917602539062,21.28639030456543],[-86.70140075683594,21.197221755981445]]],[[[-106.195556640625,21.255277633666992],[-106.26500701904297,21.336668014526367],[-106.197509765625,21.33860969543457],[-106.195556640625,21.255277633666992]]],[[[-106.38667297363281,21.42083168029785],[-106.51139831542969,21.45027732849121],[-106.33556365966797,21.49888801574707],[-106.38667297363281,21.42083168029785]]],[[[-106.51500701904297,21.5130558013916],[-106.64584350585938,21.68833351135254],[-106.5300064086914,21.690832138061523],[-106.51500701904297,21.5130558013916]]],[[[-106.65640258789062,21.752500534057617],[-106.67529296875,21.74138832092285],[-106.67056274414062,21.816389083862305],[-106.65640258789062,21.752500534057617]]],[[[-97.81889343261719,22.6825008392334],[-97.83084106445312,22.697221755981445],[-97.7841796875,22.774168014526367],[-97.81889343261719,22.6825008392334]]],[[[-97.77305603027344,22.7913875579834],[-97.78140258789062,22.80499839782715],[-97.76028442382812,22.834165573120117],[-97.77305603027344,22.7913875579834]]],[[[-109.7844467163086,24.135000228881836],[-109.87139892578125,24.187498092651367],[-109.91555786132812,24.3688907623291],[-109.7844467163086,24.135000228881836]]],[[[-111.53250122070312,24.378053665161133],[-111.49474334716797,24.351388931274414],[-111.6702880859375,24.371946334838867],[-111.53250122070312,24.378053665161133]]],[[[-111.70584106445312,24.331666946411133],[-112.01667785644531,24.532499313354492],[-111.8369369506836,24.541112899780273],[-111.70584106445312,24.331666946411133]]],[[[-110.32805633544922,24.400835037231445],[-110.40194702148438,24.579999923706055],[-110.30000305175781,24.484445571899414],[-110.32805633544922,24.400835037231445]]],[[[-110.53695678710938,24.88222312927246],[-110.70500183105469,25.093889236450195],[-110.57890319824219,25.03388786315918],[-110.53695678710938,24.88222312927246]]],[[[-112.04611206054688,24.519166946411133],[-112.25279235839844,24.809999465942383],[-112.13362121582031,25.281110763549805],[-112.20250701904297,24.844999313354492],[-112.04611206054688,24.519166946411133]]],[[[-108.84278869628906,25.42860984802246],[-108.78916931152344,25.372220993041992],[-109.01112365722656,25.43833351135254],[-108.84278869628906,25.42860984802246]]],[[[-110.79695129394531,25.594999313354492],[-110.82528686523438,25.642499923706055],[-110.8083267211914,25.695833206176758],[-110.79695129394531,25.594999313354492]]],[[[-111.197509765625,25.844999313354492],[-111.19139099121094,26.038888931274414],[-111.086669921875,26.074445724487305],[-111.197509765625,25.844999313354492]]],[[[-110.54611206054688,27.309999465942383],[-110.59750366210938,27.336111068725586],[-110.59028625488281,27.4152774810791],[-110.54611206054688,27.309999465942383]]],[[[-114.22000122070312,27.738332748413086],[-114.32389831542969,27.816667556762695],[-114.24501037597656,27.814443588256836],[-114.22000122070312,27.738332748413086]]],[[[-115.17388916015625,28.027498245239258],[-115.3266830444336,28.138334274291992],[-115.24083709716797,28.370553970336914],[-115.17388916015625,28.027498245239258]]],[[[-112.760009765625,28.593610763549805],[-112.88583374023438,28.683889389038086],[-112.79640197753906,28.644166946411133],[-112.760009765625,28.593610763549805]]],[[[-112.58168029785156,28.670278549194336],[-112.60362243652344,28.72722053527832],[-112.54084777832031,28.7358341217041],[-112.58168029785156,28.670278549194336]]],[[[-118.28916931152344,28.88166618347168],[-118.40416717529297,29.14777946472168],[-118.31001281738281,29.195276260375977],[-118.28916931152344,28.88166618347168]]],[[[-112.26194763183594,28.773332595825195],[-112.56417846679688,28.878332138061523],[-112.34584045410156,29.233610153198242],[-112.26194763183594,28.773332595825195]]],[[[-113.13555908203125,29.019723892211914],[-113.59221458435059,29.425832748413086],[-113.588623046875,29.5836124420166],[-113.13555908203125,29.019723892211914]]],[[[-114.65084838867188,31.690553665161133],[-114.76363372802734,31.712499618530273],[-114.790283203125,31.7994441986084],[-114.65084838867188,31.690553665161133]]],[[[-113.05288696289062,31.971071243286133],[-111.04583740234375,31.33305549621582],[-108.20834350585938,31.33305549621582],[-108.2086181640625,31.783334732055664],[-106.40084838867188,31.750276565551758],[-104.90055847167969,30.572778701782227],[-104.54000854492188,29.671110153198242],[-103.375,29.023611068725586],[-102.30584716796875,29.88944435119629],[-101.40501403808594,29.77277946472168],[-99.5050048828125,27.570276260375977],[-99.104736328125,26.434999465942383],[-97.14073944091797,25.966428756713867],[-97.88972473144531,22.600831985473633],[-97.17611694335938,20.684999465942383],[-95.91139221191406,18.82527732849121],[-94.80223083496094,18.52250099182129],[-94.47889709472656,18.146665573120117],[-91.99501037597656,18.7277774810791],[-91.81472778320312,18.383054733276367],[-91.47500610351562,18.439443588256836],[-90.45472717285156,19.975278854370117],[-90.3275146484375,21.031389236450195],[-88.45140075683594,21.56888771057129],[-87.02778625488281,21.59027671813965],[-86.77278137207031,21.15138816833496],[-87.7388916015625,19.67472267150879],[-87.41166687011719,19.578889846801758],[-87.84750366210938,18.190832138061523],[-88.03750610351562,18.869443893432617],[-88.29949951171875,18.48293113708496],[-88.37779235839844,18.482778549194336],[-89.14195251464844,17.81888771057129],[-90.982421875,17.820653915405273],[-90.98390197753906,17.2561092376709],[-91.4375,17.24110984802246],[-90.40640258789062,16.4163875579834],[-90.44195556640625,16.088335037231445],[-91.72917175292969,16.07499885559082],[-92.24678039550781,14.550546646118164],[-92.77278137207031,15.174444198608398],[-94.36805725097656,16.294443130493164],[-94.05778503417969,16.040834426879883],[-94.7247314453125,16.196664810180664],[-94.57806396484375,16.318334579467773],[-94.78973388671875,16.257776260375977],[-94.86195373535156,16.427499771118164],[-96.47611999511719,15.643610000610352],[-97.78500366210938,15.968610763549805],[-101.01112365722656,17.265275955200195],[-101.95001220703125,17.97749900817871],[-103.45001220703125,18.31361198425293],[-104.98361206054688,19.339445114135742],[-105.68000793457031,20.386388778686523],[-105.24417114257812,20.574167251586914],[-105.54444885253906,20.785001754760742],[-105.189453125,21.437498092651367],[-105.81696319580078,22.660276412963867],[-107.99918365478516,24.652498245239258],[-108.04251098632812,25.073610305786133],[-108.39418029785156,25.141111373901367],[-108.76779174804688,25.54222297668457],[-109.10890197753906,25.52610969543457],[-108.82805633544922,25.7983341217041],[-109.3880615234375,25.7561092376709],[-109.10389709472656,26.28360939025879],[-110.52971458435059,27.371110916137695],[-110.5097427368164,27.86638832092285],[-111.10556030273438,27.93833351135254],[-112.16472625732422,28.972501754760742],[-113.086669921875,31.22722053527832],[-115.03167724609375,31.968053817749023],[-114.5452880859375,30.00111198425293],[-112.86279296875,28.433332443237305],[-111.85861206054688,26.661943435668945],[-111.84221458435059,26.90305519104004],[-111.56083679199219,26.72361183166504],[-110.66056823730469,24.337778091430664],[-110.35417175292969,24.115835189819336],[-110.213623046875,24.351945877075195],[-109.41084289550781,23.468332290649414],[-110.00499725341797,22.886110305786133],[-110.31668090820312,23.5674991607666],[-112.08750915527344,24.7561092376709],[-112.07084655761719,25.613054275512695],[-112.10611724853516,25.51833152770996],[-112.39666557312012,26.27277946472168],[-113.22029113769531,26.705556869506836],[-113.12834167480469,26.958887100219727],[-113.59750366210938,26.7369441986084],[-114.9888916015625,27.72110939025879],[-113.98306274414062,27.70250129699707],[-114.31056213378906,27.865556716918945],[-114.06360626220703,28.527223587036133],[-115.69389343261719,29.76833152770996],[-117.12237358093262,32.53533363342285],[-114.7190933227539,32.71845817565918],[-114.80982971191406,32.50699043273926],[-113.05288696289062,31.971071243286133]],[[-109.94889831542969,27.024442672729492],[-109.98139953613281,27.076387405395508],[-110.0344467163086,27.09139060974121],[-109.94889831542969,27.024442672729492]],[[-97.6077880859375,21.736665725708008],[-97.68556213378906,21.85999870300293],[-97.67417907714844,21.7902774810791],[-97.6077880859375,21.736665725708008]]]]}},{"type":"Feature","properties":{"name":"Malaysia","iso2":"MY","iso3":"MYS"},"geometry":{"type":"MultiPolygon","coordinates":[[[[104.12024116516113,2.318891525268555],[104.15497016906738,2.287778854370117],[104.1010684967041,2.294168472290039],[104.12024116516113,2.318891525268555]]],[[[111.37082099914551,2.36027717590332],[111.30359077453613,2.448057174682617],[111.32747840881348,2.781389236450195],[111.38388252258301,2.680002212524414],[111.37692451477051,2.495279312133789],[111.41388130187988,2.37611198425293],[111.37082099914551,2.36027717590332]]],[[[104.17108345031738,2.705278396606445],[104.17191505432129,2.895002365112305],[104.22162818908691,2.72972297668457],[104.17108345031738,2.705278396606445]]],[[[117.72664833068848,4.169721603393555],[117.9035587310791,4.174043655395508],[117.68692207336426,4.168336868286133],[117.72664833068848,4.169721603393555]]],[[[118.68193244934082,4.499723434448242],[118.76277351379395,4.463613510131836],[118.68942451477051,4.441110610961914],[118.68193244934082,4.499723434448242]]],[[[118.50972175598145,4.554445266723633],[118.51748847961426,4.536111831665039],[118.49942207336426,4.529165267944336],[118.50972175598145,4.554445266723633]]],[[[118.57026863098145,4.600831985473633],[118.34387397766113,4.670553207397461],[118.47886848449707,4.689165115356445],[118.57026863098145,4.600831985473633]]],[[[115.2330493927002,5.259721755981445],[115.15833473205566,5.257776260375977],[115.24193000793457,5.384721755981445],[115.2330493927002,5.259721755981445]]],[[[100.28885841369629,5.256109237670898],[100.1838550567627,5.462499618530273],[100.32025337219238,5.427778244018555],[100.28885841369629,5.256109237670898]]],[[[115.67221260070801,5.707223892211914],[115.62776374816895,5.728334426879883],[115.65442848205566,5.735834121704102],[115.67221260070801,5.707223892211914]]],[[[118.17192268371582,5.812223434448242],[118.17886543273926,5.84889030456543],[118.2330493927002,5.848333358764648],[118.17192268371582,5.812223434448242]]],[[[116.05941963195801,6.003057479858398],[116.01693916320801,6.035833358764648],[116.05664253234863,6.039999008178711],[116.05941963195801,6.003057479858398]]],[[[115.60915565490723,6.195276260375977],[115.59274482727051,6.204721450805664],[115.60775947570801,6.221109390258789],[115.60915565490723,6.195276260375977]]],[[[99.87329292297363,6.416109085083008],[99.81302070617676,6.156667709350586],[99.64082527160645,6.419721603393555],[99.87329292297363,6.416109085083008]]],[[[100.65497016906738,6.448331832885742],[101.11551856994629,6.24888801574707],[101.13968849182129,5.63194465637207],[101.56997871398926,5.916666030883789],[101.83386421203613,5.74333381652832],[102.0952320098877,6.236139297485352],[103.40997505187988,4.858053207397461],[103.43579292297363,2.933889389038086],[104.27580451965332,1.365556716918945],[103.95941352844238,1.646944046020508],[103.51214027404785,1.269529342651367],[101.28497505187988,2.84111213684082],[101.29442024230957,3.268888473510742],[100.69719123840332,3.903890609741211],[100.12711524963379,6.424947738647461],[100.2149829864502,6.711111068725586],[100.65497016906738,6.448331832885742]]],[[[117.49359321594238,6.742498397827148],[117.46692848205566,6.642499923706055],[117.33719825744629,6.651388168334961],[117.49359321594238,6.742498397827148]]],[[[116.78914833068848,6.579168319702148],[117.17830848693848,6.990278244018555],[117.29081916809082,6.635835647583008],[117.73887825012207,6.39000129699707],[117.50305366516113,5.896112442016602],[118.00888252258301,6.061666488647461],[117.96027565002441,5.681390762329102],[118.37359809875488,5.807500839233398],[119.27581977844238,5.344999313354492],[118.14055061340332,4.888334274291992],[118.55220222473145,4.351667404174805],[117.5920581817627,4.169820785522461],[116.04942512512207,4.279443740844727],[115.68525886535645,4.171945571899414],[115.49553108215332,3.040002822875977],[115.13971138000488,2.906110763549805],[115.2371997833252,2.522500991821289],[114.8047046661377,2.24888801574707],[114.5627613067627,1.433610916137695],[113.65833473205566,1.224721908569336],[112.47276496887207,1.568056106567383],[111.82721138000488,0.998613357543945],[110.55525398254395,0.853891372680664],[109.66998481750488,1.613054275512695],[109.64856910705566,2.073408126831055],[109.92830848693848,1.689165115356445],[110.33333015441895,1.802221298217773],[111.37692451477051,1.343889236450195],[111.00000190734863,1.575555801391602],[111.37275886535645,2.150835037231445],[111.16858863830566,2.152223587036133],[111.22331428527832,2.421110153198242],[111.36811256408691,2.339094161987305],[111.45027351379395,2.368612289428711],[111.44470405578613,2.691667556762695],[113.01053810119629,3.160554885864258],[114.09507942199707,4.590539932250977],[114.64109992980957,4.018888473510742],[115.01843452453613,4.895795822143555],[115.02913093566895,4.820211410522461],[115.34332466125488,4.311944961547852],[115.2230396270752,4.804998397827148],[115.14578437805176,4.903242111206055],[115.54609870910645,5.053056716918945],[115.37886238098145,5.398889541625977],[115.84887886047363,5.56389045715332],[116.76249885559082,7.023611068725586],[116.78914833068848,6.579168319702148]]],[[[117.28333473205566,7.314722061157227],[117.06667518615723,7.10194206237793],[117.07415962219238,7.287500381469727],[117.28333473205566,7.314722061157227]]],[[[116.87248420715332,7.219999313354492],[117.00332832336426,7.353334426879883],[117.01888465881348,7.266389846801758],[116.87248420715332,7.219999313354492]]]]}},{"type":"Feature","properties":{"name":"Mozambique","iso2":"MZ","iso3":"MOZ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[32.954437,-26.058613],[32.89527100000012,-26.040836],[32.980553,-25.972778],[32.954437,-26.058613]]],[[[35.48832700000011,-21.685001],[35.435555,-21.783337],[35.47943900000021,-21.523891],[35.48832700000011,-21.685001]]],[[[39.901382,-16.413334],[39.810829000000155,-16.363056],[39.861382,-16.278057],[39.901382,-16.413334]]],[[[40.5008320000002,-11.031946],[40.64694200000022,-12.760834],[40.409996,-12.961945],[40.846107,-14.697779],[40.587776000000105,-15.479723],[39.09444400000021,-16.986389],[36.841385,-17.877224],[36.943886,-18.108612],[36.25277700000012,-18.891392],[34.899162,-19.857224],[34.619164,-19.617779],[35.312492,-22.418056],[35.545273,-22.232502],[35.497215,-24.105278],[35.012215,-24.654167],[32.81388900000016,-25.60778],[32.576111,-25.975559],[32.837494,-26.293056],[32.95249900000013,-26.083889],[32.890427,-26.847145],[32.1334,-26.839626],[31.96851,-25.95784],[32.016106,-24.459446],[31.297504000000146,-22.414764],[32.488876,-21.344448],[32.50222000000011,-20.598614],[33.0188830000001,-19.943336],[32.699165,-18.944447],[33.073051000000106,-18.348892],[32.987808,-17.265003],[32.98114,-16.709053],[31.276665,-16.018612],[30.422775,-16.009167],[30.415756,-15.631872],[30.21301700000018,-14.981716],[33.222229,-14.012566],[33.633331,-14.539722],[34.522217,-14.571667],[34.589722,-15.282778],[34.2555540000001,-15.899168],[35.2900540000002,-17.134266],[35.135300000000115,-16.553375],[35.814438,-16.019447],[35.924164000000104,-14.885557],[34.566383000000116,-13.342224],[34.375275,-12.155834],[34.626106000000135,-11.575834],[34.966728,-11.572111],[35.838333,-11.414722],[36.18972,-11.706667],[37.462044,-11.727329],[37.941383,-11.285002],[39.268051000000156,-11.168056],[40.43681300000017,-10.478174],[40.5008320000002,-11.031946]],[[34.602776000000205,-12.011946],[34.623886,-12.036667],[34.629997,-12.012501],[34.602776000000205,-12.011946]],[[34.723885,-12.032778],[34.732216,-12.095556],[34.754715,-12.044168],[34.723885,-12.032778]]]]}},{"type":"Feature","properties":{"name":"Malawi","iso2":"MW","iso3":"MWI"},"geometry":{"type":"MultiPolygon","coordinates":[[[[34.732216,-12.095556],[34.723885,-12.032778],[34.754715,-12.044168],[34.732216,-12.095556]]],[[[34.623886,-12.036667],[34.602776000000205,-12.011946],[34.629997,-12.012501],[34.623886,-12.036667]]],[[[33.13472000000016,-9.494167],[34.325272,-9.732779],[34.966728,-11.572111],[34.626106000000135,-11.575834],[34.375275,-12.155834],[34.566383000000116,-13.342224],[35.924164000000104,-14.885557],[35.814438,-16.019447],[35.135300000000115,-16.553375],[35.2900540000002,-17.134266],[34.2555540000001,-15.899168],[34.589722,-15.282778],[34.522217,-14.571667],[33.633331,-14.539722],[33.222229,-14.012566],[32.678886,-13.60639],[33.046387,-12.603889],[33.54583,-12.359446],[33.273331,-12.144445],[33.250549,-10.886667],[33.702278,-10.561857],[32.940399,-9.405077],[33.13472000000016,-9.494167]]]]}},{"type":"Feature","properties":{"name":"New Caledonia","iso2":"NC","iso3":"NCL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[167.534424,-22.69389],[167.508026,-22.688332],[167.53137200000018,-22.651112],[167.534424,-22.69389]]],[[[167.5016480000002,-22.672222],[167.434692,-22.543056],[167.553864,-22.612499],[167.5016480000002,-22.672222]]],[[[166.816071,-22.463333],[166.7724910000002,-22.456108],[166.811646,-22.395],[166.816071,-22.463333]]],[[[171.313873,-22.33139],[171.300812,-22.334999],[171.304962,-22.327778],[171.313873,-22.33139]]],[[[166.0505370000001,-22.079445],[166.027191,-22.054722],[166.0505370000001,-22.036667],[166.0505370000001,-22.079445]]],[[[166.450256,-21.704445],[166.415527,-21.691387],[166.440796,-21.68861],[166.450256,-21.704445]]],[[[168.0021970000001,-21.451942],[168.1202390000001,-21.631111],[167.808868,-21.385834],[168.0021970000001,-21.451942]]],[[[167.842743,-21.14389],[167.80136100000013,-21.119446],[167.80246,-21.100277],[167.842743,-21.14389]]],[[[166.4480290000001,-20.734165],[166.38858,-20.72583],[166.459137,-20.719719],[166.4480290000001,-20.734165]]],[[[167.287201,-20.75639],[167.39804100000012,-21.177776],[167.059692,-20.988609],[167.287201,-20.75639]]],[[[166.62466400000014,-20.406109],[166.62579300000013,-20.601665],[166.499115,-20.717777],[166.62466400000014,-20.406109]]],[[[164.288025,-20.255558],[164.275269,-20.248886],[164.27026400000014,-20.219719],[164.288025,-20.255558]]],[[[163.943848,-20.170555],[163.922485,-20.16972],[163.906921,-20.14389],[163.943848,-20.170555]]],[[[164.31665000000012,-20.327225],[167.01470900000012,-22.321388],[166.451904,-22.316666],[166.116364,-21.946388],[165.2599790000002,-21.558056],[163.98941,-20.087223],[164.31665000000012,-20.327225]]],[[[164.234131,-20.161945],[164.161102,-20.113335],[164.16330000000013,-20.065277],[164.234131,-20.161945]]],[[[163.821625,-20.082779],[163.796936,-20.040836],[163.817749,-20.040836],[163.821625,-20.082779]]],[[[163.97717300000014,-20.081669],[163.939972,-20.068058],[163.949402,-20.002224],[163.97717300000014,-20.081669]]],[[[163.671906,-19.785835],[163.61969,-19.625832],[163.700806,-19.766392],[163.671906,-19.785835]]],[[[163.6074520000001,-19.604168],[163.568024,-19.573055],[163.5766300000001,-19.549446],[163.6074520000001,-19.604168]]],[[[159.949402,-19.343334],[159.95108,-19.114445],[159.978851,-19.171665],[159.949402,-19.343334]]]]}},{"type":"Feature","properties":{"name":"Niue","iso2":"NU","iso3":"NIU"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-169.89389,-19.145557],[-169.931671,-19.016666],[-169.817505,-18.96833],[-169.89389,-19.145557]]]]}},{"type":"Feature","properties":{"name":"Niger","iso2":"NE","iso3":"NER"},"geometry":{"type":"MultiPolygon","coordinates":[[[[4.245,18.645275],[4.245277,19.146664],[5.812499,19.44611],[7.450807,20.852863],[11.986475,23.522305],[13.543888,23.16861],[14.234999,22.614166],[14.997889,23.000591],[15.202499,21.495831],[15.996666,20.353054],[15.489166,16.914165],[13.468887,14.461111],[13.62512,13.718338],[12.459166,13.066111],[10.724165,13.386389],[9.634932,12.802435],[7.815,13.352777],[6.933332,12.997221000000124],[6.423055,13.605276000000131],[5.874722,13.749443],[4.1425,13.476944],[3.604459,11.693274],[2.83862,12.396658],[2.378054,12.240274],[2.397925,11.896152],[2.1425,12.694443],[1.578333,12.629999],[0.989167,13.047222],[0.991667,13.371666],[1.285306,13.349957],[0.602222,13.703888],[0.235048,14.915068],[1.3125,15.286665],[3.523981,15.358152],[4.200833,16.393887],[4.245,18.645275]]]]}},{"type":"Feature","properties":{"name":"Aruba","iso2":"AW","iso3":"ABW"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-69.882233,12.41111],[-70.059448,12.538055],[-70.063065,12.628611],[-69.882233,12.41111]]]]}},{"type":"Feature","properties":{"name":"Anguilla","iso2":"AI","iso3":"AIA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-63.167778,18.164444],[-62.970001,18.272221],[-62.993057,18.227219],[-63.167778,18.164444]]]]}},{"type":"Feature","properties":{"name":"Belgium","iso2":"BE","iso3":"BEL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[4.302375,51.263184],[4.252368,51.375145],[5.041389000000152,51.486664],[5.849171,51.15638],[5.640833,50.839722],[6.011798000000113,50.7572710000001],[6.398204,50.323174],[6.134414,50.127846],[6.026256,50.181252],[5.80788,49.545044],[4.873055000000107,49.797218],[4.832503,50.16861],[4.149238,49.978371],[4.165,50.283051],[2.541667000000103,51.09111],[3.370866,51.373856000000146],[4.238898,51.350426],[4.302375,51.263184]]]]}},{"type":"Feature","properties":{"name":"Hong Kong","iso2":"HK","iso3":"HKG"},"geometry":{"type":"MultiPolygon","coordinates":[[[[114.24609400000011,22.203327],[114.124977,22.279999],[114.201103,22.290554],[114.24609400000011,22.203327]]],[[[113.8966520000001,22.195827000000108],[113.82527200000013,22.232216],[114.04776000000012,22.339996000000113],[113.8966520000001,22.195827000000108]]],[[[114.31414800000013,22.342773],[114.295258,22.34582900000011],[114.296097,22.368053],[114.31414800000013,22.342773]]],[[[114.219437,22.474438],[114.296104,22.260561],[114.03333040044393,22.50913814917469],[114.2225957829825,22.550548246897094],[114.219437,22.474438]]]]}},{"type":"Feature","properties":{"name":"Northern Mariana Islands","iso2":"MP","iso3":"MNP"},"geometry":{"type":"MultiPolygon","coordinates":[[[[145.2816470000001,14.158333],[145.11996500000012,14.122498],[145.237183,14.194998],[145.2816470000001,14.158333]]],[[[145.5352480000001,14.82833100000012],[145.529694,14.848331],[145.570251,14.844997],[145.5352480000001,14.82833100000012]]],[[[145.624115,14.908054000000106],[145.5722050000002,15.009998],[145.633026,15.083887],[145.624115,14.908054000000106]]],[[[145.73608400000015,15.133610000000118],[145.679138,15.105276],[145.818024,15.265833],[145.73608400000015,15.133610000000118]]],[[[145.655823,16.334721],[145.63443,16.376106],[145.714691,16.355831],[145.655823,16.334721]]],[[[145.798309,16.680275],[145.774994,16.705273000000105],[145.80163600000012,16.70055000000012],[145.798309,16.680275]]],[[[145.860779,17.28722],[145.84024,17.317219],[145.8674620000002,17.30416500000011],[145.860779,17.28722]]],[[[145.860779,17.567776],[145.824402,17.577496000000124],[145.833862,17.604996000000156],[145.860779,17.567776]]],[[[145.73608400000015,18.043888],[145.77914400000012,18.17083000000015],[145.824402,18.163052],[145.73608400000015,18.043888]]],[[[145.679138,18.721382000000133],[145.6633000000002,18.810276],[145.71051000000014,18.76833],[145.679138,18.721382000000133]]],[[[145.405823,19.652775],[145.3891600000002,19.688885],[145.415253,19.677219],[145.405823,19.652775]]],[[[145.256927,20.010830000000126],[145.242188,20.052219],[145.27359,20.036385],[145.256927,20.010830000000126]]],[[[144.921082,20.51833],[144.899139,20.526108],[144.913605,20.556385],[144.921082,20.51833]]]]}},{"type":"Feature","properties":{"name":"Faroe Islands","iso2":"FO","iso3":"FRO"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-6.655277252197266,61.38944435119629],[-6.962778091430664,61.61916542053223],[-6.724445343017578,61.57332801818848],[-6.655277252197266,61.38944435119629]]],[[[-6.604166030883789,61.821664810180664],[-6.6522216796875,61.74277687072754],[-6.908332824707031,61.90471839904785],[-6.604166030883789,61.821664810180664]]],[[[-7.049722671508789,62.06777381896973],[-7.201665878295898,62.01861000061035],[-7.434999465942383,62.140275955200195],[-7.049722671508789,62.06777381896973]]],[[[-6.706943511962891,61.9374942779541],[-7.232221603393555,62.172494888305664],[-7.210832595825195,62.28472328186035],[-6.706943511962891,61.9374942779541]]],[[[-6.657499313354492,62.09250068664551],[-7.060277938842773,62.313608169555664],[-6.601110458374023,62.19693946838379],[-6.657499313354492,62.09250068664551]]],[[[-6.620000839233398,62.22972297668457],[-6.685832977294922,62.24499702453613],[-6.720832824707031,62.33138465881348],[-6.620000839233398,62.22972297668457]]],[[[-6.418611526489258,62.18388557434082],[-6.572500228881836,62.2116641998291],[-6.57440185546875,62.34987831115723],[-6.418611526489258,62.18388557434082]]],[[[-6.406110763549805,62.284440994262695],[-6.480278015136719,62.29777717590332],[-6.545278549194336,62.38694190979004],[-6.406110763549805,62.284440994262695]]]]}},{"type":"Feature","properties":{"name":"Andorra","iso2":"AD","iso3":"AND"},"geometry":{"type":"MultiPolygon","coordinates":[[[[1.78172,42.569962],[1.723611,42.509438],[1.445833,42.601944],[1.78172,42.569962]]]]}},{"type":"Feature","properties":{"name":"Gibraltar","iso2":"GI","iso3":"GIB"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-5.334508,36.16256000000011],[-5.33823,36.112175],[-5.355799,36.1633070000001],[-5.334508,36.16256000000011]]]]}},{"type":"Feature","properties":{"name":"Isle of Man","iso2":"IM","iso3":"IMN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-4.777779,54.05555],[-4.354167,54.410828],[-4.394444,54.186386],[-4.777779,54.05555]]]]}},{"type":"Feature","properties":{"name":"Luxembourg","iso2":"LU","iso3":"LUX"},"geometry":{"type":"MultiPolygon","coordinates":[[[[6.026256,50.181252],[6.134414,50.127846],[6.524444,49.808609],[6.36217,49.459389],[5.80788,49.545044],[6.026256,50.181252]]]]}},{"type":"Feature","properties":{"name":"Macau","iso2":"MO","iso3":"MAC"},"geometry":{"type":"MultiPolygon","coordinates":[[[[113.531662,22.194736],[113.554428,22.21273000000015],[113.552467,22.183052],[113.531662,22.194736]]]]}},{"type":"Feature","properties":{"name":"Monaco","iso2":"MC","iso3":"MCO"},"geometry":{"type":"MultiPolygon","coordinates":[[[[7.439293000000106,43.75752300000015],[7.391609,43.727547],[7.387777,43.748604],[7.416111,43.770554],[7.439293000000106,43.75752300000015]]]]}},{"type":"Feature","properties":{"name":"Palestine","iso2":"PS","iso3":"PSE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[34.33416,31.25972],[34.26757800000021,31.216541],[34.21666,31.323330000000155],[34.490547,31.596096000000117],[34.33416,31.25972]]],[[[35.282494,32.516937],[35.552567,32.394196],[35.47819500000011,31.497322],[34.884995,31.391388],[35.282494,32.516937]],[[35.251663,31.788055000000114],[35.25972000000016,31.78722000000012],[35.24888600000011,31.808887000000155],[35.251663,31.788055000000114]]]]}},{"type":"Feature","properties":{"name":"Montenegro","iso2":"ME","iso3":"MNE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[18.455555,42.565826],[18.699997,43.255554],[19.228809,43.513214],[20.348888,42.886383],[20.071423,42.560913],[19.645832,42.61805],[19.367771,41.848999],[18.503197,42.44944],[18.455555,42.565826]]]]}},{"type":"Feature","properties":{"name":"Mayotte","iso2":"YT","iso3":"MYT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[45.282494,-12.804167],[45.262497,-12.76889],[45.283051,-12.747501],[45.282494,-12.804167]]],[[[45.2049940000002,-12.849724],[45.097496,-12.985834],[45.078888,-12.6625],[45.2049940000002,-12.849724]]]]}},{"type":"Feature","properties":{"name":"Åland Islands","iso2":"AX","iso3":"ALA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[20.210831000000155,59.979996000000156],[19.99916500000012,60.055275],[20.205276,60.063606],[20.210831000000155,59.979996000000156]]],[[[20.270554,60.057495000000145],[20.215553,60.13916],[20.292221,60.125275],[20.270554,60.057495000000145]]],[[[19.676666,60.156944],[19.510555,60.17527800000012],[19.601944,60.255829],[19.676666,60.156944]]],[[[20.397221000000144,60.195],[20.36610800000014,60.26554900000012],[20.441109,60.253052000000125],[20.397221000000144,60.195]]],[[[20.084721,60.350273],[20.277496,60.274162],[19.943886,60.04277],[19.648331,60.25666],[20.084721,60.350273]]]]}},{"type":"Feature","properties":{"name":"Norfolk Island","iso2":"NF","iso3":"NFK"},"geometry":{"type":"MultiPolygon","coordinates":[[[[167.964966,-29.081112],[167.912476,-29.00528],[167.997742,-29.025002],[167.964966,-29.081112]]]]}},{"type":"Feature","properties":{"name":"Cocos (Keeling) Islands","iso2":"CC","iso3":"CCK"},"geometry":{"type":"MultiPolygon","coordinates":[[[[96.914154,-12.198055],[96.902481,-12.199999],[96.91470300000012,-12.151945],[96.914154,-12.198055]]],[[[96.86276200000012,-12.196112],[96.819443,-12.178057],[96.826385,-12.128332],[96.86276200000012,-12.196112]]]]}},{"type":"Feature","properties":{"name":"Antarctica","iso2":"AQ","iso3":"ATA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-60.220001220703125,-80.28584289550781],[-60.90861511230469,-80.74833679199219],[-61.843894958496094,-80.83639526367188],[-67.03195190429688,-80.16639709472656],[-62.55000305175781,-80.25889587402344],[-60.69500732421875,-79.61000061035156],[-60.173614501953125,-79.711669921875],[-60.220001220703125,-80.28584289550781]]],[[[162.15973091125488,-79.06167602539062],[161.94778633117676,-79.03083801269531],[161.92584419250488,-78.98167419433594],[162.15973091125488,-79.06167602539062]]],[[[-162.13336181640625,-78.74111938476562],[-158.53250122070312,-79.71389770507812],[-161.08584594726562,-79.83528137207031],[-163.81640625,-79.20750427246094],[-162.13336181640625,-78.74111938476562]]],[[[-39.972503662109375,-78.55473327636719],[-37.459449768066406,-78.64028930664062],[-41.93055725097656,-78.59194946289062],[-39.972503662109375,-78.55473327636719]]],[[[-70.945556640625,-79.65000915527344],[-71.85528564453125,-79.4202880859375],[-70.30416870117188,-78.80528259277344],[-67.31723022460938,-78.50361633300781],[-70.945556640625,-79.65000915527344]]],[[[167.31555366516113,-78.25361633300781],[166.87164497375488,-78.20808410644531],[167.67749214172363,-78.11752319335938],[167.31555366516113,-78.25361633300781]]],[[[166.35220527648926,-78.31362915039062],[166.06555366516113,-78.11474609375],[166.77417182922363,-78.22111511230469],[166.35220527648926,-78.31362915039062]]],[[[-44.11444854736328,-78.69889831542969],[-45.575279235839844,-78.85195922851562],[-43.7933349609375,-79.00361633300781],[-44.583335876464844,-79.33389282226562],[-43.46611785888672,-79.47029113769531],[-43.35444641113281,-79.77972412109375],[-44.57250213623047,-80.09222412109375],[-44.066673278808594,-80.25750732421875],[-44.28639221191406,-80.33973693847656],[-52.05555725097656,-80.90278625488281],[-54.90888977050781,-80.71861267089844],[-50.666114807128906,-79.588623046875],[-50.183616638183594,-78.65055847167969],[-48.27278137207031,-78.05639457702637],[-44.841949462890625,-78.10139465332031],[-43.89111328125,-78.36195373535156],[-44.11444854736328,-78.69889831542969]]],[[[-148.76113891601562,-77.44223022460938],[-149.0352783203125,-77.41694641113281],[-148.8294677734375,-77.40139770507812],[-148.76113891601562,-77.44223022460938]]],[[[-150.20751953125,-77.37001037597656],[-151.19390869140625,-77.27195739746094],[-150.076416015625,-77.34056091308594],[-150.20751953125,-77.37001037597656]]],[[[-148.85861206054688,-77.354736328125],[-149.51947021484375,-77.29084777832031],[-149.16168212890625,-77.25889587402344],[-148.85861206054688,-77.354736328125]]],[[[167.71695137023926,-77.40583801269531],[169.45111274719238,-77.49668884277344],[166.77664375305176,-77.8577880859375],[166.54776191711426,-77.70668029785156],[166.88250923156738,-77.67195129394531],[166.2133502960205,-77.53863525390625],[166.63165473937988,-77.17280578613281],[167.71695137023926,-77.40583801269531]]],[[[-147.25222778320312,-77.16555786132812],[-147.53280639648438,-77.15194702148438],[-147.0625,-77.17388916015625],[-147.25222778320312,-77.16555786132812]]],[[[-147.89697265625,-77.42973327636719],[-148.86419677734375,-77.27084350585938],[-148.46444702148438,-77.070556640625],[-147.70889282226562,-77.189453125],[-147.59085083007812,-77.33168029785156],[-147.89697265625,-77.42973327636719]]],[[[-147.63363647460938,-77.10334777832031],[-147.83529663085938,-77.03472900390625],[-147.65472412109375,-77.04000854492188],[-147.63363647460938,-77.10334777832031]]],[[[-148.51168823242188,-76.90779113769531],[-148.20669555664062,-76.97805786132812],[-149.19473266601562,-76.9505615234375],[-148.51168823242188,-76.90779113769531]]],[[[-149.47836303710938,-76.89834594726562],[-149.072509765625,-77.10084533691406],[-150.73638916015625,-76.95112609863281],[-149.47836303710938,-76.89834594726562]]],[[[-146.71084594726562,-76.97917175292969],[-146.99166870117188,-76.85139465332031],[-146.22335815429688,-76.89750671386719],[-146.71084594726562,-76.97917175292969]]],[[[-148.53390502929688,-76.72250366210938],[-148.1572265625,-76.76528930664062],[-149.169189453125,-76.73222351074219],[-148.53390502929688,-76.72250366210938]]],[[[-149.83197021484375,-76.66445922851562],[-150.32086181640625,-76.78167724609375],[-150.701416015625,-76.71945190429688],[-149.83197021484375,-76.66445922851562]]],[[[-148.40945434570312,-76.689453125],[-148.77474975585938,-76.65278625488281],[-148.61917114257812,-76.61805725097656],[-148.40945434570312,-76.689453125]]],[[[-147.43362426757812,-76.68861389160156],[-147.95419311523438,-76.59112358093262],[-147.59140014648438,-76.59390258789062],[-147.43362426757812,-76.68861389160156]]],[[[-146.77224731445312,-76.71417236328125],[-147.25140380859375,-76.57695007324219],[-146.76083374023438,-76.570556640625],[-146.77224731445312,-76.71417236328125]]],[[[-147.34722900390625,-76.6138916015625],[-147.61807250976562,-76.55694580078125],[-147.4747314453125,-76.55751037597656],[-147.34722900390625,-76.6138916015625]]],[[[168.60333442687988,-76.2327880859375],[168.36108589172363,-76.16250610351562],[168.490816116333,-76.15861511230469],[168.60333442687988,-76.2327880859375]]],[[[-146.5855712890625,-76.30555725097656],[-147.278076171875,-76.11334228515625],[-146.776123046875,-76.08723258972168],[-146.57305908203125,-76.22029113769531],[-146.5855712890625,-76.30555725097656]]],[[[-146.79055786132812,-75.8558349609375],[-147.00363159179688,-75.8194580078125],[-146.85946655273438,-75.80555725097656],[-146.79055786132812,-75.8558349609375]]],[[[-145.15390014648438,-75.73667907714844],[-145.86727905273438,-75.60455322265625],[-145.57168579101562,-75.55278015136719],[-145.15390014648438,-75.73667907714844]]],[[[-143.00140380859375,-75.526123046875],[-143.28085327148438,-75.49166870117188],[-143.08224487304688,-75.46528625488281],[-143.00140380859375,-75.526123046875]]],[[[-132.3719482421875,-74.46417236328125],[-132.66195678710938,-74.41917419433594],[-132.20529174804688,-74.39250183105469],[-132.3719482421875,-74.46417236328125]]],[[[-131.38973999023438,-74.34695434570312],[-130.7447509765625,-74.41500854492188],[-132.00778198242188,-74.42916870117188],[-131.38973999023438,-74.34695434570312]]],[[[-127.39111328125,-74.58029174804688],[-128.16085815429688,-74.25418090820312],[-127.03611755371094,-74.39222717285156],[-127.39111328125,-74.58029174804688]]],[[[-117.11418151855469,-74.33416557312012],[-117.19833374023438,-74.32833862304688],[-116.75167846679688,-74.24722290039062],[-117.11418151855469,-74.33416557312012]]],[[[-20.46750259399414,-74.33029174804688],[-20.11944580078125,-74.85057067871094],[-21.603614807128906,-74.45083618164062],[-20.36944580078125,-74.12167358398438],[-20.46750259399414,-74.33029174804688]]],[[[-115.93028259277344,-73.96194458007812],[-116.27362060546875,-74.15362358093262],[-117.24111938476562,-74.1875],[-115.93028259277344,-73.96194458007812]]],[[[-122.14972686767578,-73.61445617675781],[-118.54945373535156,-73.92889404296875],[-122.13223266601562,-74.36805725097656],[-122.62999725341797,-74.32084655761719],[-122.41445922851562,-73.87055969238281],[-123.15939331054688,-73.73403930664062],[-122.14972686767578,-73.61445617675781]]],[[[169.8244342803955,-73.5955810546875],[169.388032913208,-73.5330810546875],[169.86859321594238,-73.28916931152344],[169.8244342803955,-73.5955810546875]]],[[[-78.04806518554688,-73.44223022460938],[-78.34611511230469,-73.25279235839844],[-77.63639831542969,-73.30000305175781],[-78.04806518554688,-73.44223022460938]]],[[[-126.11834716796875,-73.24722290039062],[-125.13417053222656,-73.71806335449219],[-124.23056030273438,-73.68917846679688],[-123.72416687011719,-74.10057067871094],[-125.25279235839844,-74.06390380859375],[-127.39250183105469,-73.41778564453125],[-126.11834716796875,-73.24722290039062]]],[[[-73.89111328125,-73.42500305175781],[-74.06417846679688,-73.3255615234375],[-73.4989013671875,-73.15362358093262],[-73.89111328125,-73.42500305175781]]],[[[-104.8650131225586,-73.2388916015625],[-105.24111938476562,-73.05473327636719],[-104.55029296875,-73.18667602539062],[-104.8650131225586,-73.2388916015625]]],[[[-89.74501037597656,-72.87556457519531],[-89.45668029785156,-72.91361999511719],[-90.37945556640625,-73.04779052734375],[-89.74501037597656,-72.87556457519531]]],[[[-74.2227783203125,-72.97611999511719],[-74.46556091308594,-73.64834594726562],[-76.09361267089844,-73.20945739746094],[-75.39527893066406,-73.06001281738281],[-75.72029113769531,-72.945556640625],[-75.38612365722656,-72.81806945800781],[-74.2227783203125,-72.97611999511719]]],[[[-93.75944519042969,-72.91166687011719],[-94.1380615234375,-72.83917236328125],[-93.80584716796875,-72.81500244140625],[-93.75944519042969,-72.91166687011719]]],[[[-98.14805603027344,-72.73001098632812],[-98.34361267089844,-72.69944763183594],[-97.82528686523438,-72.66334533691406],[-98.14805603027344,-72.73001098632812]]],[[[-99.7408447265625,-72.62361145019531],[-98.93028259277344,-72.67361450195312],[-100.85861206054688,-72.66555786132812],[-99.7408447265625,-72.62361145019531]]],[[[-95.33139038085938,-72.67195129394531],[-95.51834106445312,-72.64944458007812],[-94.69676208496094,-72.61419677734375],[-95.33139038085938,-72.67195129394531]]],[[[-91.33723258972168,-73.15695190429688],[-91.61723327636719,-72.604736328125],[-90.80639457702637,-72.59278869628906],[-91.33723258972168,-73.15695190429688]]],[[[-93.36528015136719,-72.65444946289062],[-93.46142578125,-72.58451843261719],[-93.1702880859375,-72.5755615234375],[-93.36528015136719,-72.65444946289062]]],[[[-61.038612365722656,-72.55972290039062],[-61.13500213623047,-72.54501342773438],[-60.970001220703125,-72.52751159667969],[-61.038612365722656,-72.55972290039062]]],[[[-78.42001342773438,-72.56777954101562],[-77.43917846679688,-72.588623046875],[-77.59445190429688,-72.91000366210938],[-78.80636596679688,-73.18165588378906],[-79.42167663574219,-72.96000671386719],[-78.8416748046875,-72.77139282226562],[-79.46139526367188,-72.56639099121094],[-79.24751281738281,-72.40251159667969],[-78.42001342773438,-72.56777954101562]]],[[[-68.81611633300781,-72.47445678710938],[-68.97750854492188,-72.46055603027344],[-68.59806823730469,-72.38583374023438],[-68.81611633300781,-72.47445678710938]]],[[[-60.336944580078125,-72.25750732421875],[-60.501943588256836,-72.19972229003906],[-60.34361267089844,-72.19416809082031],[-60.336944580078125,-72.25750732421875]]],[[[68.48201179504395,-72.27778625488281],[68.6931324005127,-72.08891296386719],[68.82002449035645,-72.165283203125],[68.48201179504395,-72.27778625488281]]],[[[69.79756355285645,-72.0330810546875],[69.7730884552002,-71.92362976074219],[69.9572925567627,-71.91864013671875],[69.79756355285645,-72.0330810546875]]],[[[-98.80307006835938,-71.88667297363281],[-98.29750061035156,-71.8719482421875],[-98.56056213378906,-72.13111877441406],[-98.19667053222656,-72.19917297363281],[-98.13630676269531,-71.89289855957031],[-97.6864013671875,-72.18194580078125],[-97.34945678710938,-71.86250305175781],[-96.65055847167969,-71.87333679199219],[-96.34263610839844,-72.002197265625],[-97.258056640625,-72.22222900390625],[-95.99514770507812,-72.08000183105469],[-95.82167053222656,-72.189453125],[-96.59611511230469,-72.28666687011719],[-95.67584228515625,-72.36056518554688],[-98.61611938476562,-72.56889343261719],[-102.56278991699219,-72.12472534179688],[-100.41445922851562,-71.88139343261719],[-100.06166076660156,-71.93513488769531],[-100.51055908203125,-72.02362060546875],[-100.23500061035156,-72.13084411621094],[-98.83306884765625,-72.13139343261719],[-99.30751037597656,-71.94389343261719],[-98.80307006835938,-71.88667297363281]]],[[[0.452028274536133,-71.1005859375],[0.239809036254883,-71.03361511230469],[0.586732864379883,-71.064453125],[0.452028274536133,-71.1005859375]]],[[[-60.53553009033203,-71.05635070800781],[-60.95916557312012,-70.94528198242188],[-60.624725341796875,-70.885009765625],[-60.53553009033203,-71.05635070800781]]],[[[-7.879444122314453,-70.73390197753906],[-8.043611526489258,-70.70001220703125],[-7.725276947021484,-70.71028137207031],[-7.879444122314453,-70.73390197753906]]],[[[-2.389999389648438,-70.751953125],[-1.982776641845703,-70.81639099121094],[-2.796388626098633,-71.03973388671875],[-3.454999923706055,-70.69306945800781],[-2.389999389648438,-70.751953125]]],[[[-73.68528747558594,-70.68028259277344],[-74.30612182617188,-71.01028442382812],[-76.635009765625,-71.06028747558594],[-73.68528747558594,-70.68028259277344]]],[[[2.050657272338867,-70.69972229003906],[1.895933151245117,-70.6461181640625],[2.216733932495117,-70.63639831542969],[2.050657272338867,-70.69972229003906]]],[[[-60.81945037841797,-70.6622314453125],[-61.15917205810547,-70.57583618164062],[-60.63139343261719,-70.54833984375],[-60.81945037841797,-70.6622314453125]]],[[[2.957578659057617,-70.625],[2.613157272338867,-70.50502014160156],[3.327329635620117,-70.46891784667969],[2.957578659057617,-70.625]]],[[[-6.040277481079102,-70.57917785644531],[-6.376682281494141,-70.47607421875],[-5.969852447509766,-70.4179515838623],[-6.040277481079102,-70.57917785644531]]],[[[-3.128055572509766,-70.50418090820312],[-3.329721450805664,-70.48333740234375],[-2.644166946411133,-70.415283203125],[-3.128055572509766,-70.50418090820312]]],[[[163.38614082336426,-70.38056945800781],[163.30529975891113,-70.34918212890625],[163.48333930969238,-70.35389709472656],[163.38614082336426,-70.38056945800781]]],[[[72.22700691223145,-70.61308288574219],[71.6881275177002,-70.33834838867188],[71.9300708770752,-70.29417419433594],[72.22700691223145,-70.61308288574219]]],[[[-1.790277481079102,-70.23194885253906],[-1.973054885864258,-70.18167114257812],[-1.897220611572266,-70.16889953613281],[-1.790277481079102,-70.23194885253906]]],[[[13.109552383422852,-70.0572509765625],[13.221185684204102,-70.13751220703125],[12.481744766235352,-70.11056518554688],[13.109552383422852,-70.0572509765625]]],[[[15.992849349975586,-70.1722412109375],[15.360345840454102,-70.02890014648438],[16.3620548248291,-70.01751708984375],[15.992849349975586,-70.1722412109375]]],[[[-61.38500213623047,-70.01528930664062],[-61.52806091308594,-69.96528625488281],[-61.292503356933594,-69.93417358398438],[-61.38500213623047,-70.01528930664062]]],[[[-74.84222412109375,-69.81584167480469],[-74.4525146484375,-70.02166557312012],[-75.86138916015625,-70.05528259277344],[-74.84222412109375,-69.81584167480469]]],[[[38.23148536682129,-69.67807006835938],[38.05619239807129,-69.63668823242188],[38.23148536682129,-69.64666557312012],[38.23148536682129,-69.67807006835938]]],[[[-72.35528564453125,-69.75750732421875],[-72.94528198242188,-69.60084533691406],[-72.04444885253906,-69.69306945800781],[-72.35528564453125,-69.75750732421875]]],[[[-62.04222869873047,-69.72000122070312],[-62.32722473144531,-69.10751342773438],[-61.71556091308594,-69.46861267089844],[-62.04222869873047,-69.72000122070312]]],[[[155.873628616333,-69.151123046875],[155.5258502960205,-69.00057983398438],[155.88369941711426,-69.05897521972656],[155.873628616333,-69.151123046875]]],[[[155.20083808898926,-69.04611206054688],[154.95392036437988,-69.01722717285156],[155.30890083312988,-68.98114013671875],[155.20083808898926,-69.04611206054688]]],[[[-70.15695190429688,-68.84861755371094],[-70.08416557312012,-69.26362609863281],[-68.37722778320312,-70.64944458007812],[-68.07139587402344,-71.63833618164062],[-68.39167785644531,-72.23390197753906],[-69.260009765625,-72.56417846679688],[-72.37611389160156,-72.727783203125],[-73.1944580078125,-72.43139457702637],[-70.52195739746094,-72.20777893066406],[-72.04501342773438,-72.1944580078125],[-70.94723510742188,-72.03889465332031],[-72.26750183105469,-71.6461181640625],[-72.86666870117188,-71.93417358398438],[-73.87918090820312,-71.820556640625],[-73.58111572265625,-72.04722595214844],[-74.0433349609375,-72.20889282226562],[-75.46612358093262,-71.85111999511719],[-75.14195251464844,-71.57778930664062],[-74.43583679199219,-71.69306945800781],[-74.38917541503906,-71.43417358398438],[-73.5291748046875,-71.64334106445312],[-73.67916870117188,-71.35806274414062],[-72.41195678710938,-71.33639526367188],[-73.15972900390625,-71.18501281738281],[-72.9263916015625,-71.1158447265625],[-70.6138916015625,-71.16639709472656],[-71.02084350585938,-70.8033447265625],[-72.46084594726562,-70.60195922851562],[-71.38917541503906,-70.23001098632812],[-71.81500244140625,-69.98417663574219],[-71.64584350585938,-69.51750183105469],[-72.25334167480469,-69.20722961425781],[-70.15695190429688,-68.84861755371094]]],[[[-90.59445190429688,-68.92584228515625],[-90.75140380859375,-68.79917907714844],[-90.48695373535156,-68.82778930664062],[-90.59445190429688,-68.92584228515625]]],[[[-63.44694519042969,-68.85139465332031],[-63.627784729003906,-68.79695129394531],[-63.41333770751953,-68.83723258972168],[-63.44694519042969,-68.85139465332031]]],[[[-60.718055725097656,-68.75473022460938],[-61.08167266845703,-68.67945861816406],[-60.82972717285156,-68.66111755371094],[-60.718055725097656,-68.75473022460938]]],[[[-67.50750732421875,-67.81001281738281],[-67.81529235839844,-67.68917846679688],[-67.08416557312012,-67.63139343261719],[-67.50750732421875,-67.81001281738281]]],[[[47.67118263244629,-67.58668518066406],[47.89804267883301,-67.59428405761719],[47.40786933898926,-67.62472534179688],[47.67118263244629,-67.58668518066406]]],[[[59.35531044006348,-67.33168029785156],[59.26925849914551,-67.290283203125],[59.41646766662598,-67.32057189941406],[59.35531044006348,-67.33168029785156]]],[[[164.78723335266113,-67.59529113769531],[164.56167793273926,-67.27166557312012],[164.84002876281738,-67.42362976074219],[164.78723335266113,-67.59529113769531]]],[[[58.64254951477051,-67.12641906738281],[58.52865028381348,-67.1177978515625],[58.67147254943848,-67.12001037597656],[58.64254951477051,-67.12641906738281]]],[[[58.86062049865723,-67.1219482421875],[58.77419471740723,-67.10861206054688],[58.82480049133301,-67.10224914550781],[58.86062049865723,-67.1219482421875]]],[[[50.34646797180176,-67.11639404296875],[50.13064765930176,-67.07418823242188],[50.25009346008301,-67.06779479980469],[50.34646797180176,-67.11639404296875]]],[[[48.79397773742676,-66.75613403320312],[48.39731788635254,-66.89028930664062],[48.29147529602051,-66.82000732421875],[48.79397773742676,-66.75613403320312]]],[[[86.0653247833252,-67.00112915039062],[85.3728199005127,-66.74668884277344],[85.8719654083252,-66.77389526367188],[86.18390083312988,-66.92251586914062],[86.0653247833252,-67.00112915039062]]],[[[86.49279975891113,-66.77473258972168],[86.30169868469238,-66.71113586425781],[86.73201179504395,-66.71223258972168],[86.49279975891113,-66.77473258972168]]],[[[-67.24417114257812,-66.74778747558594],[-67.54194641113281,-66.86973571777344],[-67.45973205566406,-66.69723510742188],[-67.24417114257812,-66.74778747558594]]],[[[-68.10028076171875,-67.39334106445312],[-68.56500244140625,-67.74806213378906],[-69.22889709472656,-67.54139709472656],[-67.58555603027344,-66.6138916015625],[-67.91084289550781,-66.84889221191406],[-67.67472839355469,-67.1591796875],[-68.10028076171875,-67.39334106445312]]],[[[99.29449653625488,-66.74861145019531],[99.21588325500488,-66.72306823730469],[99.52087593078613,-66.59002685546875],[99.29449653625488,-66.74861145019531]]],[[[163.10696601867676,-66.75613403320312],[162.9491901397705,-66.57223510742188],[163.11834907531738,-66.62306213378906],[163.10696601867676,-66.75613403320312]]],[[[85.33284187316895,-66.62861633300781],[85.1519947052002,-66.59028625488281],[85.2841968536377,-66.52029418945312],[85.33284187316895,-66.62861633300781]]],[[[98.77197456359863,-66.49197387695312],[98.60199165344238,-66.43333435058594],[98.86279487609863,-66.4544677734375],[98.77197456359863,-66.49197387695312]]],[[[97.22918891906738,-66.46640014648438],[97.08838081359863,-66.415283203125],[97.35310554504395,-66.42388916015625],[97.22918891906738,-66.46640014648438]]],[[[162.5680866241455,-66.43502807617188],[162.30029487609863,-66.18891906738281],[162.601411819458,-66.3505859375],[162.5680866241455,-66.43502807617188]]],[[[100.27307319641113,-66.19279479980469],[100.22973823547363,-66.14889526367188],[100.3516788482666,-66.14363098144531],[100.27307319641113,-66.19279479980469]]],[[[96.76751899719238,-66.25973510742188],[96.26001167297363,-66.18891906738281],[96.8477954864502,-66.12168884277344],[96.76751899719238,-66.25973510742188]]],[[[-66.73222351074219,-66.31056213378906],[-66.74305725097656,-66.11778259277344],[-66.5755615234375,-66.08805847167969],[-66.73222351074219,-66.31056213378906]]],[[[100.55475044250488,-66.14723205566406],[100.61865425109863,-66.04695129394531],[100.75641059875488,-66.07919311523438],[100.55475044250488,-66.14723205566406]]],[[[100.82141304016113,-66.02694702148438],[100.77282905578613,-66.01333618164062],[100.81726264953613,-65.99752807617188],[100.82141304016113,-66.02694702148438]]],[[[100.92755317687988,-66.00556945800781],[100.84362983703613,-65.98307800292969],[100.95892524719238,-65.96833801269531],[100.92755317687988,-66.00556945800781]]],[[[100.77057075500488,-65.86138916015625],[100.70807075500488,-65.83279418945312],[100.99810981750488,-65.80891418457031],[100.77057075500488,-65.86138916015625]]],[[[92.69893074035645,-65.79835510253906],[92.26892280578613,-65.76417541503906],[92.49505805969238,-65.6722412109375],[92.69893074035645,-65.79835510253906]]],[[[-65.66694641113281,-65.68722534179688],[-66.16111755371094,-65.86889457702637],[-65.9183349609375,-65.52972412109375],[-65.66694641113281,-65.68722534179688]]],[[[100.7549991607666,-65.67861938476562],[100.24695014953613,-65.5836181640625],[101.25665473937988,-65.50376892089844],[100.7549991607666,-65.67861938476562]]],[[[103.24279975891113,-65.29583740234375],[103.4725284576416,-65.45001220703125],[102.77393531799316,-65.14028930664062],[103.24279975891113,-65.29583740234375]]],[[[-59.43611145019531,-65.25584411621094],[-59.81305694580078,-65.10722351074219],[-59.533058166503906,-65.10945129394531],[-59.43611145019531,-65.25584411621094]]],[[[-63.14417266845703,-64.78140258789062],[-63.32444763183594,-64.91195678710938],[-63.55500030517578,-64.89306640625],[-63.14417266845703,-64.78140258789062]]],[[[-57.27916717529297,-64.55250358581543],[-57.488616943359375,-64.49639892578125],[-56.855003356933594,-64.338623046875],[-57.27916717529297,-64.55250358581543]]],[[[-63.306671142578125,-64.42861938476562],[-62.760284423828125,-64.56028747558594],[-63.64000701904297,-64.83389282226562],[-64.22056579589844,-64.67333984375],[-63.089447021484375,-64.29667663574219],[-63.306671142578125,-64.42861938476562]]],[[[-56.81500244140625,-64.31695556640625],[-56.758338928222656,-64.23779296875],[-56.5755615234375,-64.2197265625],[-56.81500244140625,-64.31695556640625]]],[[[-62.30000305175781,-64.4344482421875],[-62.70472717285156,-64.46612358093262],[-62.480560302734375,-64.0433349609375],[-62.01167297363281,-64.21417236328125],[-62.30000305175781,-64.4344482421875]]],[[[-57.815834045410156,-63.961395263671875],[-57.03334045410156,-64.17250061035156],[-57.91278076171875,-64.44528198242188],[-58.23944854736328,-64.32501220703125],[-58.080833435058594,-64.08473205566406],[-58.428611755371094,-64.11334228515625],[-57.815834045410156,-63.961395263671875]]],[[[-57.570556640625,-63.78778076171875],[-57.045562744140625,-63.822784423828125],[-57.694725036621094,-63.81639099121094],[-57.570556640625,-63.78778076171875]]],[[[-60.73833465576172,-63.86833953857422],[-60.76416778564453,-63.660560607910156],[-60.531394958496094,-63.65167236328125],[-60.73833465576172,-63.86833953857422]]],[[[-55.97666931152344,-63.581390380859375],[-56.20555877685547,-63.452781677246094],[-55.70777893066406,-63.45250701904297],[-55.97666931152344,-63.581390380859375]]],[[[-62.15416717529297,-63.32417297363281],[-62.260284423828125,-63.25389099121094],[-61.94333457946777,-63.28166961669922],[-62.15416717529297,-63.32417297363281]]],[[[-56.94639587402344,-63.4505615234375],[-56.72138977050781,-63.5947265625],[-57.3800048828125,-63.46055603027344],[-58.60083770751953,-63.948890686035156],[-58.77864074707031,-64.53581237792969],[-59.49305725097656,-64.31611633300781],[-59.505279541015625,-64.5372314453125],[-59.91889190673828,-64.4122314453125],[-61.959449768066406,-65.18028259277344],[-62.08972930908203,-65.44029235839844],[-61.68305969238281,-65.53861999511719],[-62.45972442626953,-65.90472412109375],[-61.872779846191406,-66.17195129394531],[-60.55750274658203,-65.94528198242188],[-60.93695068359375,-66.260009765625],[-61.41667175292969,-66.12528991699219],[-61.713890075683594,-66.46917724609375],[-62.18139457702637,-66.18028259277344],[-62.885284423828125,-66.26278686523438],[-62.44361114501953,-66.43028259277344],[-62.60889434814453,-66.72834777832031],[-63.675559997558594,-66.21833801269531],[-64.19667053222656,-66.72029113769531],[-63.743614196777344,-66.89167785644531],[-64.83778381347656,-66.95140075683594],[-64.77056884765625,-67.31723022460938],[-65.6138916015625,-67.55917358398438],[-65.290283203125,-67.67333984375],[-65.61778259277344,-67.8800048828125],[-65.32917785644531,-67.9747314453125],[-65.72361755371094,-68.14805603027344],[-64.76834106445312,-68.12278747558594],[-65.5966796875,-68.34750366210938],[-65.0916748046875,-68.44195556640625],[-65.31333923339844,-68.71139526367188],[-63.85778045654297,-68.84278869628906],[-64.3900146484375,-68.51333618164062],[-62.72834014892578,-68.41000366210938],[-63.97416687011719,-68.53639221191406],[-63.21055603027344,-68.78695678710938],[-63.70667266845703,-68.74250793457031],[-63.36805725097656,-69.05000305175781],[-63.638893127441406,-69.22723388671875],[-62.47583770751953,-69.45306396484375],[-62.63500213623047,-69.85334777832031],[-61.940834045410156,-70.22917175292969],[-62.49083709716797,-70.38056945800781],[-61.48445129394531,-70.52027893066406],[-62.12889099121094,-70.86557006835938],[-61.380279541015625,-70.81529235839844],[-60.9425048828125,-71.15834045410156],[-61.929725646972656,-71.65640258789062],[-60.90416717529297,-71.73638916015625],[-62.55250358581543,-72.04750061035156],[-60.86583709716797,-72.00306701660156],[-61.07472229003906,-72.16361999511719],[-60.852500915527344,-72.38890075683594],[-61.54972839355469,-72.42279052734375],[-61.270835876464844,-72.70028686523438],[-60.616111755371094,-72.64334106445312],[-60.617225646972656,-73.02862358093262],[-59.774169921875,-72.90028381347656],[-59.849449157714844,-73.23306274414062],[-60.59972381591797,-73.36029052734375],[-61.91944885253906,-73.14306640625],[-61.43639373779297,-73.34361267089844],[-61.836669921875,-73.36639404296875],[-61.609169006347656,-73.54611206054688],[-60.58778381347656,-73.70611572265625],[-61.76250457763672,-73.91389465332031],[-61.03639221191406,-74.09834289550781],[-61.755279541015625,-74.30639457702637],[-61.88750457763672,-74.83222961425781],[-62.531394958496094,-74.98251342773438],[-63.24583435058594,-74.60417175292969],[-63.0513916015625,-74.89527893066406],[-63.98944854736328,-75.008056640625],[-63.09584045410156,-75.13084411621094],[-64.44778442382812,-75.29779052734375],[-63.0947265625,-75.3255615234375],[-63.429168701171875,-75.4505615234375],[-69.38528442382812,-76.29611206054688],[-70.47639465332031,-76.70777893066406],[-75.4444580078125,-76.54640197753906],[-76.38056945800781,-76.06500244140625],[-77.77166557312012,-75.91889953613281],[-78.47666931152344,-76.4072265625],[-75.63278198242188,-77.50862121582031],[-72.83973693847656,-77.6400146484375],[-74.85334777832031,-78.14111328125],[-81.4969482421875,-77.65779113769531],[-80.60556030273438,-77.88639831542969],[-81.47000122070312,-77.89723205566406],[-77.48750305175781,-78.52667236328125],[-78.95750427246094,-78.81333923339844],[-84.1077880859375,-78.36083984375],[-80.63555908203125,-79.61917114257812],[-80.20278930664062,-79.22889709472656],[-77.02944946289062,-79.27944946289062],[-76.0836181640625,-79.64584350585938],[-77.32194519042969,-80.01139831542969],[-79.84945678710938,-79.95445251464844],[-76.08944702148438,-80.19723510742188],[-74.69389343261719,-80.69723510742188],[-59.64805603027344,-82.43389892578125],[-58.783058166503906,-82.64500427246094],[-59.07972717285156,-82.96583557128906],[-58.210838317871094,-83.03334045410156],[-53.72583770751953,-82.15028381347656],[-43.084449768066406,-81.85139465332031],[-41.4888916015625,-81.38334655761719],[-28.319446563720703,-80.27694702148438],[-28.0625,-80.00473022460938],[-30.210556030273438,-79.66667175292969],[-27.085556030273438,-79.01333618164062],[-33.00111389160156,-79.45390319824219],[-36.30278015136719,-78.7791748046875],[-33.88611602783203,-77.66056823730469],[-28.305278778076172,-76.56529235839844],[-17.758056640625,-75.729736328125],[-18.256389617919922,-75.49583435058594],[-17.14722442626953,-74.78472900390625],[-13.704723358154297,-73.94195556640625],[-16.326114654541016,-74.06390380859375],[-16.919170379638672,-73.97611999511719],[-16.069168090820312,-73.74751281738281],[-16.89889144897461,-73.77305603027344],[-16.02361297607422,-73.32028198242188],[-13.731111526489258,-73.02084350585938],[-14.469167709350586,-72.79667663574219],[-13.406112670898438,-72.82305908203125],[-11.657777786254883,-72.32695007324219],[-11.325834274291992,-71.96501159667969],[-12.276945114135742,-71.37750244140625],[-11.556507110595703,-71.27882385253906],[-11.592779159545898,-71.56195068359375],[-11.019445419311523,-71.6572265625],[-10.048612594604492,-71.11138916015625],[-10.430000305175781,-70.98695373535156],[-9.878713607788086,-70.90097045898438],[-8.93083381652832,-71.23361206054688],[-8.366945266723633,-71.82583618164062],[-7.337778091430664,-71.69195556640625],[-7.723333358764648,-71.42916870117188],[-6.021110534667969,-70.69972229003906],[-5.441110610961914,-70.88250732421875],[-6.103889465332031,-71.14445495605469],[-6.009166717529297,-71.41889953613281],[-2.261667251586914,-71.17083740234375],[-2.093889236450195,-71.48611450195312],[-1.053333282470703,-71.27667236328125],[-0.7772216796875,-71.38917541503906],[-0.923055648803711,-71.58917236328125],[-0.29749870300293,-71.65888977050781],[2.803159713745117,-70.84695434570312],[6.699522018432617,-70.58639526367188],[7.557310104370117,-70.16835021972656],[8.480646133422852,-70.47724914550781],[9.090387344360352,-70.31834411621094],[8.682855606079102,-70.074462890625],[11.270624160766602,-70.71028137207031],[12.046747207641602,-70.71751403808594],[12.740350723266602,-70.2811279296875],[14.165643692016602,-70.15890502929688],[15.705926895141602,-70.27862358093262],[18.036489486694336,-69.96917724609375],[23.246755599975586,-70.54641723632812],[31.08342170715332,-69.77389526367188],[32.90232276916504,-69.27694702148438],[33.44504737854004,-68.95724487304688],[33.42423439025879,-68.65141296386719],[34.14035987854004,-68.4827880859375],[36.41452980041504,-69.314453125],[36.12644386291504,-69.53361511230469],[36.72257423400879,-69.72807312011719],[37.91617774963379,-69.25141906738281],[37.85093116760254,-69.53390502929688],[37.14505958557129,-69.66474914550781],[38.23923683166504,-69.9927978515625],[38.56449317932129,-69.50057983398438],[38.65036964416504,-69.98863220214844],[39.70176124572754,-69.64863586425781],[39.76035499572754,-68.9544677734375],[41.10312843322754,-68.52389526367188],[46.30893135070801,-67.64169311523438],[46.24643135070801,-67.35751342773438],[46.55143165588379,-67.27725219726562],[47.44895362854004,-67.41780090332031],[47.00950050354004,-67.55030822753906],[47.39560890197754,-67.72251892089844],[48.21701240539551,-67.63444519042969],[49.16726875305176,-67.38336181640625],[48.26285743713379,-67.16752624511719],[49.16397285461426,-66.86280822753906],[49.15170478820801,-67.088623046875],[50.68948554992676,-67.18139457702637],[50.16977119445801,-66.74305725097656],[50.41311836242676,-66.44197082519531],[53.77896308898926,-65.84002685546875],[55.61923408508301,-66.0069580078125],[57.31197547912598,-66.56333923339844],[56.72952461242676,-66.901123046875],[59.11062049865723,-67.4122314453125],[69.6447925567627,-67.75390625],[70.10200691223145,-68.52389526367188],[69.2920093536377,-69.102783203125],[69.74312019348145,-69.36308288574219],[68.87117195129395,-69.37947082519531],[69.34004402160645,-69.63862609863281],[69.2053394317627,-69.86390686035156],[68.0947437286377,-69.87947082519531],[67.6461353302002,-70.38639831542969],[68.59395027160645,-70.77058410644531],[68.85029792785645,-70.53224182128906],[68.66169929504395,-70.3677978515625],[69.1447925567627,-70.33139038085938],[69.2439136505127,-70.67057800292969],[67.60530281066895,-71.58308410644531],[67.9011402130127,-71.64447021484375],[67.33755683898926,-72.06333923339844],[68.9364185333252,-72.42500305175781],[70.86494636535645,-71.93014526367188],[71.44978523254395,-71.54611206054688],[71.24812507629395,-71.38945007324219],[71.50447273254395,-70.95390319824219],[72.86311531066895,-70.43278503417969],[72.6156177520752,-70.20361328125],[72.9011402130127,-70.02195739746094],[77.74727058410645,-69.11697387695312],[78.11641120910645,-68.45973205566406],[82.0572681427002,-67.6722412109375],[81.4697437286377,-67.50529479980469],[82.01448249816895,-67.25167846679688],[82.66504096984863,-67.39389038085938],[83.40339851379395,-67.15667724609375],[85.79168891906738,-67.17778015136719],[87.50251960754395,-66.89474487304688],[88.10949897766113,-66.65252685546875],[88.22723579406738,-66.03639221191406],[88.96722602844238,-66.76139831542969],[92.00531196594238,-66.53390502929688],[97.56445503234863,-66.74057006835938],[98.26196479797363,-66.51611328125],[99.28308296203613,-66.88084411621094],[100.95392036437988,-66.08084106445312],[102.62616157531738,-65.901123046875],[107.80478096008301,-66.39836120605469],[108.82422065734863,-66.83113098144531],[110.62976264953613,-66.48667907714844],[110.89172554016113,-66.06362915039062],[113.31534004211426,-65.71334838867188],[114.43142890930176,-66.17947387695312],[114.51835823059082,-66.4727783203125],[116.18004035949707,-66.36668395996094],[117.76700019836426,-66.98974609375],[122.18335914611816,-66.54780578613281],[125.19001960754395,-66.73419189453125],[126.35616493225098,-66.27972412109375],[126.98835945129395,-66.45358276367188],[126.92865180969238,-66.83445739746094],[128.83477973937988,-67.14251708984375],[130.35199165344238,-66.22584533691406],[134.24530220031738,-66.20112609863281],[134.43640327453613,-66.00141906738281],[134.10061836242676,-65.12306213378906],[134.437837600708,-64.92613220214844],[135.27224922180176,-65.4364013671875],[134.94778633117676,-66.09306335449219],[142.56640815734863,-66.99417114257812],[143.40002632141113,-66.85113525390625],[144.58557319641113,-67.24528503417969],[145.40445137023926,-67.01722717285156],[145.87530708312988,-67.19586181640625],[145.31500434875488,-67.61334228515625],[146.6427936553955,-67.70945739746094],[147.1508502960205,-67.99085998535156],[146.9533405303955,-68.14169311523438],[148.02945137023926,-67.84446716308594],[148.64807319641113,-67.98919677734375],[148.21722602844238,-68.12724304199219],[148.81335639953613,-68.33528137207031],[150.992525100708,-68.39085388183594],[151.1850299835205,-68.98002624511719],[153.76861763000488,-68.9222412109375],[153.77835273742676,-68.3436279296875],[154.68585395812988,-68.61500358581543],[154.28668403625488,-68.86308288574219],[154.85669136047363,-69.10252380371094],[156.33612251281738,-69.24057006835938],[157.23639106750488,-68.94252014160156],[160.96890449523926,-70.25556945800781],[162.75390815734863,-70.28030395507812],[163.520845413208,-70.67500305175781],[163.78528022766113,-70.62806701660156],[163.55389595031738,-70.46528625488281],[166.77166938781738,-70.61167907714844],[166.46304512023926,-70.70195007324219],[167.76751899719238,-70.78083801269531],[170.27224922180176,-71.66001892089844],[170.21527290344238,-71.28279113769531],[170.45303535461426,-71.35166931152344],[170.99444770812988,-71.86419677734375],[170.129976272583,-72.05140686035156],[169.87164497375488,-72.37919616699219],[170.3041706085205,-72.30084228515625],[170.3222370147705,-72.58030700683594],[169.26642036437988,-73.08390808105469],[169.07916450500488,-73.52752685546875],[167.56167793273926,-73.40335083007812],[165.54858589172363,-73.93251037597656],[166.12915229797363,-74.12724304199219],[164.780855178833,-74.136962890625],[165.33331489562988,-74.67280578613281],[164.14251899719238,-74.61611938476562],[163.65667915344238,-74.77445983886719],[163.871675491333,-74.95335388183594],[162.53973579406738,-75.10891723632812],[163.13696479797363,-75.93667602539062],[162.33780097961426,-76.167236328125],[162.875581741333,-76.24778747558594],[162.93225288391113,-76.58308410644531],[162.623628616333,-76.61946105957031],[163.06973457336426,-76.73085021972656],[162.33279609680176,-76.951416015625],[163.23834419250488,-77.04139709472656],[163.89697456359863,-77.46669006347656],[163.61084175109863,-77.69612121582031],[164.56500434875488,-77.73638916015625],[164.20669746398926,-78.14389038085938],[165.5400104522705,-78.00335693359375],[165.68359565734863,-78.39169311523438],[167.26944160461426,-78.65583801269531],[164.49444770812988,-78.56974792480469],[160.49417304992676,-79.02085876464844],[160.04055976867676,-79.15583801269531],[160.73806953430176,-79.45307922363281],[159.09280586242676,-79.97111511230469],[160.52444648742676,-80.04139709472656],[158.05725288391113,-80.28056335449219],[160.89196968078613,-80.37750244140625],[159.75695991516113,-80.56974792480469],[161.17447090148926,-80.63555908203125],[160.01556587219238,-80.78030395507812],[160.84390449523926,-80.89306640625],[160.50308418273926,-80.95278930664062],[160.839448928833,-81.07807922363281],[160.62613105773926,-81.20501708984375],[162.19391059875488,-81.29780578613281],[160.39111518859863,-81.52140808105469],[162.2758502960205,-81.6622314453125],[163.859468460083,-82.17417907714844],[163.446138381958,-82.26502990722656],[168.692476272583,-83.14640808105469],[167.46972846984863,-83.43917846679688],[169.250825881958,-83.33001708984375],[172.31860542297363,-83.59722900390625],[171.90503120422363,-83.80169677734375],[180.00000190734863,-84.30224609375],[180.00000190734863,-90],[-180,-90],[-180,-84.30534362792969],[-157.48333740234375,-85.44862365722656],[-150.23947143554688,-85.463623046875],[-148.13833618164062,-85.09083557128906],[-139.66140747070312,-85.24501037597656],[-138.58944702148438,-84.98472595214844],[-149.29473876953125,-84.56195068359375],[-153.05307006835938,-84.01278686523438],[-153.00750732421875,-83.08750915527344],[-151.794189453125,-82.57778930664062],[-154.89141845703125,-81.90501403808594],[-153.98919677734375,-81.62918090820312],[-154.20501708984375,-81.55223083496094],[-156.96002197265625,-81.25167846679688],[-154.92169189453125,-81.001953125],[-148.41336059570312,-81.35751342773438],[-145.524169921875,-80.46055603027344],[-146.81195068359375,-79.88751220703125],[-155.90640258789062,-78.7197265625],[-153.75030517578125,-78.30833435058594],[-157.9102783203125,-78.001953125],[-158.17584228515625,-77.85972595214844],[-157.69696044921875,-77.57139587402344],[-157.75308227539062,-77.10806274414062],[-156.48333740234375,-77.35861206054688],[-155.86138916015625,-77.08445739746094],[-153.790283203125,-77.17472839355469],[-153.0836181640625,-77.28666687011719],[-153.10641479492188,-77.49722290039062],[-152.06112670898438,-77.32528686523438],[-149.6622314453125,-77.76112365722656],[-149.08724975585938,-77.69612121582031],[-149.4141845703125,-77.57084655761719],[-148.7327880859375,-77.62556457519531],[-148.5855712890625,-77.59445190429688],[-148.58111572265625,-77.50445556640625],[-147.59140014648438,-77.42222595214844],[-147.49307250976562,-77.29695129394531],[-147.07168579101562,-77.37278747558594],[-147.0322265625,-77.22084045410156],[-146.26861572265625,-77.46640014648438],[-145.87890625,-77.30639457702637],[-146.22750854492188,-77.16500854492188],[-145.84280395507812,-77.11418151855469],[-146.3013916015625,-76.99917602539062],[-145.29888916015625,-77.0291748046875],[-146.10223388671875,-76.84001159667969],[-145.45639038085938,-76.76028442382812],[-146.9322509765625,-76.45195007324219],[-149.50613403320312,-76.38751220703125],[-148.10128784179688,-76.09565734863281],[-146.49166870117188,-76.36750793457031],[-145.47946166992188,-76.44334411621094],[-146.2952880859375,-76.03973388671875],[-134.30389404296875,-74.53279113769531],[-133.26251220703125,-74.84722900390625],[-121.47834777832031,-74.74250793457031],[-118.53167724609375,-74.61361694335938],[-117.74305725097656,-74.30862426757812],[-117.39695739746094,-74.53083801269531],[-114.6977767944336,-74.46917724609375],[-114.81001281738281,-74.104736328125],[-114.00361633300781,-73.88917541503906],[-113.1864013671875,-74.16889953613281],[-113.4336166381836,-74.47222900390625],[-112.93028259277344,-74.45500183105469],[-113.55555725097656,-74.63444519042969],[-112.65416717529297,-74.85861206054688],[-111.34306335449219,-74.75944519042969],[-111.72445678710938,-74.58723258972168],[-111.38583374023438,-74.46223258972168],[-111.50389099121094,-74.19168090820312],[-110.15471458435059,-74.2841796875],[-109.92888641357422,-74.76139831542969],[-110.961669921875,-75.15779113769531],[-110.383056640625,-75.30612182617188],[-99.51028442382812,-75.09251403808594],[-100.85166931152344,-74.81472778320312],[-100.151123046875,-74.76083374023438],[-100.51555633544922,-74.67111206054688],[-100.24806213378906,-74.4908447265625],[-101.33194732666016,-74.48056030273438],[-101.65834045410156,-73.9989013671875],[-102.90139770507812,-73.87583923339844],[-103.01334381103516,-73.62918090820312],[-99.17556762695312,-73.61917114257812],[-103.03611755371094,-73.32640075683594],[-103.60334777832031,-72.89195251464844],[-103.17611694335938,-72.73333740234375],[-102.09916687011719,-73.08473205566406],[-90.86111450195312,-73.32667541503906],[-89.32112121582031,-73.05416870117188],[-89.5372314453125,-72.63362121582031],[-89.26112365722656,-72.63945007324219],[-88.33584594726562,-72.81611633300781],[-88.70916557312012,-73.17945861816406],[-86.84083557128906,-73.33639526367188],[-85.9666748046875,-73.04139709472656],[-85.47084045410156,-73.3497314453125],[-85.5997314453125,-73.55833435058594],[-82.13417053222656,-73.94334411621094],[-81.04139709472656,-73.71556091308594],[-81.27528381347656,-73.36944580078125],[-80.51918029785156,-73.44639587402344],[-80.695556640625,-73.05056762695312],[-78.95889282226562,-73.39250183105469],[-78.78973388671875,-73.69306945800781],[-76.61834716796875,-73.57667541503906],[-76.96278381347656,-73.87306213378906],[-69.4283447265625,-73.19723510742188],[-66.79722595214844,-72.40779113769531],[-66.85917663574219,-71.89556884765625],[-67.5372314453125,-71.45472717285156],[-67.40028381347656,-71.04000854492188],[-67.70390319824219,-70.59306335449219],[-68.83805847167969,-69.417236328125],[-66.65779113769531,-69.01779174804688],[-67.49444580078125,-68.81556701660156],[-66.93223571777344,-68.77389526367188],[-67.16555786132812,-68.2933349609375],[-66.58973693847656,-68.23806762695312],[-67.1572265625,-68.01055908203125],[-66.42723083496094,-67.53334045410156],[-67.6239013671875,-67.55361938476562],[-67.48583984375,-67.07722473144531],[-66.40472412109375,-66.88555908203125],[-66.49722290039062,-66.62251281738281],[-65.68972778320312,-66.125],[-64.45333862304688,-65.98167419433594],[-64.65972900390625,-65.74028015136719],[-63.71278381347656,-65.50250244140625],[-64.05307006835938,-65.42195129394531],[-63.87944793701172,-65.01834106445312],[-63.09056091308594,-65.13389587402344],[-62.93805694580078,-64.79750061035156],[-62.31945037841797,-64.85890197753906],[-62.61778259277344,-64.7550048828125],[-62.45361328125,-64.58917236328125],[-61.935279846191406,-64.69056701660156],[-60.94194793701172,-64.27751159667969],[-60.991668701171875,-64.03584289550781],[-59.445838928222656,-63.89305877685547],[-58.91083526611328,-63.533058166503906],[-57.20500183105469,-63.20555877685547],[-56.94639587402344,-63.4505615234375]]],[[[-55.470001220703125,-63.143333435058594],[-55.002784729003906,-63.28388977050781],[-56.5433349609375,-63.36444854736328],[-55.470001220703125,-63.143333435058594]]],[[[-56.26500701904297,-63.16944885253906],[-56.58472442626953,-63.035003662109375],[-55.97084045410156,-63.05445098876953],[-56.26500701904297,-63.16944885253906]]],[[[-60.471839904785156,-62.90089797973633],[-60.58000183105469,-63.008056640625],[-60.74248123168945,-62.97399139404297],[-60.471839904785156,-62.90089797973633]]],[[[-62.69139099121094,-63.095001220703125],[-62.48944854736328,-62.921112060546875],[-62.26055908203125,-62.88166809082031],[-62.69139099121094,-63.095001220703125]]],[[[-61.358612060546875,-62.81361389160156],[-61.47917175292969,-62.75389099121094],[-61.15055847167969,-62.7086181640625],[-61.358612060546875,-62.81361389160156]]],[[[-60.51667022705078,-62.55389404296875],[-59.81694793701172,-62.614173889160156],[-61.17250061035156,-62.57500457763672],[-60.51667022705078,-62.55389404296875]]],[[[-59.665557861328125,-62.55694580078125],[-59.97917175292969,-62.450836181640625],[-59.54222869873047,-62.49861145019531],[-59.665557861328125,-62.55694580078125]]],[[[-59.439170837402344,-62.44722557067871],[-59.67833709716797,-62.3638916015625],[-59.32750701904297,-62.37139129638672],[-59.439170837402344,-62.44722557067871]]],[[[-58.99250030517578,-62.3477783203125],[-59.208892822265625,-62.285560607910156],[-58.81639099121094,-62.298057556152344],[-58.99250030517578,-62.3477783203125]]],[[[-57.6219482421875,-61.90972900390625],[-58.98638916015625,-62.214447021484375],[-58.40028381347656,-61.93861389160156],[-57.6219482421875,-61.90972900390625]]],[[[-55.09222412109375,-61.098060607910156],[-54.646392822265625,-61.09278106689453],[-55.49444580078125,-61.126670837402344],[-55.09222412109375,-61.098060607910156]]],[[[-54.04695129394531,-61.269447326660156],[-54.2005615234375,-61.236114501953125],[-54.0322265625,-61.08805847167969],[-54.04695129394531,-61.269447326660156]]],[[[-44.428062438964844,-60.72333526611328],[-44.78472900390625,-60.73445129394531],[-44.531394958496094,-60.675559997558594],[-44.428062438964844,-60.72333526611328]]],[[[-45.005279541015625,-60.72528076171875],[-45.07111358642578,-60.63111114501953],[-45.025840759277344,-60.641944885253906],[-45.005279541015625,-60.72528076171875]]],[[[-45.55083465576172,-60.54722595214844],[-45.14527893066406,-60.76611328125],[-46.02361297607422,-60.61083984375],[-45.55083465576172,-60.54722595214844]]]]}},{"type":"Feature","properties":{"name":"Bouvet Island","iso2":"BV","iso3":"BVT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[3.361389,-54.462784],[3.366944,-54.399727],[3.483611,-54.402229],[3.361389,-54.462784]]]]}},{"type":"Feature","properties":{"name":"French Southern and Antarctic Lands","iso2":"TF","iso3":"ATF"},"geometry":{"type":"MultiPolygon","coordinates":[[[[69.81277656555176,-49.678062438964844],[69.76193428039551,-49.65888977050781],[69.79500007629395,-49.64722442626953],[69.81277656555176,-49.678062438964844]]],[[[68.78915596008301,-49.361671447753906],[68.64444160461426,-49.34361267089844],[68.80166816711426,-49.328338623046875],[68.78915596008301,-49.361671447753906]]],[[[69.60666084289551,-49.20777893066406],[69.53305244445801,-49.19667053222656],[69.67833137512207,-49.15306091308594],[69.60666084289551,-49.20777893066406]]],[[[69.26471138000488,-49.09111785888672],[69.21638679504395,-48.96722412109375],[69.36888313293457,-48.886390686035156],[69.26471138000488,-49.09111785888672]]],[[[69.15222358703613,-48.988059997558594],[69.22221565246582,-48.856117248535156],[69.24249458312988,-48.89250183105469],[69.15222358703613,-48.988059997558594]]],[[[69.4911060333252,-48.882781982421875],[69.40193367004395,-48.834449768066406],[69.51721382141113,-48.86028289794922],[69.4911060333252,-48.882781982421875]]],[[[69.00110054016113,-48.79750061035156],[69.06305122375488,-49.119728088378906],[69.10388374328613,-48.99583435058594],[69.21721076965332,-49.12555694580078],[69.62193489074707,-48.978057861328125],[69.2824878692627,-49.18639373779297],[69.58276557922363,-49.30445098876953],[70.32388496398926,-49.05083465576172],[70.5666675567627,-49.24500274658203],[69.77472114562988,-49.39417266845703],[70.25360298156738,-49.69111633300781],[69.6433277130127,-49.50139617919922],[68.79777717590332,-49.721946716308594],[69.00110054016113,-48.79750061035156]],[[69.9044361114502,-49.47722625732422],[69.82527351379395,-49.42583465576172],[69.84305000305176,-49.459449768066406],[69.9044361114502,-49.47722625732422]],[[70.01193428039551,-49.57194519042969],[69.92109870910645,-49.5130615234375],[69.83554267883301,-49.508056640625],[70.01193428039551,-49.57194519042969]]],[[[68.6755542755127,-48.643890380859375],[68.60611152648926,-48.63972473144531],[68.66861152648926,-48.62805938720703],[68.6755542755127,-48.643890380859375]]],[[[68.79777717590332,-48.61500358581543],[68.78721809387207,-48.57722473144531],[68.82470893859863,-48.570556640625],[68.79777717590332,-48.61500358581543]]],[[[52.25444221496582,-46.45750427246094],[52.088335037231445,-46.41111755371094],[52.257219314575195,-46.37805938720703],[52.25444221496582,-46.45750427246094]]],[[[51.81944465637207,-46.45361328125],[51.65194129943848,-46.374168395996094],[51.78000068664551,-46.34111785888672],[51.81944465637207,-46.45361328125]]],[[[50.27221870422363,-46.13139343261719],[50.17694282531738,-46.0625],[50.27388954162598,-46.05083465576172],[50.27221870422363,-46.13139343261719]]],[[[77.5294361114502,-38.73778533935547],[77.49971199035645,-38.731117248535156],[77.50610542297363,-38.703895568847656],[77.5294361114502,-38.73778533935547]]],[[[77.55415534973145,-37.90277862548828],[77.48388862609863,-37.83528137207031],[77.55444526672363,-37.82250213623047],[77.55415534973145,-37.90277862548828]]],[[[42.75777626037598,-17.075000762939453],[42.72110939025879,-17.055557250976562],[42.75694465637207,-17.059722900390625],[42.75777626037598,-17.075000762939453]]]]}},{"type":"Feature","properties":{"name":"Heard Island and McDonald Islands","iso2":"HM","iso3":"HMD"},"geometry":{"type":"MultiPolygon","coordinates":[[[[73.77388,-53.125031],[73.474442,-53.194168],[73.234436,-52.987785],[73.77388,-53.125031]]]]}},{"type":"Feature","properties":{"name":"British Indian Ocean Territory","iso2":"IO","iso3":"IOT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[72.48719800000012,-7.381944],[72.35914600000015,-7.265278],[72.4488680000002,-7.234445],[72.48719800000012,-7.381944]]],[[[71.3483279999999,-6.658889],[71.343323,-6.656667],[71.36526500000011,-6.651667],[71.3483279999999,-6.658889]]],[[[71.266388,-6.391945],[71.25860600000013,-6.382222],[71.266098,-6.366666],[71.266388,-6.391945]]],[[[71.347763,-6.206944],[71.338593,-6.195833],[71.360809,-6.174167],[71.347763,-6.206944]]],[[[71.7824860000002,-5.440277],[71.759995,-5.431389],[71.766388,-5.429722],[71.7824860000002,-5.440277]]],[[[72.216385,-5.362222],[72.207764,-5.354445],[72.20860300000012,-5.348056],[72.216385,-5.362222]]],[[[72.23248300000014,-5.319722],[72.2211,-5.335556],[72.228043,-5.315833],[72.23248300000014,-5.319722]]],[[[71.74220300000016,-5.291111],[71.74054,-5.271111],[71.748596,-5.265556],[71.74220300000016,-5.291111]]],[[[71.86943100000016,-5.257778],[71.87025500000013,-5.249722],[71.882202,-5.256111],[71.86943100000016,-5.257778]]]]}},{"type":"Feature","properties":{"name":"Christmas Island","iso2":"CX","iso3":"CXR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[105.701401,-10.51097],[105.628998,-10.43731],[105.736603,-10.38408],[105.701401,-10.51097]]]]}},{"type":"Feature","properties":{"name":"United States Minor Outlying Islands","iso2":"UM","iso3":"UMI"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-160.021149,-0.398056],[-160.048615,-0.383611],[-160.017792,-0.374722],[-160.021149,-0.398056]]],[[[-176.456146,0.215833],[-176.468323,0.222222],[-176.453918,0.226111],[-176.456146,0.215833]]],[[[-176.632202,0.793055],[-176.64447,0.795555],[-176.643097,0.812778],[-176.632202,0.793055]]],[[[-169.522522,16.728882],[-169.543884,16.726379000000108],[-169.531708,16.732491],[-169.522522,16.728882]]],[[[166.646362,19.279442000000145],[166.607452,19.304996],[166.627594,19.324577],[166.646362,19.279442000000145]]],[[[-177.334442,28.194157],[-177.321686,28.213608],[-177.317505,28.200829000000155],[-177.334442,28.194157]]],[[[-177.388062,28.18637800000012],[-177.389771,28.212769],[-177.358032,28.219162],[-177.388062,28.18637800000012]]]]}},{"type":"Feature","properties":{"name":"Vanuatu","iso2":"VU","iso3":"VUT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[169.846069,-20.252224],[169.745514,-20.149445],[169.886658,-20.170555],[169.846069,-20.252224]]],[[[170.217468,-19.559444],[170.205231,-19.525002],[170.2324520000001,-19.52417],[170.217468,-19.559444]]],[[[169.498291,-19.545002],[169.349701,-19.636944],[169.232452,-19.350277],[169.498291,-19.545002]]],[[[169.594971,-19.273613],[169.578583,-19.262501],[169.594971,-19.231388],[169.594971,-19.273613]]],[[[169.30523700000018,-18.978886],[168.989136,-18.880833],[169.018585,-18.639999],[169.30523700000018,-18.978886]]],[[[168.574677,-17.692776],[168.148041,-17.719719],[168.3110960000001,-17.531391],[168.574677,-17.692776]]],[[[168.399139,-16.78278],[168.168579,-16.805279],[168.14831500000017,-16.580555],[168.399139,-16.78278]]],[[[168.231079,-16.516113],[168.20135500000012,-16.500557],[168.242462,-16.429165],[168.231079,-16.516113]]],[[[168.21524000000014,-16.174168],[168.304138,-16.339443],[167.9177550000002,-16.260281],[168.21524000000014,-16.174168]]],[[[167.41665600000013,-16.110001],[167.7724910000002,-16.535],[167.41748,-16.532223],[167.177765,-15.899168],[167.41665600000013,-16.110001]]],[[[167.209137,-15.755556],[167.077454,-15.640278],[167.227173,-15.637779],[167.209137,-15.755556]]],[[[167.258606,-15.588055],[167.239136,-15.574444],[167.2769170000001,-15.546112],[167.258606,-15.588055]]],[[[167.202454,-15.60861],[167.110229,-15.59],[167.16275,-15.535833],[167.190521,-15.529167],[167.21051000000014,-15.580278],[167.202454,-15.60861]]],[[[168.21078500000013,-15.998055],[168.15332,-15.492222],[168.266663,-15.870832],[168.21078500000013,-15.998055]]],[[[167.85580400000012,-15.485832],[167.66830400000012,-15.446945],[168.0021970000001,-15.290001],[167.85580400000012,-15.485832]]],[[[167.17526200000012,-15.266666],[167.163605,-15.254168],[167.179413,-15.256668],[167.17526200000012,-15.266666]]],[[[167.14444000000012,-14.971388],[167.096344,-14.932501],[167.1510930000002,-14.957777],[167.14444000000012,-14.971388]]],[[[168.169128,-15.395834],[168.10580400000018,-14.92],[168.190247,-15.214722],[168.169128,-15.395834]]],[[[166.802765,-15.157501],[167.058868,-14.945],[167.237717,-15.524258],[167.151154,-15.520343],[167.071625,-15.598055],[166.90277100000017,-15.582777],[166.8146970000001,-15.663055],[166.761932,-15.642778],[166.59274300000018,-14.624443],[166.802765,-15.157501]]],[[[167.527466,-14.326666],[167.413605,-14.178888],[167.58828700000012,-14.172777],[167.527466,-14.326666]]],[[[167.479126,-13.948334],[167.4766240000001,-13.706667],[167.577759,-13.847221],[167.479126,-13.948334]]],[[[167.70553600000014,-13.675001],[167.62356600000012,-13.691944],[167.687744,-13.621666],[167.70553600000014,-13.675001]]],[[[167.34719800000013,-13.56139],[167.29330400000018,-13.52639],[167.322205,-13.486944],[167.34719800000013,-13.56139]]],[[[166.67746,-13.452499],[166.6508180000001,-13.409723],[166.694122,-13.415834],[166.67746,-13.452499]]],[[[166.631622,-13.381388],[166.5960690000002,-13.334166],[166.6413570000001,-13.356943],[166.631622,-13.381388]]],[[[166.620239,-13.271389],[166.587463,-13.223055],[166.638306,-13.221666],[166.620239,-13.271389]]],[[[166.55969200000013,-13.186388],[166.521362,-13.070555],[166.564972,-13.091944],[166.55969200000013,-13.186388]]]]}},{"type":"Feature","properties":{"name":"Nigeria","iso2":"NG","iso3":"NGA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[7.466389,4.445277],[7.335833,4.443055],[7.411944,4.488055],[7.466389,4.445277]]],[[[7.20361,4.380555000000129],[7.22611,4.52],[7.316667,4.4725],[7.20361,4.380555000000129]]],[[[5.874722,13.749443],[6.423055,13.605276000000131],[6.933332,12.997221000000124],[7.815,13.352777],[9.634932,12.802435],[10.724165,13.386389],[12.459166,13.066111],[13.62512,13.718338],[14.07472,13.0816650000001],[14.174444,12.396666],[14.645277,12.188332000000145],[14.646387,11.575832],[13.80722,11.055832],[12.79694400000011,8.769722],[12.253887000000134,8.408054],[11.864166,7.084722],[11.340277,6.440833],[10.615000000000123,7.06861],[9.795555,6.801666],[8.865276,5.841944],[8.591738000000134,4.810932000000122],[7.676944,4.496388],[7.071666,4.753888],[7.073055,4.434722],[6.962222000000111,4.725277000000119],[7.005555,4.369444],[6.768055,4.774722],[6.848611000000119,4.348332000000113],[6.727221,4.605],[6.694166000000109,4.33],[6.104166,4.272778000000102],[5.451944,4.923055],[5.345277,5.33],[5.639722,5.536111],[5.257222000000183,5.43555500000015],[5.501111,5.620555],[5.175278000000105,5.575555],[4.525833,6.304999],[3.388611,6.443333000000109],[3.807222000000166,6.612778],[2.719606,6.365505],[2.789444,9.043888],[3.095,9.090555],[3.855,10.584999],[3.604459,11.693274],[4.1425,13.476944],[5.874722,13.749443]]]]}},{"type":"Feature","properties":{"name":"Netherlands","iso2":"NL","iso3":"NLD"},"geometry":{"type":"MultiPolygon","coordinates":[[[[3.764165878295898,51.34527778625488],[3.370866775512695,51.373857498168945],[4.238897323608398,51.35042762756348],[3.764165878295898,51.34527778625488]]],[[[5.763887405395508,52.4152774810791],[5.573057174682617,52.368051528930664],[5.53416633605957,52.283334732055664],[5.428613662719727,52.26416206359863],[5.135557174682617,52.38027381896973],[5.643613815307617,52.60110664367676],[5.855558395385742,52.54416847229004],[5.855558395385742,52.49249458312988],[5.763887405395508,52.4152774810791]]],[[[5.423334121704102,52.63638496398926],[5.051794052124023,52.39411735534668],[5.039495468139648,52.63365364074707],[5.423334121704102,52.63638496398926]]],[[[4.76472282409668,52.99027442932129],[4.713888168334961,53.056108474731445],[4.883333206176758,53.18416786193848],[4.76472282409668,52.99027442932129]]],[[[4.957223892211914,53.23777961730957],[4.879999160766602,53.21444129943848],[5.106389999389648,53.30333137512207],[4.957223892211914,53.23777961730957]]],[[[6.871667861938477,53.41610908508301],[7.208364486694336,53.242807388305664],[7.051668167114258,52.64361000061035],[6.68889045715332,52.54916572570801],[7.065557479858398,52.38582801818848],[6.828889846801758,51.96555519104004],[5.962499618530273,51.80777931213379],[6.222223281860352,51.465829849243164],[5.864721298217773,51.04610633850098],[6.011800765991211,50.757272720336914],[5.640832901000977,50.83972358703613],[5.849172592163086,51.156381607055664],[5.041391372680664,51.48666572570801],[4.252370834350586,51.37514686584473],[3.440832138061523,51.53582954406738],[4.286111831665039,51.44861030578613],[3.687501907348633,51.70971870422363],[4.167753219604492,51.68557167053223],[3.865556716918945,51.81499671936035],[4.584432601928711,52.461503982543945],[5.424444198608398,52.248605728149414],[5.533609390258789,52.267221450805664],[5.624723434448242,52.35416603088379],[5.774168014526367,52.40527534484863],[5.878057479858398,52.50943946838379],[5.855001449584961,52.60691261291504],[5.599443435668945,52.65860939025879],[5.59916877746582,52.75777626037598],[5.718351364135742,52.838022232055664],[5.368612289428711,52.87777900695801],[5.420557022094727,52.96444129943848],[5.364168167114258,53.07027626037598],[5.100278854370117,52.94805335998535],[5.304166793823242,52.70694160461426],[5.033334732055664,52.634164810180664],[5.02833366394043,52.37583351135254],[4.579999923706055,52.47166633605957],[4.734167098999023,52.95555305480957],[6.871667861938477,53.41610908508301]]],[[[5.213056564331055,53.35000038146973],[5.168889999389648,53.37388801574707],[5.581945419311523,53.44777870178223],[5.213056564331055,53.35000038146973]]],[[[5.699167251586914,53.462778091430664],[5.956113815307617,53.462778091430664],[5.633054733276367,53.441667556762695],[5.699167251586914,53.462778091430664]]],[[[6.135000228881836,53.4536075592041],[6.148889541625977,53.49749946594238],[6.34111213684082,53.50277900695801],[6.135000228881836,53.4536075592041]]]]}},{"type":"Feature","properties":{"name":"Norway","iso2":"NO","iso3":"NOR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[8.743612289428711,58.40972328186035],[8.726945877075195,58.41277503967285],[8.73750114440918,58.43499946594238],[8.761388778686523,58.436662673950195],[8.761388778686523,58.42138862609863],[8.743612289428711,58.40972328186035]]],[[[5.961946487426758,58.97222328186035],[5.945001602172852,58.977495193481445],[5.958887100219727,58.98388862609863],[5.961946487426758,58.97222328186035]]],[[[5.726388931274414,59.07805061340332],[5.548334121704102,59.13055610656738],[5.68889045715332,59.129167556762695],[5.726388931274414,59.07805061340332]]],[[[5.952779769897461,59.22833442687988],[5.909723281860352,59.2741641998291],[6.059167861938477,59.26082801818848],[5.952779769897461,59.22833442687988]]],[[[5.287778854370117,59.218889236450195],[5.155279159545898,59.14694404602051],[5.183610916137695,59.411943435668945],[5.287778854370117,59.218889236450195]]],[[[5.263334274291992,59.79860877990723],[5.148889541625977,59.58111000061035],[5.107500076293945,59.86444282531738],[5.263334274291992,59.79860877990723]]],[[[5.413057327270508,59.751665115356445],[5.276388168334961,59.96694374084473],[5.468332290649414,59.88638496398926],[5.413057327270508,59.751665115356445]]],[[[5.524999618530273,59.893327713012695],[5.360834121704102,59.99221992492676],[5.658056259155273,60.075273513793945],[5.524999618530273,59.893327713012695]]],[[[5.268056869506836,60.0049991607666],[5.168058395385742,60.031389236450195],[5.17277717590332,60.12166786193848],[5.268056869506836,60.0049991607666]]],[[[5.954721450805664,60.08944129943848],[5.924165725708008,60.145273208618164],[6.016946792602539,60.14666175842285],[5.954721450805664,60.08944129943848]]],[[[5.216943740844727,60.24194526672363],[5.19972038269043,60.251108169555664],[5.233335494995117,60.254716873168945],[5.216943740844727,60.24194526672363]]],[[[5.111944198608398,60.18583106994629],[4.946943283081055,60.249162673950195],[4.942499160766602,60.427499771118164],[5.111944198608398,60.18583106994629]]],[[[5.195276260375977,60.408884048461914],[5.000833511352539,60.53110694885254],[5.179445266723633,60.48277473449707],[5.195276260375977,60.408884048461914]]],[[[5.185277938842773,60.50610542297363],[4.926946640014648,60.60527229309082],[5.121667861938477,60.57805061340332],[5.185277938842773,60.50610542297363]]],[[[5.55000114440918,60.4313907623291],[5.360002517700195,60.52388954162598],[5.675832748413086,60.683053970336914],[5.55000114440918,60.4313907623291]]],[[[5.158334732055664,60.58166694641113],[4.85444450378418,60.732500076293945],[4.980001449584961,60.71472358703613],[5.158334732055664,60.58166694641113]]],[[[4.696390151977539,60.98722267150879],[4.630834579467773,61.006662368774414],[4.628057479858398,61.06443977355957],[4.696390151977539,60.98722267150879]]],[[[4.986387252807617,61.104440689086914],[4.804723739624023,61.044443130493164],[4.788057327270508,61.14638710021973],[4.986387252807617,61.104440689086914]]],[[[4.934167861938477,61.7741641998291],[4.804166793823242,61.84055519104004],[5.221944808959961,61.84555244445801],[4.934167861938477,61.7741641998291]]],[[[5.068056106567383,61.923051834106445],[5.009721755981445,62.01361274719238],[5.127222061157227,61.99249458312988],[5.068056106567383,61.923051834106445]]],[[[5.64777946472168,62.1874942779541],[5.506109237670898,62.224443435668945],[5.80805778503418,62.27305030822754],[5.64777946472168,62.1874942779541]]],[[[5.840555191040039,62.239999771118164],[5.804998397827148,62.36694526672363],[5.977502822875977,62.41111183166504],[5.840555191040039,62.239999771118164]]],[[[6.253889083862305,62.39166450500488],[6.023054122924805,62.435556411743164],[6.333612442016602,62.41333198547363],[6.253889083862305,62.39166450500488]]],[[[6.736665725708008,62.66722297668457],[6.649721145629883,62.6813907623291],[6.919443130493164,62.70916175842285],[6.736665725708008,62.66722297668457]]],[[[6.886388778686523,62.77694129943848],[6.775835037231445,62.84555244445801],[6.940557479858398,62.84444618225098],[6.886388778686523,62.77694129943848]]],[[[7.548334121704102,62.94832801818848],[7.365556716918945,62.99638557434082],[7.711946487426758,63.00249671936035],[7.548334121704102,62.94832801818848]]],[[[7.809724807739258,63.023332595825195],[7.679445266723633,63.056108474731445],[7.915277481079102,63.07916450500488],[7.809724807739258,63.023332595825195]]],[[[8.060277938842773,63.14166450500488],[7.926389694213867,63.171945571899414],[8.18638801574707,63.15305519104004],[8.060277938842773,63.14166450500488]]],[[[8.391111373901367,63.15916633605957],[8.269723892211914,63.2661075592041],[8.437498092651367,63.283884048461914],[8.576112747192383,63.18943977355957],[8.391111373901367,63.15916633605957]]],[[[8.511945724487305,63.319162368774414],[8.431112289428711,63.33194160461426],[8.675832748413086,63.34666633605957],[8.511945724487305,63.319162368774414]]],[[[8.162221908569336,63.36138343811035],[7.77833366394043,63.405832290649414],[8.091665267944336,63.46666145324707],[8.162221908569336,63.36138343811035]]],[[[8.494165420532227,63.42833137512207],[8.280000686645508,63.46472358703613],[9.176389694213867,63.56472206115723],[8.494165420532227,63.42833137512207]]],[[[8.808332443237305,63.81027412414551],[8.794443130493164,63.69749641418457],[8.269998550415039,63.67888832092285],[8.808332443237305,63.81027412414551]]],[[[11.453611373901367,64.51416206359863],[11.175554275512695,64.50694465637207],[11.038610458374023,64.62887763977051],[11.453611373901367,64.51416206359863]]],[[[11.351388931274414,64.64999580383301],[11.310834884643555,64.59666633605957],[11.176111221313477,64.64444160461426],[11.351388931274414,64.64999580383301]]],[[[11.261667251586914,64.88472175598145],[10.82499885559082,64.8449878692627],[11.106111526489258,64.95027351379395],[11.261667251586914,64.88472175598145]]],[[[11.110834121704102,64.96582221984863],[10.731389999389648,64.86027717590332],[10.777776718139648,64.91888618469238],[11.110834121704102,64.96582221984863]]],[[[11.636667251586914,65.06527900695801],[11.531389236450195,65.06082344055176],[11.77277946472168,65.11360359191895],[11.636667251586914,65.06527900695801]]],[[[12.156389236450195,65.05137825012207],[11.981668472290039,65.07638740539551],[12.183610916137695,65.20833015441895],[12.315279006958008,65.10998725891113],[12.285001754760742,65.08444404602051],[12.156389236450195,65.05137825012207]]],[[[12.075277328491211,65.21138191223145],[12.258054733276367,65.57611274719238],[12.502779006958008,65.39193916320801],[12.075277328491211,65.21138191223145]]],[[[11.974164962768555,65.62693977355957],[11.758611679077148,65.61694526672363],[11.894445419311523,65.70443916320801],[11.974164962768555,65.62693977355957]]],[[[12.542501449584961,65.89694404602051],[12.414999008178711,65.89360237121582],[12.573888778686523,66.01054573059082],[12.90361213684082,66.00860786437988],[12.542501449584961,65.89694404602051]]],[[[12.352499008178711,66.02249336242676],[12.563333511352539,66.21777534484863],[12.657220840454102,66.10472297668457],[12.352499008178711,66.02249336242676]]],[[[12.796667098999023,66.21443367004395],[12.71583366394043,66.24749946594238],[12.870832443237305,66.27749824523926],[12.796667098999023,66.21443367004395]]],[[[12.986665725708008,66.22833442687988],[12.93083381652832,66.22638130187988],[13.158334732055664,66.27749824523926],[12.986665725708008,66.22833442687988]]],[[[14.257776260375977,67.13304328918457],[14.191946029663086,66.99943733215332],[13.991109848022461,67.07859992980957],[14.257776260375977,67.13304328918457]]],[[[14.253053665161133,67.35859870910645],[14.216665267944336,67.35832405090332],[14.374998092651367,67.42221260070801],[14.253053665161133,67.35859870910645]]],[[[15.20222282409668,67.90027046203613],[14.931665420532227,67.92387580871582],[15.303609848022461,67.92027473449707],[15.20222282409668,67.90027046203613]]],[[[15.90333366394043,67.97888374328613],[15.49888801574707,67.98777961730957],[15.851110458374023,68.01361274719238],[15.90333366394043,67.97888374328613]]],[[[12.841943740844727,67.8086109161377],[13.155832290649414,68.08110237121582],[13.134443283081055,67.95250129699707],[12.841943740844727,67.8086109161377]]],[[[13.438055038452148,68.11277961730957],[13.163057327270508,68.01138496398926],[13.299165725708008,68.14972114562988],[13.438055038452148,68.11277961730957]]],[[[13.968332290649414,68.23832893371582],[14.135831832885742,68.23944282531738],[13.44972038269043,68.06749153137207],[13.968332290649414,68.23832893371582]]],[[[14.870553970336914,68.21165657043457],[14.826112747192383,68.25444221496582],[14.940553665161133,68.26805305480957],[14.870553970336914,68.21165657043457]]],[[[14.203611373901367,68.23916816711426],[14.049444198608398,68.30333137512207],[14.214166641235352,68.30110359191895],[14.203611373901367,68.23916816711426]]],[[[13.973333358764648,68.25332832336426],[13.883333206176758,68.30221748352051],[13.990556716918945,68.30999946594238],[13.973333358764648,68.25332832336426]]],[[[15.026388168334961,68.3549976348877],[14.19972038269043,68.15222358703613],[15.168889999389648,68.45054817199707],[15.026388168334961,68.3549976348877]]],[[[16.405553817749023,68.41110420227051],[16.094446182250977,68.39665412902832],[16.32694435119629,68.53360176086426],[16.405553817749023,68.41110420227051]]],[[[17.11638832092285,68.75248908996582],[16.81305503845215,68.72833442687988],[17.00055503845215,68.85443305969238],[17.11638832092285,68.75248908996582]]],[[[17.241666793823242,68.78860664367676],[17.0836124420166,68.91026496887207],[17.437776565551758,68.86526679992676],[17.241666793823242,68.78860664367676]]],[[[14.954442977905273,68.87277412414551],[14.839166641235352,68.88194465637207],[14.885278701782227,68.93332099914551],[14.954442977905273,68.87277412414551]]],[[[15.988054275512695,68.75193977355957],[15.739442825317383,68.52610969543457],[16.17888832092285,68.85165596008301],[16.565000534057617,68.65193367004395],[14.986665725708008,68.24749946594238],[15.71360969543457,68.69861030578613],[15.451665878295898,68.76220893859863],[15.636110305786133,68.94665718078613],[15.988054275512695,68.75193977355957]]],[[[16.537221908569336,68.87971687316895],[16.261110305786133,68.96666145324707],[16.601667404174805,68.94554328918457],[16.537221908569336,68.87971687316895]]],[[[15.382776260375977,68.84527778625488],[15.059167861938477,68.57249641418457],[14.371110916137695,68.6836109161377],[15.148611068725586,68.81221199035645],[15.087778091430664,69.00804328918457],[15.382776260375977,68.84527778625488]]],[[[17.41694450378418,68.99582099914551],[17.3527774810791,69.02415657043457],[17.56138801574707,69.0949878692627],[17.41694450378418,68.99582099914551]]],[[[15.522500991821289,68.90609931945801],[15.560277938842773,69.09471321105957],[16.148054122924805,69.28637886047363],[15.522500991821289,68.90609931945801]]],[[[17.63661003112793,69.51604652404785],[18.074167251586914,69.43083381652832],[18.003610610961914,69.19027900695801],[16.775278091430664,69.06443977355957],[17.173887252807617,69.19583320617676],[16.93083381652832,69.39248847961426],[17.63661003112793,69.51604652404785]]],[[[30.155553817749023,69.78166389465332],[30.11055564880371,69.78721809387207],[30.12611198425293,69.79748725891113],[30.155553817749023,69.78166389465332]]],[[[18.89000129699707,69.69194221496582],[17.996946334838867,69.58833503723145],[18.75139045715332,69.68277168273926],[18.693056106567383,69.88443183898926],[18.89000129699707,69.69194221496582]]],[[[20.68027687072754,69.8086109161377],[20.5563907623291,69.85110664367676],[20.739168167114258,69.90527534484863],[20.68027687072754,69.8086109161377]]],[[[29.8266658782959,69.75694465637207],[29.841943740844727,69.91026496887207],[30.04805564880371,69.82750129699707],[29.8266658782959,69.75694465637207]]],[[[21.730276107788086,69.93110847473145],[21.668611526489258,69.94194221496582],[21.717222213745117,69.94970893859863],[21.730276107788086,69.93110847473145]]],[[[19.56722068786621,69.85165596008301],[19.459444046020508,69.84250068664551],[19.89777946472168,69.97221565246582],[19.56722068786621,69.85165596008301]]],[[[19.959165573120117,70.00555610656738],[19.899168014526367,70.01609992980957],[19.996110916137695,70.01277351379395],[19.959165573120117,70.00555610656738]]],[[[19.300554275512695,70.02610969543457],[19.691946029663086,69.99472236633301],[18.72110939025879,69.93416023254395],[19.300554275512695,70.02610969543457]]],[[[20.892568588256836,70.03081703186035],[21.10249900817871,70.00471687316895],[20.757776260375977,69.98999214172363],[20.892568588256836,70.03081703186035]]],[[[21.00083351135254,70.01971626281738],[20.95194435119629,70.02583503723145],[21.049165725708008,70.04971504211426],[21.00083351135254,70.01971626281738]]],[[[18.785001754760742,70.11137580871582],[19.002779006958008,70.08415412902832],[18.684446334838867,69.99666023254395],[18.785001754760742,70.11137580871582]]],[[[20.919721603393555,70.07943916320801],[20.814722061157227,70.1161060333252],[20.861387252807617,70.14915657043457],[20.919721603393555,70.07943916320801]]],[[[19.607500076293945,70.1019458770752],[19.349721908569336,70.13138008117676],[19.4313907623291,70.17776679992676],[19.607500076293945,70.1019458770752]]],[[[20.831945419311523,70.19388008117676],[20.78388786315918,70.05638313293457],[20.385278701782227,70.09887886047363],[20.831945419311523,70.19388008117676]]],[[[20.11277961730957,70.10472297668457],[19.76999855041504,70.06527900695801],[19.53611183166504,70.24832344055176],[20.11277961730957,70.10472297668457]]],[[[19.185277938842773,70.12249946594238],[19.03360939025879,70.16110420227051],[19.233610153198242,70.25444221496582],[19.185277938842773,70.12249946594238]]],[[[22.8347225189209,70.33221626281738],[23.02277946472168,70.25943183898926],[22.36861228942871,70.33444404602051],[22.8347225189209,70.33221626281738]]],[[[21.77277946472168,70.26666450500488],[21.697778701782227,70.38194465637207],[21.84139060974121,70.35026741027832],[21.77277946472168,70.26666450500488]]],[[[23.595834732055664,70.57805061340332],[23.230554580688477,70.27832221984863],[22.851110458374023,70.40582466125488],[23.595834732055664,70.57805061340332]]],[[[23.871110916137695,70.51220893859863],[23.634164810180664,70.69638252258301],[24.12583351135254,70.61526679992676],[23.871110916137695,70.51220893859863]]],[[[23.4516658782959,70.78360176086426],[22.78416633605957,70.51971626281738],[21.94972038269043,70.64610481262207],[23.4516658782959,70.78360176086426]]],[[[24.06194496154785,70.90887641906738],[23.880834579467773,70.99360847473145],[24.2438907623291,70.95193672180176],[24.06194496154785,70.90887641906738]]],[[[24.7994441986084,71.02388191223145],[24.63944435119629,71.06082344055176],[24.853612899780273,71.0899829864502],[24.7994441986084,71.02388191223145]]],[[[25.828054428100586,71.09860420227051],[26.2197208404541,71.03360176086426],[25.28611183166504,71.02083015441895],[25.828054428100586,71.09860420227051]]],[[[5.336946487426758,61.59277534484863],[5.276834487915039,61.58799934387207],[5.345335006713867,61.58633232116699],[5.336946487426758,61.59277534484863],[4.938055038452148,61.6763858795166],[6.763612747192383,61.868051528930664],[5.148054122924805,61.892221450805664],[5.40361213684082,62.0161075592041],[5.150278091430664,62.21193885803223],[6.357221603393555,62.05527687072754],[5.918058395385742,62.215829849243164],[6.306665420532227,62.37166786193848],[6.538057327270508,62.10472297668457],[6.388334274291992,62.36972236633301],[6.87611198425293,62.414995193481445],[7.043058395385742,62.08638954162598],[7.415555953979492,62.232500076293945],[6.781389236450195,62.47833442687988],[6.257223129272461,62.44888496398926],[6.649835586547852,62.49838447570801],[6.246946334838867,62.574716567993164],[8.14527702331543,62.68999671936035],[6.958887100219727,62.72249794006348],[7.03639030456543,62.96750068664551],[8.548334121704102,62.653886795043945],[7.879167556762695,63.01055335998535],[8.530832290649414,62.841386795043945],[8.15916633605957,63.12027931213379],[8.938333511352539,63.20666694641113],[8.477777481079102,63.29361152648926],[8.763612747192383,63.34527778625488],[8.652776718139648,63.40916633605957],[9.004999160766602,63.46750068664551],[9.427778244018555,63.37693977355957],[9.149721145629883,63.48416328430176],[9.647500991821289,63.62388801574707],[10.25666618347168,63.26111030578613],[10.047224044799805,63.40610694885254],[10.910276412963867,63.45111274719238],[10.65888786315918,63.549997329711914],[11.455831527709961,63.78721809387207],[11.090555191040039,63.87832832336426],[11.492776870727539,64.01944160461426],[11.318887710571289,64.03221321105957],[11.358331680297852,64.11055183410645],[11.30583381652832,64.11638069152832],[11.180276870727539,64.00804328918457],[10.574167251586914,63.80499458312988],[10.904165267944336,63.89416694641113],[11.07722282409668,63.83749580383301],[10.941946029663086,63.738054275512695],[10.04777717590332,63.496110916137695],[9.789167404174805,63.66250038146973],[10.098333358764648,63.76194190979004],[9.543889999389648,63.76361274719238],[10.189722061157227,63.930551528930664],[9.982221603393555,63.990556716918945],[10.495290756225586,64.42381477355957],[10.972223281860352,64.60138130187988],[11.22166633605957,64.31610298156738],[11.728055953979492,64.57971382141113],[11.438333511352539,64.71110725402832],[12.224443435668945,64.93721199035645],[11.297224044799805,64.88360786437988],[11.975000381469727,65.06582832336426],[12.019445419311523,65.02610969543457],[12.04749870300293,65.05583381652832],[12.148889541625977,65.03915596008301],[12.624723434448242,65.13360786437988],[12.939722061157227,65.30832099914551],[12.24888801574707,65.22860908508301],[12.638055801391602,65.41888618469238],[12.360834121704102,65.64776802062988],[12.788610458374023,65.63638496398926],[12.667501449584961,65.91693305969238],[13.17500114440918,65.84915351867676],[13.121946334838867,65.94027900695801],[12.931943893432617,65.9749927520752],[12.959444046020508,66.04222297668457],[12.673887252807617,66.06694221496582],[14.146665573120117,66.32165718078613],[13.027223587036133,66.18609809875488],[13.53639030456543,66.3036060333252],[12.969999313354492,66.5183277130127],[13.725557327270508,66.6019458770752],[13.228055953979492,66.71249580383301],[13.990835189819336,66.78360176086426],[13.546945571899414,66.92666816711426],[15.739721298217773,67.17248725891113],[14.361665725708008,67.23388862609863],[15.035833358764648,67.57054328918457],[15.64000129699707,67.26638984680176],[15.541112899780273,67.4769458770752],[15.899168014526367,67.55888557434082],[14.758054733276367,67.80526924133301],[15.871110916137695,67.92332649230957],[15.961111068725586,68.01304817199707],[15.283056259155273,68.03555488586426],[15.972223281860352,68.24554634094238],[16.217222213745117,67.88804817199707],[16.495832443237305,67.79416084289551],[16.20749855041504,68.00166511535645],[16.71527671813965,68.0666675567627],[16.103334426879883,68.27693367004395],[16.80583381652832,68.13138008117676],[16.31722068786621,68.36694526672363],[17.35472297668457,68.17387580871582],[17.200834274291992,68.36694526672363],[17.552778244018555,68.52388191223145],[16.459444046020508,68.50804328918457],[17.68027687072754,68.6544361114502],[17.236112594604492,68.75471687316895],[17.79250144958496,68.75694465637207],[17.425832748413086,68.90500068664551],[18.152223587036133,69.15222358703613],[18.25694465637207,69.48637580871582],[19.440553665161133,69.22583198547363],[18.94416618347168,69.6130542755127],[19.75889015197754,69.81027412414551],[19.679166793823242,69.42944526672363],[20.304166793823242,69.96832466125488],[19.946943283081055,69.25610542297363],[20.853055953979492,69.48916816711426],[20.48138999938965,69.63888740539551],[21.307222366333008,70.01971626281738],[22.101667404174805,69.74083137512207],[21.797224044799805,70.03360176086426],[22.09666633605957,70.11332893371582],[21.30000114440918,70.24693489074707],[22.9505558013916,70.20555305480957],[22.287778854370117,70.03888130187988],[23.31194496154785,69.94082832336426],[23.660001754760742,70.42000007629395],[24.72916603088379,70.62193489074707],[24.245553970336914,70.77722358703613],[24.591943740844727,70.96304512023926],[25.907777786254883,70.88665962219238],[25.073610305786133,70.50000190734863],[25.273054122924805,70.39888191223145],[24.9424991607666,70.08777046203613],[25.234724044799805,70.08972358703613],[26.570276260375977,70.93889045715332],[26.5049991607666,70.3630542755127],[27.029443740844727,70.47415351867676],[27.565553665161133,70.80471992492676],[27.136110305786133,70.95833015441895],[27.65166664123535,71.1130542755127],[28.550832748413086,70.96832466125488],[27.64750099182129,70.60527229309082],[28.295000076293945,70.71277046203613],[27.851667404174805,70.47888374328613],[28.335554122924805,70.50555610656738],[28.038888931274414,70.06193733215332],[28.527498245239258,70.72665596008301],[29.03611183166504,70.8741626739502],[31.078054428100586,70.28915596008301],[28.61250114440918,70.10777473449707],[29.671667098999023,69.96750068664551],[29.365556716918945,69.85527229309082],[29.73750114440918,69.90527534484863],[29.486665725708008,69.65555000305176],[30.854841232299805,69.79231452941895],[30.910001754760742,69.54887580871582],[30.103334426879883,69.66305732727051],[28.95734214782715,69.05162239074707],[28.78416633605957,69.16055488586426],[29.176111221313477,69.6352710723877],[28.165834426879883,69.91221809387207],[26.44999885559082,69.92721748352051],[25.945833206176758,69.67332649230957],[25.761110305786133,68.98916816711426],[24.934919357299805,68.58081245422363],[23.976388931274414,68.83249092102051],[22.398332595825195,68.71110725402832],[21.320833206176758,69.32611274719238],[20.580930709838867,69.06030464172363],[20.09694480895996,69.04222297668457],[20.350278854370117,68.78665351867676],[19.937776565551758,68.33749580383301],[18.09083366394043,68.50776863098145],[17.884164810180664,67.94554328918457],[16.726945877075195,67.89915657043457],[16.085832595825195,67.41165351867676],[16.3538875579834,67.01777839660645],[15.36277961730957,66.4799976348877],[15.468053817749023,66.28387641906738],[14.504999160766602,66.13249397277832],[14.49305534362793,65.31360054016113],[13.662500381469727,64.58276557922363],[14.116388320922852,64.47055244445801],[13.988332748413086,64.01805305480957],[12.938055038452148,64.05333137512207],[12.139444351196289,63.58416175842285],[11.93638801574707,63.27221870422363],[12.295831680297852,62.261667251586914],[12.124444961547852,61.72860908508301],[12.856111526489258,61.362497329711914],[12.210000991821289,61.00249671936035],[12.594446182250977,60.51693916320801],[12.494165420532227,60.11110877990723],[11.815961837768555,59.84610176086426],[11.75111198425293,59.09027290344238],[11.429193496704102,58.98764228820801],[10.79749870300293,59.18638801574707],[10.557779312133789,59.72860908508301],[10.748334884643555,59.88694190979004],[10.527498245239258,59.87527656555176],[10.558053970336914,59.54305458068848],[10.222223281860352,59.727495193481445],[10.516389846801758,59.31083106994629],[10.231111526489258,59.03860664367676],[9.540834426879883,59.11471748352051],[9.693056106567383,58.98305702209473],[9.409444808959961,58.841386795043945],[9.191110610961914,58.658334732055664],[8.995832443237305,58.59832954406738],[8.712644577026367,58.441938400268555],[8.691946029663086,58.37722206115723],[8.510278701782227,58.270273208618164],[8.248056411743164,58.20194435119629],[8.211111068725586,58.115556716918945],[6.597776412963867,58.07027626037598],[6.767221450805664,58.23832893371582],[5.45777702331543,58.74444007873535],[5.552778244018555,59.03277778625488],[6.168611526489258,58.832223892211914],[6.623334884643555,59.05166816711426],[5.866388320922852,59.072221755981445],[6.468889236450195,59.55527687072754],[5.511110305786133,59.27499580383301],[5.178056716918945,59.50833320617676],[6.306390762329102,59.843332290649414],[5.698335647583008,59.832773208618164],[6.204721450805664,60.29555702209473],[6.640554428100586,60.4102725982666],[6.521112442016602,60.07666206359863],[7.108057022094727,60.49416542053223],[6.220834732055664,60.41250038146973],[5.747224807739258,59.98666572570801],[5.734445571899414,60.38694190979004],[5.411111831665039,60.129716873168945],[5.142221450805664,60.346384048461914],[5.70250129699707,60.45443916320801],[5.700834274291992,60.694162368774414],[5.261388778686523,60.553056716918945],[4.928888320922852,60.79888343811035],[5.433610916137695,60.62722206115723],[5.236387252807617,60.77388954162598],[5.533609390258789,60.87249946594238],[5.007776260375977,61.03721809387207],[5.419443130493164,61.02555274963379],[5.920835494995117,61.123056411743164],[6.372224807739258,61.06194496154785],[6.590555191040039,61.151384353637695],[7.113889694213867,60.86027717590332],[7.000833511352539,61.09610939025879],[7.428613662719727,61.1813907623291],[7.303888320922852,61.294443130493164],[7.574445724487305,61.479440689086914],[7.309167861938477,61.362497329711914],[7.273054122924805,61.278886795043945],[7.353891372680664,61.18999671936035],[7.278055191040039,61.15860939025879],[6.955556869506836,61.109994888305664],[6.564165115356445,61.218332290649414],[6.703611373901367,61.401384353637695],[6.520406723022461,61.24620246887207],[6.498334884643555,61.13027381896973],[5.749166488647461,61.15277290344238],[5.397222518920898,61.06860542297363],[4.953332901000977,61.25860786437988],[5.63416862487793,61.360551834106445],[4.948888778686523,61.41277503967285],[5.804998397827148,61.452775955200195],[5.130834579467773,61.52666664123535],[5.273889541625977,61.55777549743652],[5.148611068725586,61.59305000305176],[5.336946487426758,61.59277534484863]],[[5.77833366394043,58.94749641418457],[5.754999160766602,58.95638465881348],[5.760835647583008,58.94583320617676],[5.77833366394043,58.94749641418457]]]]}},{"type":"Feature","properties":{"name":"Nepal","iso2":"NP","iso3":"NPL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[82.06639900000013,27.914154],[80.055817,28.836109],[80.37692300000012,29.748604],[81.02536,30.204353],[81.22360200000011,30.010277],[81.421097,30.385273],[82.10054,30.342220000000125],[83.55276500000011,29.185829],[84.119141,29.259998],[84.481094,28.736660000000157],[85.189972,28.603329],[85.1066440000001,28.309441],[85.721375,28.279163],[86.014435,27.882774],[86.183594,28.163883],[86.444977,27.90805100000013],[86.686371,28.112217],[87.192749,27.82305100000015],[88.142792,27.866055],[88.014709,26.364719],[85.855545,26.57027400000011],[84.147217,27.51138700000014],[83.29136700000018,27.337776],[82.06639900000013,27.914154]]]]}},{"type":"Feature","properties":{"name":"Nauru","iso2":"NR","iso3":"NRU"},"geometry":{"type":"MultiPolygon","coordinates":[[[[166.929138,-0.552222],[166.930542,-0.493333],[166.958588,-0.506389],[166.929138,-0.552222]]]]}},{"type":"Feature","properties":{"name":"Suriname","iso2":"SR","iso3":"SUR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-55.127968,5.822173],[-54.030006,5.821111],[-54.166946,5.346944],[-54.477501,4.747777],[-54.001114,3.448333],[-54.603783,2.329195],[-55.965836,2.532777],[-55.904167,1.893055],[-56.470634,1.944499000000135],[-57.301392,3.3775],[-57.642227,3.356389000000107],[-58.047226,4.008333000000107],[-57.92333999999988,4.821944],[-57.327225,5.026111],[-57.248505,5.486111],[-56.972504,5.996944],[-55.899559,5.671908],[-55.836395,5.956666],[-55.127968,5.822173]]]]}},{"type":"Feature","properties":{"name":"Nicaragua","iso2":"NI","iso3":"NIC"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-83.712509,11.868332],[-83.73194899999987,11.903332],[-83.714447,11.988054],[-83.712509,11.868332]]],[[[-83.048889,12.145555],[-83.05751,12.183611],[-83.021393,12.184166],[-83.048889,12.145555]]],[[[-82.964737,12.286943],[-82.983337,12.313055],[-82.97139,12.312498000000119],[-82.964737,12.286943]]],[[[-82.750839,14.353888],[-82.7897339999999,14.374998],[-82.733612,14.418888],[-82.750839,14.353888]]],[[[-83.239731,14.98249800000012],[-83.131851,14.992979000000105],[-83.421402,14.80611],[-83.186951,14.323889],[-83.551117,13.450554],[-83.482788,12.403889],[-83.604446,12.819443],[-83.83168,11.874722],[-83.645798,10.924847],[-83.915558,10.708611],[-85.087784,11.009998],[-85.692383,11.076061],[-87.69250499999987,12.912222],[-87.301392,12.986599],[-86.695007,13.296944000000124],[-86.763016,13.751621],[-86.015839,14.065832000000114],[-85.732315,13.829235],[-84.906677,14.808611],[-84.482788,14.617777],[-83.239731,14.98249800000012]]]]}},{"type":"Feature","properties":{"name":"New Zealand","iso2":"NZ","iso3":"NZL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[169.185516,-52.57695],[169.000824,-52.507225],[169.205231,-52.441383],[169.185516,-52.57695]]],[[[166.09661900000017,-50.923058],[165.923584,-50.856392],[166.22052,-50.887505],[166.09661900000017,-50.923058]]],[[[165.995544,-50.603638],[165.969421,-50.605003],[166.003601,-50.595001],[165.995544,-50.603638]]],[[[166.2508240000001,-50.82695],[165.886932,-50.804443],[166.199402,-50.527222],[166.2508240000001,-50.82695]]],[[[166.321899,-50.50695],[166.284973,-50.50528],[166.331909,-50.49472],[166.321899,-50.50695]]],[[[178.816376,-49.723885],[178.71524,-49.685272],[178.814972,-49.613617],[178.816376,-49.723885]]],[[[166.632172,-48.04084],[166.563873,-48.039444],[166.622192,-47.995552],[166.632172,-48.04084]]],[[[179.076904,-47.680595],[179.049133,-47.67556],[179.0697020000002,-47.661667],[179.076904,-47.680595]]],[[[167.434967,-47.248611],[167.426636,-47.222496],[167.486908,-47.214165],[167.434967,-47.248611]]],[[[167.685791,-46.796669],[167.663605,-46.760002],[167.718842,-46.771385],[167.685791,-46.796669]]],[[[168.191925,-46.905273],[167.519135,-47.27417],[167.775818,-46.700279],[168.191925,-46.905273]]],[[[166.71637000000013,-45.741669],[166.50497400000015,-45.719162],[166.710785,-45.61528],[166.71637000000013,-45.741669]]],[[[167.0099790000002,-45.31028],[166.891357,-45.250282],[166.962189,-45.153328],[167.0099790000002,-45.31028]]],[[[-176.162231,-44.324722],[-176.23584,-44.234734],[-176.115814,-44.263336],[-176.162231,-44.324722]]],[[[-176.45224,-43.736122],[-176.60556,-44.119171],[-176.53421,-43.870277],[-176.848053,-43.812225],[-176.45224,-43.736122]]],[[[174.399414,-41.115837],[174.37439,-41.203056],[174.193298,-41.232498],[174.344421,-41.18306],[174.3718870000001,-41.148613],[174.322754,-41.1325],[174.399414,-41.115837]]],[[[173.80581700000013,-40.92778],[173.823303,-40.762505],[173.963867,-40.710556],[173.80581700000013,-40.92778]]],[[[172.861359,-40.507782],[172.656921,-40.653328],[173.013306,-40.796669],[173.10553,-41.313332],[174.323853,-41.003334],[174.026642,-41.236115],[174.20636,-41.269447],[174.326904,-41.222771],[174.04443400000022,-41.442497],[174.289154,-41.748337],[172.760803,-43.239166],[173.091644,-43.856392],[172.424988,-43.733612],[171.293579,-44.343613],[170.554413,-45.888054],[170.783051,-45.878334],[169.008026,-46.680832],[166.48440600000018,-46.01445],[166.987183,-45.709724],[166.775818,-45.662773],[167.0413510000001,-45.501396],[166.704407,-45.574448],[166.82162500000013,-45.320557],[167.21191400000012,-45.475273],[166.996918,-45.145836],[167.507202,-45.001396],[168.374969,-44.037781],[170.794128,-42.90139],[172.064972,-41.40361],[172.108856,-40.885559],[172.861359,-40.507782]]],[[[177.001373,-37.870552],[176.964691,-37.863617],[176.97995,-37.848053],[177.001373,-37.870552]]],[[[176.43856800000012,-37.650276],[176.44693,-37.604721],[176.459412,-37.622772],[176.43856800000012,-37.650276]]],[[[175.166077,-36.833885],[175.002472,-36.792778],[175.193848,-36.727493],[175.166077,-36.833885]]],[[[175.827179,-36.630829],[175.770264,-36.580833],[175.80246,-36.576111],[175.827179,-36.630829]]],[[[174.86386100000013,-36.459724],[174.869965,-36.388893],[174.907196,-36.451668],[174.86386100000013,-36.459724]]],[[[175.1494139999999,-36.213333],[175.07968100000014,-36.200836],[175.121887,-36.170555],[175.1494139999999,-36.213333]]],[[[175.5447080000002,-36.347778],[175.358856,-36.229439],[175.3718870000001,-36.070557],[175.5447080000002,-36.347778]]],[[[173.038879,-34.436943],[173.2691350000002,-35.019722],[173.450806,-34.807777],[174.319977,-35.232773],[174.85440099999985,-36.847778],[175.579132,-37.244446],[175.353577,-36.481941],[175.84079,-36.754173],[175.994415,-37.638893],[177.15942400000014,-38.013336],[178.0180050000001,-37.550831],[178.565521,-37.713333],[177.90997300000012,-39.25695],[177.05496200000013,-39.204445],[176.834137,-40.181671],[175.323029,-41.614449],[174.591919,-41.27861],[175.127747,-40.713615],[175.155548,-40.095833],[173.75192300000012,-39.288612],[174.594421,-38.815834],[174.974976,-37.75],[174.549713,-37.073616],[174.887482,-37.059166],[174.502472,-37.037506],[174.187744,-36.496948],[174.453033,-36.651108],[174.268585,-36.342224],[174.505249,-36.231384],[173.913879,-35.86972],[174.080811,-36.409439],[173.398865,-35.573891],[173.655548,-35.313332],[173.38052400000012,-35.528053],[173.087463,-35.211388],[172.722473,-34.495277],[173.038879,-34.436943]]],[[[172.157196,-34.173889],[172.133331,-34.153328],[172.18692,-34.152496],[172.157196,-34.173889]]],[[[-178.605286,-30.581116],[-178.613068,-30.587223],[-178.612518,-30.574448],[-178.605286,-30.581116]]],[[[-177.84613,-29.278614],[-177.923615,-29.284725],[-177.952484,-29.226112],[-177.84613,-29.278614]]]]}},{"type":"Feature","properties":{"name":"Paraguay","iso2":"PY","iso3":"PRY"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-54.330559,-24.679449],[-54.59891499999989,-25.573223],[-54.698334,-26.438335],[-55.736115,-27.439445],[-58.604622,-27.316921],[-57.576668,-25.549446],[-57.75611099999986,-25.176945],[-61.007782,-23.813335],[-62.643768,-22.238903],[-61.7425,-19.645],[-59.09584,-19.348892],[-58.15139,-19.828056],[-58.15889,-20.168056],[-57.814445,-20.971947],[-57.985107,-22.091827],[-55.849724,-22.288891],[-55.411667,-23.95639],[-54.407227,-23.916668],[-54.330559,-24.679449]]]]}},{"type":"Feature","properties":{"name":"Peru","iso2":"PE","iso3":"PER"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-78.70903,-4.584787],[-78.3375089999999,-3.422778],[-76.66062899999986,-2.572135],[-75.559174,-1.534167],[-75.21608,-0.965336],[-75.62796,-0.108859],[-75.285843,-0.119722],[-74.776947,-0.204167],[-74.227234,-1.027778],[-73.556396,-1.370833],[-72.88195799999988,-2.506389],[-71.698059,-2.146945],[-70.288345,-2.505],[-70.067505,-2.755556],[-70.724167,-3.779723],[-69.956924,-4.236874],[-70.765839,-4.146389],[-72.85195899999985,-5.124722],[-73.123901,-6.447223],[-73.74417099999988,-6.876945],[-74.01055899999989,-7.541389],[-72.964172,-8.983334],[-73.205292,-9.407223],[-72.366394,-9.494446],[-72.14389,-10.004723],[-71.298889,-9.996389],[-70.5146639999999,-9.428001],[-70.631393,-11.009167],[-69.568436,-10.951092],[-68.673904,-12.50115],[-68.974457,-12.869722],[-68.853058,-14.199167],[-69.366394,-14.802502],[-69.136948,-15.245834],[-69.421951,-15.618057],[-68.82251,-16.339725],[-69.618896,-17.214725],[-69.499725,-17.50528],[-69.951126,-18.242779],[-70.405487,-18.348545],[-71.497513,-17.296947],[-75.047501,-15.469168],[-75.933334,-14.658056],[-76.39389,-13.898056],[-76.196945,-13.418335],[-77.652512,-11.292223],[-78.989731,-8.226946],[-79.982788,-6.764445],[-81.174728,-6.086667],[-80.871399,-5.652223],[-81.289734,-4.31],[-80.340424,-3.380517],[-80.153336,-3.884228],[-80.467224,-3.986945],[-80.467789,-4.43889],[-79.649734,-4.432778],[-79.054825,-5.009132],[-78.70903,-4.584787]]]]}},{"type":"Feature","properties":{"name":"Pakistan","iso2":"PK","iso3":"PAK"},"geometry":{"type":"MultiPolygon","coordinates":[[[[67.449417,24.002777],[67.41192600000014,24.005833000000123],[67.379425,24.051662],[67.45887800000011,24.05694200000012],[67.481659,24.042774],[67.45887800000011,24.007221],[67.449417,24.002777]]],[[[74.8174900000001,37.021767],[75.864426,36.65967600000015],[76.166382,35.819717],[77.8239290000001,35.501328],[77.04248,35.099159],[76.8699800000002,34.658882],[73.94165,34.646385],[73.913315,34.068604],[74.295822,33.977486],[73.99054000000015,33.743881000000115],[74.016388,33.18859900000011],[75.381287,32.214241],[74.605324,31.877119],[74.69458800000021,31.053961],[73.872498,30.390099],[73.933403,30.136002],[73.397491,29.942772],[71.896942,27.961941000000152],[70.829437,27.706383],[70.368317,28.020832000000112],[69.580276,27.173328],[69.506104,26.754444000000106],[70.183594,26.536110000000107],[70.088043,25.982773],[70.666382,25.69833],[71.10582,24.416386],[70.01470900000012,24.169716],[68.78305100000014,24.332775],[68.747208,23.969994],[68.1978,23.766685000000123],[67.493591,23.890831],[67.53804000000017,23.938129],[67.50067100000015,23.974043],[67.486649,24.045277],[67.461197,24.065355],[67.338043,24.089718],[67.2738800000001,24.425827],[67.15165700000014,24.610554],[67.2541660000002,24.746105000000128],[66.645538,24.829163],[66.732758,25.197495],[66.359421,25.613609000000125],[66.141602,25.503941000000125],[66.506378,25.402496],[64.65193200000013,25.162773],[64.113876,25.453327],[61.61103100000017,25.197647],[61.858047,26.234718],[63.17638400000013,26.631107],[63.34193400000012,27.122498],[62.782494000000185,27.260555],[62.78138,28.266941],[61.90554800000015,28.554996],[60.86859900000016,29.863884],[62.4844360000001,29.406105],[66.256653,29.851940000000113],[66.395538,30.94083],[66.72303800000012,31.212215],[67.778046,31.33221800000014],[67.575546,31.53194000000012],[68.166092,31.833054000000104],[68.833054,31.603886],[69.32824700000012,31.940365000000114],[69.505264,33.034164],[70.326935,33.33194],[69.90637200000018,34.035271],[71.08194000000012,34.05582400000013],[70.987488,34.551102000000114],[71.64942900000014,35.424995],[71.2435760000001,36.129715],[72.556641,36.821266],[74.56543,37.027817],[74.8174900000001,37.021767]]]]}},{"type":"Feature","properties":{"name":"Poland","iso2":"PL","iso3":"POL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[18.851246,49.517357],[18.577221,49.914444],[17.657776,50.108055],[17.722775,50.319717],[16.890274,50.439438],[17.00222,50.216942],[16.641941,50.10833],[16.20583,50.423882],[16.341942,50.66111],[14.828333,50.865829],[15.036388,51.285553],[14.599443,51.818604],[14.640276,52.572495],[14.14916600000015,52.862778],[14.275627,53.699066],[14.614166,53.816383],[14.218887,53.869019],[14.225555000000156,53.928604],[17.918888,54.82666],[18.334999,54.836662],[18.739998,54.685272],[18.405277,54.74305],[18.582775,54.435272],[18.836388,54.353333],[19.627258,54.463272],[19.651108,54.455826],[19.226662,54.32888],[19.797007,54.43755],[22.785885,54.363838],[23.50404,53.947044],[23.94083,52.732208],[23.1654,52.282276],[23.638607,52.079437],[23.604633,51.527695],[24.111385,50.56694],[22.680828000000105,49.572495],[22.886074,49.002914],[22.558052,49.079437],[21.618889,49.436386],[20.074444,49.175278],[19.475555,49.599998],[18.851246,49.517357]]]]}},{"type":"Feature","properties":{"name":"Panama","iso2":"PA","iso3":"PAN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-81.77862358093262,7.276388168334961],[-81.79750061035156,7.225835800170898],[-81.81861877441406,7.290002822875977],[-81.77862358093262,7.276388168334961]]],[[[-81.20584106445312,7.486665725708008],[-81.24972534179688,7.488332748413086],[-81.03361511230469,7.570833206176758],[-81.20584106445312,7.486665725708008]]],[[[-81.64944458007812,7.38416862487793],[-81.87417602539062,7.491113662719727],[-81.75862121582031,7.63416862487793],[-81.64944458007812,7.38416862487793]]],[[[-81.10389709472656,7.717779159545898],[-81.149169921875,7.741666793823242],[-81.12417602539062,7.758890151977539],[-81.10389709472656,7.717779159545898]]],[[[-81.165283203125,7.822778701782227],[-81.17361450195312,7.818056106567383],[-81.16139221191406,7.841665267944336],[-81.165283203125,7.822778701782227]]],[[[-82.34056091308594,8.087499618530273],[-82.36639404296875,8.088888168334961],[-82.31973266601562,8.136667251586914],[-82.34056091308594,8.087499618530273]]],[[[-82.21334838867188,8.197500228881836],[-82.2952880859375,8.193609237670898],[-82.31333923339844,8.218889236450195],[-82.21334838867188,8.197500228881836]]],[[[-82.33250427246094,8.233610153198242],[-82.40362358093262,8.253053665161133],[-82.33612060546875,8.292501449584961],[-82.31417846679688,8.271665573120117],[-82.33250427246094,8.233610153198242]]],[[[-79.10694885253906,8.201112747192383],[-79.09750366210938,8.309167861938477],[-79.05584716796875,8.25139045715332],[-79.10694885253906,8.201112747192383]]],[[[-79.07640075683594,8.369722366333008],[-79.11445617675781,8.415277481079102],[-79.07583618164062,8.408609390258789],[-79.07640075683594,8.369722366333008]]],[[[-78.85139465332031,8.288610458374023],[-78.95916557312012,8.29222297668457],[-78.96028137207031,8.447221755981445],[-78.85139465332031,8.288610458374023]]],[[[-82.0150146484375,9.12639045715332],[-82.04917907714844,9.144166946411133],[-82.04583740234375,9.176389694213867],[-82.0150146484375,9.12639045715332]]],[[[-82.07917785644531,9.284444808959961],[-82.12445068359375,9.271944046020508],[-82.20639038085938,9.348333358764648],[-82.07917785644531,9.284444808959961]]],[[[-82.22445678710938,9.335000991821289],[-82.22944641113281,9.337499618530273],[-82.2247314453125,9.352499008178711],[-82.22445678710938,9.335000991821289]]],[[[-82.23918151855469,9.330278396606445],[-82.314453125,9.424722671508789],[-82.25834655761719,9.429166793823242],[-82.23918151855469,9.330278396606445]]],[[[-79.46305847167969,9.568056106567383],[-78.03556823730469,9.230001449584961],[-77.36666870117188,8.67500114440918],[-77.21556091308594,7.937223434448242],[-77.57389831542969,7.525278091430664],[-77.74667358398438,7.722223281860352],[-77.88972473144531,7.228891372680664],[-78.43305969238281,8.051942825317383],[-78.25723266601562,8.101945877075195],[-78.13917541503906,8.403890609741211],[-77.7791748046875,8.155000686645508],[-78.10751342773438,8.455831527709961],[-78.41416931152344,8.344167709350586],[-78.97862243652344,9.142778396606445],[-80.47361755371094,8.212778091430664],[-79.98973083496094,7.516111373901367],[-80.43333435058594,7.244443893432617],[-80.92529296875,7.250001907348633],[-81.05805969238281,7.873334884643555],[-81.17886352539062,7.85499382019043],[-81.21778869628906,7.607221603393555],[-81.4969482421875,7.698610305786133],[-81.73861694335938,8.162500381469727],[-82.19195556640625,8.19444465637207],[-82.2872314453125,8.313333511352539],[-82.7216796875,8.317220687866211],[-82.89884757995605,8.025671005249023],[-82.71084594726562,8.931112289428711],[-82.93472290039062,9.47166633605957],[-82.56356811523438,9.562875747680664],[-82.23695373535156,8.997777938842773],[-81.81639099121094,8.945276260375977],[-81.88389587402344,9.174444198608398],[-81.19612121582031,8.780279159545898],[-79.46305847167969,9.568056106567383]],[[-77.98695373535156,8.242223739624023],[-77.99223327636719,8.250555038452148],[-78.00306701660156,8.25111198425293],[-77.98695373535156,8.242223739624023]]]]}},{"type":"Feature","properties":{"name":"Portugal","iso2":"PT","iso3":"PRT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-17.102500915527344,32.82332801818848],[-16.715557098388672,32.75889015197754],[-16.94361114501953,32.63749885559082],[-17.102500915527344,32.82332801818848]]],[[[-16.28583526611328,33.09416389465332],[-16.400558471679688,33.03860664367676],[-16.325557708740234,33.10805702209473],[-16.28583526611328,33.09416389465332]]],[[[-25.01639175415039,36.9697208404541],[-25.200557708740234,36.9858341217041],[-25.08639144897461,37.02360725402832],[-25.01639175415039,36.9697208404541]]],[[[-25.585002899169922,37.82666206359863],[-25.864723205566406,37.85055732727051],[-25.130279541015625,37.811662673950195],[-25.585002899169922,37.82666206359863]]],[[[-28.14111328125,38.44988441467285],[-28.03778076171875,38.40694618225098],[-28.54944610595703,38.52722358703613],[-28.14111328125,38.44988441467285]]],[[[-27.086944580078125,38.63138771057129],[-27.38500213623047,38.76333045959473],[-27.065834045410156,38.76416206359863],[-27.086944580078125,38.63138771057129]]],[[[-31.215557098388672,39.35333442687988],[-31.213890075683594,39.52194404602051],[-31.123058319091797,39.44888496398926],[-31.215557098388672,39.35333442687988]]],[[[-8.204723358154297,41.87471961975098],[-6.594165802001953,41.9536075592041],[-6.187221527099609,41.579721450805664],[-6.931667327880859,41.01805305480957],[-7.017221450805664,39.674997329711914],[-7.532505035400391,39.66942024230957],[-6.954792022705078,39.026384353637695],[-7.321111679077148,38.44944190979004],[-6.939167022705078,38.178056716918945],[-7.446945190429688,37.69944190979004],[-7.431854248046875,37.253190994262695],[-8.990278244018555,37.02305030822754],[-8.673334121704102,38.413888931274414],[-9.183889389038086,38.41971778869629],[-8.984445571899414,38.94777870178223],[-9.484445571899414,38.71000099182129],[-8.660833358764648,40.68721961975098],[-8.74500846862793,41.95250129699707],[-8.201223373413086,42.15274238586426],[-8.204723358154297,41.87471961975098]]]]}},{"type":"Feature","properties":{"name":"Papua New Guinea","iso2":"PG","iso3":"PNG"},"geometry":{"type":"MultiPolygon","coordinates":[[[[153.77081489562988,-11.616388320922852],[153.376070022583,-11.567222595214844],[153.19803047180176,-11.324167251586914],[153.77081489562988,-11.616388320922852]]],[[[154.29776191711426,-11.391944885253906],[154.00332832336426,-11.383890151977539],[154.15387153625488,-11.314167022705078],[154.29776191711426,-11.391944885253906]]],[[[153.241060256958,-11.268890380859375],[153.21051216125488,-11.285833358764648],[153.09106636047363,-11.197221755981445],[153.241060256958,-11.268890380859375]]],[[[152.87329292297363,-10.662221908569336],[152.74441719055176,-10.716665267944336],[152.54080390930176,-10.63055419921875],[152.87329292297363,-10.662221908569336]]],[[[151.06970405578613,-10.61111068725586],[151.0422077178955,-10.676944732666016],[150.90997505187988,-10.654722213745117],[151.06970405578613,-10.61111068725586]]],[[[150.89221382141113,-10.650833129882812],[150.79080390930176,-10.54222297668457],[150.90027046203613,-10.553054809570312],[150.89221382141113,-10.650833129882812]]],[[[151.116060256958,-10.046667098999023],[151.28137397766113,-9.923334121704102],[151.22912788391113,-10.20111083984375],[150.958589553833,-10.11027717590332],[150.7599811553955,-9.70777702331543],[151.116060256958,-10.046667098999023]]],[[[150.66665840148926,-9.438333511352539],[150.92163276672363,-9.670833587646484],[150.42190742492676,-9.389444351196289],[150.66665840148926,-9.438333511352539]]],[[[150.33914375305176,-9.524723052978516],[150.10830879211426,-9.368610382080078],[150.18914985656738,-9.211111068725586],[150.33914375305176,-9.524723052978516]]],[[[152.81497383117676,-8.972776412963867],[152.99719429016113,-9.173055648803711],[152.49774360656738,-9.021665573120117],[152.81497383117676,-8.972776412963867]]],[[[151.1249713897705,-8.425556182861328],[151.14444160461426,-8.830554962158203],[150.996919631958,-8.52861213684082],[151.1249713897705,-8.425556182861328]]],[[[143.638032913208,-8.733055114746094],[143.18359565734863,-8.420000076293945],[143.46719551086426,-8.527778625488281],[143.638032913208,-8.733055114746094]]],[[[143.57275581359863,-8.493888854980469],[143.3144245147705,-8.376665115356445],[143.57831001281738,-8.37388801574707],[143.57275581359863,-8.493888854980469]]],[[[143.68719673156738,-8.439722061157227],[143.60717964172363,-8.33277702331543],[143.672212600708,-8.35444450378418],[143.68719673156738,-8.439722061157227]]],[[[143.6974811553955,-8.245277404785156],[143.65164375305176,-8.199722290039062],[143.73330879211426,-8.174722671508789],[143.6974811553955,-8.245277404785156]]],[[[143.67776679992676,-8.174722671508789],[143.6049518585205,-8.108888626098633],[143.70025825500488,-8.106109619140625],[143.67776679992676,-8.174722671508789]]],[[[143.73108100891113,-8.071666717529297],[143.58856391906738,-8.071666717529297],[143.56524848937988,-8.020000457763672],[143.73108100891113,-8.071666717529297]]],[[[145.1935749053955,-7.867221832275391],[145.18054389953613,-7.861110687255859],[145.182466506958,-7.827777862548828],[145.1935749053955,-7.867221832275391]]],[[[143.99969673156738,-7.824443817138672],[143.8771686553955,-7.709722518920898],[143.96692085266113,-7.748332977294922],[143.99969673156738,-7.824443817138672]]],[[[154.88244819641113,-5.543333053588867],[155.91858100891113,-6.807777404785156],[155.2399616241455,-6.622499465942383],[154.74438667297363,-5.939779281616211],[154.88244819641113,-5.543333053588867]]],[[[148.0614948272705,-5.777116775512695],[147.86511421203613,-5.747753143310547],[147.78027534484863,-5.494165420532227],[148.0614948272705,-5.777116775512695]]],[[[148.12079048156738,-5.468332290649414],[148.071626663208,-5.424444198608398],[148.099702835083,-5.377498626708984],[148.12079048156738,-5.468332290649414]]],[[[147.60217475891113,-5.361944198608398],[147.5605182647705,-5.318889617919922],[147.60913276672363,-5.288055419921875],[147.60217475891113,-5.361944198608398]]],[[[147.15332221984863,-5.44972038269043],[147.0080280303955,-5.350276947021484],[147.1210651397705,-5.191110610961914],[147.15332221984863,-5.44972038269043]]],[[[154.67553901672363,-5.440832138061523],[154.53027534484863,-5.133888244628906],[154.63916206359863,-5.016387939453125],[154.67553901672363,-5.440832138061523]]],[[[149.15692329406738,-4.923055648803711],[149.118013381958,-4.889444351196289],[149.16192817687988,-4.866388320922852],[149.15692329406738,-4.923055648803711]]],[[[146.24661445617676,-4.857500076293945],[146.19940376281738,-4.833610534667969],[146.21997261047363,-4.788331985473633],[146.24661445617676,-4.857500076293945]]],[[[149.55719184875488,-4.718889236450195],[149.45581245422363,-4.679166793823242],[149.5402545928955,-4.653888702392578],[149.55719184875488,-4.718889236450195]]],[[[159.516939163208,-4.578056335449219],[159.51138496398926,-4.576665878295898],[159.51886177062988,-4.536388397216797],[159.516939163208,-4.578056335449219]]],[[[145.95135688781738,-4.764444351196289],[145.87246894836426,-4.67249870300293],[145.98163032531738,-4.527500152587891],[145.95135688781738,-4.764444351196289]]],[[[154.1552448272705,-4.438055038452148],[154.13272285461426,-4.371665954589844],[154.15277290344238,-4.379444122314453],[154.1552448272705,-4.438055038452148]]],[[[152.23523139953613,-4.207221984863281],[152.40582466125488,-4.688888549804688],[151.970796585083,-4.993331909179688],[152.09607124328613,-5.457221984863281],[151.45941352844238,-5.535833358764648],[150.46856880187988,-6.276111602783203],[149.05691719055176,-6.164165496826172],[148.323091506958,-5.675376892089844],[148.42859077453613,-5.45111083984375],[149.88080024719238,-5.534999847412109],[150.08886909484863,-5.007778167724609],[150.16443061828613,-5.551387786865234],[150.924409866333,-5.487220764160156],[151.67608833312988,-4.908054351806641],[151.51165962219238,-4.204444885253906],[152.23523139953613,-4.207221984863281]],[[149.05359077453613,-6.094165802001953],[149.05414009094238,-6.083889007568359],[149.04385566711426,-6.088611602783203],[149.05359077453613,-6.094165802001953]]],[[[145.05774116516113,-4.135276794433594],[145.06884956359863,-4.045000076293945],[145.109956741333,-4.098333358764648],[145.05774116516113,-4.135276794433594]]],[[[153.64554023742676,-4.140277862548828],[153.58441352844238,-4.095832824707031],[153.65860176086426,-4.019166946411133],[153.64554023742676,-4.140277862548828]]],[[[153.25833320617676,-3.49888801574707],[153.19384956359863,-3.468610763549805],[153.23358345031738,-3.446666717529297],[153.25833320617676,-3.49888801574707]]],[[[154.83304023742676,-3.510276794433594],[154.8185749053955,-3.530277252197266],[154.799409866333,-3.424999237060547],[154.83304023742676,-3.510276794433594]]],[[[153.34524726867676,-3.411943435668945],[153.26248359680176,-3.404443740844727],[153.333589553833,-3.371389389038086],[153.34524726867676,-3.411943435668945]]],[[[152.64636421203613,-3.228610992431641],[152.53888130187988,-3.106109619140625],[152.599702835083,-3.048055648803711],[152.64636421203613,-3.228610992431641]]],[[[150.94134712219238,-2.921943664550781],[151.02163887023926,-2.971942901611328],[150.7660846710205,-2.979442596435547],[150.94134712219238,-2.921943664550781]]],[[[152.06997871398926,-3.001388549804688],[151.97357368469238,-2.848054885864258],[152.07885932922363,-2.928333282470703],[152.06997871398926,-3.001388549804688]]],[[[152.00219917297363,-2.828887939453125],[151.93164253234863,-2.832500457763672],[151.932466506958,-2.708332061767578],[152.00219917297363,-2.828887939453125]]],[[[150.90652656555176,-2.635944366455078],[152.05581855773926,-3.247777938842773],[152.98968696594238,-4.075832366943359],[152.97467231750488,-4.766666412353516],[152.73550605773926,-4.660833358764648],[152.69165229797363,-4.18055534362793],[152.28247261047363,-3.572776794433594],[150.72967720031738,-2.740554809570313],[150.90652656555176,-2.635944366455078]]],[[[141.889986038208,-2.969999313354492],[144.51165962219238,-3.820833206176758],[145.73550605773926,-4.802776336669922],[145.76638984680176,-5.48527717590332],[147.47686958312988,-5.974191665649414],[147.86941719055176,-6.660833358764648],[146.96136665344238,-6.747220993041992],[147.17859077453613,-7.463888168334961],[148.13525581359863,-8.066110610961914],[148.60412788391113,-9.082500457763672],[149.31469917297363,-9.018890380859375],[149.21997261047363,-9.474721908569336],[150.008882522583,-9.631387710571289],[149.71747016906738,-9.826665878295898],[149.914155960083,-10.04888916015625],[150.87829780578613,-10.231666564941406],[150.3691120147705,-10.321945190429688],[150.69134712219238,-10.561111450195312],[150.2096881866455,-10.700555801391602],[149.74774360656738,-10.342777252197266],[147.95245552062988,-10.145833969116211],[147.05523872375488,-9.466665267944336],[146.97247505187988,-9.029167175292969],[146.5866413116455,-8.999164581298828],[146.089693069458,-8.091110229492188],[144.52054023742676,-7.501943588256836],[144.21301460266113,-7.795276641845703],[143.66482734680176,-7.467649459838867],[143.95800971984863,-7.978622436523438],[143.35830879211426,-7.902500152587891],[143.611909866333,-8.243888854980469],[142.13720893859863,-8.225555419921875],[143.11023139953613,-8.470277786254883],[143.331636428833,-9.02833366394043],[142.6388874053955,-9.334722518920898],[141.00702095031738,-9.128467559814453],[141.00247383117676,-2.607084274291992],[141.889986038208,-2.969999313354492]]],[[[152.02221870422363,-2.667499542236328],[151.9577350616455,-2.664722442626953],[151.9838581085205,-2.596111297607422],[152.02221870422363,-2.667499542236328]]],[[[150.45831489562988,-2.653610229492188],[149.948579788208,-2.47166633605957],[150.21637153625488,-2.377777099609375],[150.45831489562988,-2.653610229492188]]],[[[147.8124713897705,-2.349721908569336],[147.81524848937988,-2.243610382080078],[147.8791217803955,-2.293611526489258],[147.8124713897705,-2.349721908569336]]],[[[147.30081367492676,-2.025278091430664],[146.524995803833,-2.190832138061523],[146.63858222961426,-1.978610992431641],[147.30081367492676,-2.025278091430664]]],[[[142.86636543273926,-1.697776794433594],[142.81360054016113,-1.732776641845703],[142.82107734680176,-1.695833206176758],[142.86636543273926,-1.697776794433594]]],[[[149.7196979522705,-1.433332443237305],[149.7319049835205,-1.60333251953125],[149.52777290344238,-1.454442977905273],[149.7196979522705,-1.433332443237305]]],[[[144.52191352844238,-1.395553588867188],[144.50555610656738,-1.380556106567383],[144.51638984680176,-1.381942749023438],[144.52191352844238,-1.395553588867188]]],[[[144.52054023742676,-1.120832443237305],[144.51443672180176,-1.116109848022461],[144.51721382141113,-1.098333358764648],[144.52054023742676,-1.120832443237305]]]]}},{"type":"Feature","properties":{"name":"Guinea-Bissau","iso2":"GW","iso3":"GNB"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-15.885834,11.052221],[-15.981111999999882,11.049444000000122],[-15.94639,11.195],[-15.885834,11.052221]]],[[[-16.005836,11.068333],[-16.06139,11.163055],[-15.980556,11.202499000000131],[-16.005836,11.068333]]],[[[-16.088058,11.025555],[-16.24416699999989,11.100555],[-16.0825,11.206944],[-16.088058,11.025555]]],[[[-15.862223,11.199999],[-15.906388999999876,11.224998],[-15.830278,11.300833],[-15.862223,11.199999]]],[[[-15.740002,11.166943],[-15.77639,11.225832000000167],[-15.667501,11.306389],[-15.740002,11.166943]]],[[[-16.17778,11.2152770000001],[-16.264446,11.281666],[-16.160835,11.290277000000103],[-16.17778,11.2152770000001]]],[[[-15.679724,11.439444000000108],[-15.743057,11.458332],[-15.665834,11.502222000000131],[-15.679724,11.439444000000108]]],[[[-16.21278,11.439722],[-16.300556,11.449444],[-16.16444799999988,11.514999],[-16.21278,11.439722]]],[[[-16.250557,11.536665],[-16.419445,11.482777],[-16.393889999999885,11.545832000000132],[-16.250557,11.536665]]],[[[-15.952501,11.423054],[-16.065002,11.44972],[-15.958334,11.594166],[-15.952501,11.423054]]],[[[-15.553057,11.517221],[-15.633612,11.535276],[-15.472223,11.631109000000109],[-15.553057,11.517221]]],[[[-16.031948,11.755833],[-16.162224,11.86861],[-15.978334,11.905832],[-16.031948,11.755833]]],[[[-16.236389,11.836943],[-16.30167,11.971666000000113],[-16.184723,11.876665],[-16.236389,11.836943]]],[[[-14.516945,12.67972200000014],[-13.713139,12.677221],[-13.971035,12.154758],[-13.709167,11.715277],[-14.686944999999895,11.509722],[-15.016847999999868,10.956451000000143],[-15.022779,11.195276],[-15.407223,11.184999],[-15.26528,11.425913],[-15.509167,11.338055],[-15.027223999999876,11.594166],[-15.55666699999989,11.723331],[-14.931946,11.750832],[-15.003889,11.974165000000113],[-15.963335,11.734165000000132],[-15.704445,12.004444],[-15.852779,12.016666],[-16.128056,11.881943],[-16.333893,11.996664],[-16.334446,12.15111],[-16.110558,12.330832],[-16.71777,12.322426],[-14.516945,12.67972200000014]]]]}},{"type":"Feature","properties":{"name":"Qatar","iso2":"QA","iso3":"QAT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[51.51759,25.383415],[51.611664,25.010277],[51.215164,24.620888],[50.830956,24.749966],[51.042496,26.049442],[51.568054,25.908333],[51.51759,25.383415]]]]}},{"type":"Feature","properties":{"name":"Reunion","iso2":"RE","iso3":"REU"},"geometry":{"type":"MultiPolygon","coordinates":[[[[55.709999,-20.998058],[55.674164,-21.37389],[55.219719,-21.027779],[55.709999,-20.998058]]]]}},{"type":"Feature","properties":{"name":"Romania","iso2":"RO","iso3":"ROU"},"geometry":{"type":"MultiPolygon","coordinates":[[[[20.726955,46.17556],[21.176666,46.295555],[22.032497,47.530273],[22.894804,47.95454],[24.91944100000012,47.711662],[26.634995,48.257164],[28.119717,46.854404],[28.21484,45.448647],[29.664331,45.211803],[29.549438,44.820267],[28.868324,44.943047],[28.583244,43.747765],[27.036427,44.147339],[25.430229,43.626778],[24.179996,43.684715],[22.875275,43.842499],[23.044167,44.076111],[22.681435,44.224701],[22.457333,44.474358],[22.764893,44.559006],[22.479164,44.710274],[22.146385,44.479164],[21.400398,44.780823],[21.513611,45.151108],[20.261024,46.114853],[20.726955,46.17556]]]]}},{"type":"Feature","properties":{"name":"Republic of Moldova","iso2":"MD","iso3":"MDA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[28.119717,46.854404],[26.634995,48.257164],[27.755554,48.451385],[29.141937000000155,47.98609200000014],[29.184441,47.443047],[29.949997,46.814156],[30.11694,46.386101],[28.994434,46.47832500000011],[28.971935,46.006653],[28.21484,45.448647],[28.119717,46.854404]]]]}},{"type":"Feature","properties":{"name":"Philippines","iso2":"PH","iso3":"PHL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[119.47221565246582,4.648054122924805],[119.45583534240723,4.90888786315918],[119.51053810119629,4.763887405395508],[119.47221565246582,4.648054122924805]]],[[[120.01915168762207,5.030279159545898],[120.01888465881348,5.02861213684082],[120.01471138000488,5.030832290649414],[120.01915168762207,5.030279159545898]]],[[[119.94719886779785,5.076944351196289],[119.93414497375488,5.075834274291992],[119.94109535217285,5.083612442016602],[119.94719886779785,5.076944351196289]]],[[[120.24414253234863,5.300832748413086],[120.22664833068848,5.306390762329102],[120.23108863830566,5.325002670288086],[120.24414253234863,5.300832748413086]]],[[[120.25360298156738,5.233335494995117],[119.83110237121582,5.059164047241211],[120.17775917053223,5.343610763549805],[120.25360298156738,5.233335494995117]]],[[[125.41470527648926,5.361112594604492],[125.32998847961426,5.38722038269043],[125.40582466125488,5.430276870727539],[125.41470527648926,5.361112594604492]]],[[[125.47831916809082,5.388334274291992],[125.45027351379395,5.421945571899414],[125.47943305969238,5.491945266723633],[125.47831916809082,5.388334274291992]]],[[[120.86971473693848,5.491388320922852],[120.84332466125488,5.585000991821289],[120.90999031066895,5.536111831665039],[120.86971473693848,5.491388320922852]]],[[[121.18387031555176,5.787500381469727],[121.13916206359863,5.785276412963867],[121.1463794708252,5.84889030456543],[121.18387031555176,5.787500381469727]]],[[[121.18525886535645,6.039999008178711],[121.42581367492676,5.95250129699707],[120.87552833557129,5.921110153198242],[121.18525886535645,6.039999008178711]]],[[[121.86303901672363,6.016389846801758],[121.76277351379395,6.09083366394043],[121.95332527160645,6.051111221313477],[121.86303901672363,6.016389846801758]]],[[[120.56833076477051,6.244722366333008],[120.47776985168457,6.264165878295898],[120.59971809387207,6.396112442016602],[120.56833076477051,6.244722366333008]]],[[[122.23027229309082,6.660833358764648],[122.03386878967285,6.411111831665039],[121.79471015930176,6.593610763549805],[122.23027229309082,6.660833358764648]]],[[[118.53360176086426,7.035001754760742],[118.54026985168457,6.965276718139648],[118.41721534729004,7.022222518920898],[118.53360176086426,7.035001754760742]]],[[[125.79498481750488,6.932775497436523],[125.66998481750488,7.075002670288086],[125.69914436340332,7.191667556762695],[125.79498481750488,6.932775497436523]]],[[[117.02221870422363,7.808889389038086],[116.94999885559082,8.032220840454102],[117.06553840637207,8.078611373901367],[117.02221870422363,7.808889389038086]]],[[[117.29886817932129,8.182222366333008],[117.26805305480957,8.306108474731445],[117.31804847717285,8.331110000610352],[117.29886817932129,8.182222366333008]]],[[[126.23665046691895,9.008333206176758],[126.23166084289551,8.998052597045898],[126.22943305969238,9.013055801391602],[126.23665046691895,9.008333206176758]]],[[[126.26361274719238,8.997220993041992],[126.24664497375488,9.013612747192383],[126.26053810119629,9.00666618347168],[126.26361274719238,8.997220993041992]]],[[[123.67498970031738,9.226388931274414],[123.60942268371582,9.092222213745117],[123.45720863342285,9.190553665161133],[123.67498970031738,9.226388931274414]]],[[[124.77858924865723,9.075555801391602],[124.64360237121582,9.155279159545898],[124.67276191711426,9.253053665161133],[124.77858924865723,9.075555801391602]]],[[[123.77361488342285,9.544164657592773],[123.74471473693848,9.595277786254883],[123.84499549865723,9.636110305786133],[123.77361488342285,9.544164657592773]]],[[[125.95247840881348,9.557500839233398],[125.90054512023926,9.616941452026367],[125.93831062316895,9.756387710571289],[125.95247840881348,9.557500839233398]]],[[[126.0486011505127,9.231943130493164],[126.58582496643066,7.285001754760742],[126.16526985168457,6.88166618347168],[126.19165229797363,6.272222518920898],[125.85555458068848,7.349721908569336],[125.65220832824707,7.236665725708008],[125.37719917297363,6.719720840454102],[125.70332527160645,6.027223587036133],[125.40555000305176,5.563333511352539],[125.26361274719238,6.091665267944336],[124.95694160461426,5.851388931274414],[124.1858081817627,6.210554122924805],[123.94859504699707,6.823335647583008],[124.26860237121582,7.374444961547852],[123.6766529083252,7.812498092651367],[123.45471382141113,7.367498397827148],[123.11638069152832,7.72944450378418],[122.83276557922363,7.275278091430664],[122.62387275695801,7.773054122924805],[122.14998817443848,6.905279159545898],[121.92109870910645,6.994165420532227],[122.22331428527832,7.962221145629883],[122.92302894592285,8.15083122253418],[123.37915229797363,8.72722053527832],[123.81804847717285,8.47694206237793],[123.67109870910645,7.953889846801758],[124.43221473693848,8.615274429321289],[124.72747993469238,8.486387252807617],[124.80386543273926,9.001665115356445],[125.51471138000488,9.00666618347168],[125.44026374816895,9.809164047241211],[126.0486011505127,9.231943130493164]]],[[[124.57415962219238,9.854719161987305],[124.56609535217285,9.849443435668945],[124.56553840637207,9.861944198608398],[124.57415962219238,9.863332748413086],[124.57415962219238,9.854719161987305]]],[[[123.38443183898926,9.878885269165039],[123.3722095489502,9.880552291870117],[123.37970161437988,9.888055801391602],[123.38443183898926,9.878885269165039]]],[[[126.11303901672363,9.744443893432617],[125.94553565979004,9.830831527709961],[126.06025886535645,10.054166793823242],[126.11303901672363,9.744443893432617]]],[[[124.48387336730957,10.050832748413086],[124.36554145812988,9.626943588256836],[123.79332160949707,9.72944450378418],[124.14888191223145,10.146944046020508],[124.48387336730957,10.050832748413086]]],[[[125.28692817687988,9.90916633605957],[125.12664985656738,10.155832290649414],[125.21748542785645,10.122220993041992],[125.28692817687988,9.90916633605957]]],[[[125.6594181060791,9.82472038269043],[125.47527503967285,10.131109237670898],[125.64526557922363,10.468889236450195],[125.6594181060791,9.82472038269043]]],[[[119.82721138000488,10.439722061157227],[119.75833320617676,10.556943893432617],[120.00248908996582,10.591386795043945],[119.82721138000488,10.439722061157227]]],[[[124.3672046661377,10.60777473449707],[124.27581977844238,10.587778091430664],[124.32054328918457,10.706941604614258],[124.3672046661377,10.60777473449707]]],[[[124.43747901916504,10.624998092651367],[124.45139503479004,10.714998245239258],[124.51748847961426,10.659444808959961],[124.43747901916504,10.624998092651367]]],[[[122.6352710723877,10.443609237670898],[122.47971534729004,10.487775802612305],[122.6594181060791,10.748331069946289],[122.6352710723877,10.443609237670898]]],[[[125.80246925354004,10.688886642456055],[125.6624927520752,10.750833511352539],[125.69220161437988,10.823610305786133],[125.80246925354004,10.688886642456055]]],[[[123.56387519836426,10.794164657592773],[123.13638496398926,9.836111068725586],[123.29637336730957,9.229719161987305],[123.01471138000488,9.03388786315918],[122.45276832580566,9.973333358764648],[122.85832405090332,10.097497940063477],[122.95247840881348,10.894445419311523],[123.56387519836426,10.794164657592773]]],[[[121.0405445098877,10.79194450378418],[121.00388526916504,10.836111068725586],[121.08110237121582,10.905279159545898],[121.0405445098877,10.79194450378418]]],[[[124.01987648010254,11.11894416809082],[124.02693367004395,10.381940841674805],[123.31025886535645,9.411943435668945],[124.01987648010254,11.11894416809082]]],[[[123.75081825256348,11.147500991821289],[123.69275093078613,11.22138786315918],[123.7330493927002,11.300554275512695],[123.75081825256348,11.147500991821289]]],[[[119.50857734680176,11.335607528686523],[119.71248817443848,10.497499465942383],[117.1858081817627,8.325555801391602],[119.31247901916504,10.582498550415039],[119.21692848205566,10.959997177124023],[119.45610237121582,10.723608016967773],[119.50857734680176,11.335607528686523]]],[[[119.53386878967285,11.362497329711914],[119.52221870422363,11.366666793823242],[119.54026985168457,11.373052597045898],[119.53386878967285,11.362497329711914]]],[[[119.83249092102051,11.376943588256836],[119.71470832824707,11.476110458374023],[119.87137031555176,11.50666618347168],[119.83249092102051,11.376943588256836]]],[[[124.63889503479004,11.293333053588867],[124.94748115539551,11.42500114440918],[125.02998542785645,11.195833206176758],[125.27165412902832,10.29749870300293],[124.98027229309082,10.37916374206543],[125.01471138000488,10.027776718139648],[124.28970527648926,11.541387557983398],[124.63889503479004,11.293333053588867]]],[[[124.58471870422363,11.472497940063477],[124.3388843536377,11.68083381652832],[124.53137397766113,11.679719924926758],[124.58471870422363,11.472497940063477]]],[[[124.83167457580566,11.528886795043945],[124.71805000305176,11.72722053527832],[124.84276008605957,11.591665267944336],[124.83167457580566,11.528886795043945]]],[[[122.22943305969238,11.79777717590332],[122.88081550598145,11.429166793823242],[123.15305519104004,11.600275039672852],[123.12859535217285,11.174444198608398],[121.94331550598145,10.416387557983398],[122.09887886047363,11.69999885559082],[121.8480396270752,11.760000228881836],[122.22943305969238,11.79777717590332]]],[[[119.96527290344238,11.656942367553711],[119.88498878479004,11.976110458374023],[120.07054328918457,11.864999771118164],[119.96527290344238,11.656942367553711]],[[120.04637336730957,11.823331832885742],[120.04609870910645,11.826387405395508],[120.04387092590332,11.824441909790039],[120.04637336730957,11.823331832885742]]],[[[120.26805305480957,11.826944351196289],[120.20276832580566,11.946111679077148],[120.25444221496582,11.982221603393555],[120.26805305480957,11.826944351196289]]],[[[120.08471870422363,11.958608627319336],[120.06553840637207,11.964166641235352],[120.06165504455566,11.992498397827148],[120.08471870422363,11.958608627319336]]],[[[119.95358467102051,12.021665573120117],[119.95025825500488,12.030553817749023],[119.95941352844238,12.036943435668945],[119.95358467102051,12.021665573120117]]],[[[121.13749885559082,12.157499313354492],[121.04276466369629,12.22944450378418],[121.04582405090332,12.290555953979492],[121.13749885559082,12.157499313354492]]],[[[120.16829872131348,12.118330001831055],[120.3399829864502,11.992776870727539],[119.87387275695801,12.314443588256836],[120.16829872131348,12.118330001831055]]],[[[122.68109321594238,12.308053970336914],[122.43248176574707,12.461111068725586],[122.66943550109863,12.483610153198242],[122.68109321594238,12.308053970336914]]],[[[124.4638843536377,12.520833969116211],[125.29694557189941,12.457498550415039],[125.7602710723877,11.011667251586914],[125.26944160461426,11.128053665161133],[124.96999549865723,11.447500228881836],[124.84359931945801,11.466386795043945],[125.04248237609863,11.747220993041992],[124.38693428039551,12.190275192260742],[124.25804328918457,12.55555534362793],[124.4638843536377,12.520833969116211]],[[125.67249488830566,11.089998245239258],[125.68193244934082,11.103609085083008],[125.66470527648926,11.102777481079102],[125.67249488830566,11.089998245239258]]],[[[123.66943550109863,12.346944808959961],[124.07639503479004,11.718332290649414],[123.53027534484863,12.208608627319336],[123.15776252746582,11.908609390258789],[123.24165534973145,12.606943130493164],[123.66943550109863,12.346944808959961]]],[[[122.30693244934082,12.486387252807617],[122.24803352355957,12.56110954284668],[122.28305244445801,12.633333206176758],[122.30693244934082,12.486387252807617]]],[[[123.79221534729004,12.344999313354492],[123.58554267883301,12.660554885864258],[123.72776985168457,12.601663589477539],[123.79221534729004,12.344999313354492]]],[[[122.0486011505127,12.176664352416992],[121.91748237609863,12.304166793823242],[122.12275886535645,12.676942825317383],[122.0486011505127,12.176664352416992]]],[[[123.38247871398926,12.69194221496582],[122.93193244934082,13.10999870300293],[123.0486011505127,13.134721755981445],[123.38247871398926,12.69194221496582]]],[[[124.21805000305176,13.17249870300293],[124.07832527160645,13.211111068725586],[124.16330909729004,13.232221603393555],[124.21805000305176,13.17249870300293]]],[[[124.04609870910645,13.220552444458008],[123.95610237121582,13.232500076293945],[123.91499519348145,13.286386489868164],[124.09887886047363,13.260557174682617],[124.04609870910645,13.220552444458008]]],[[[123.91304206848145,13.24305534362793],[123.87915229797363,13.22944450378418],[123.85386848449707,13.267221450805664],[123.8510913848877,13.35194206237793],[123.93081855773926,13.324441909790039],[123.89048194885254,13.278779983520508],[123.91304206848145,13.24305534362793]]],[[[122.1513843536377,13.39555549621582],[122.13165473937988,13.40083122253418],[122.12608528137207,13.421945571899414],[122.1513843536377,13.39555549621582]]],[[[122.12343788146973,13.404104232788086],[122.00332832336426,13.20222282409668],[121.81331062316895,13.448610305786133],[122.12343788146973,13.404104232788086]]],[[[120.72165107727051,13.477777481079102],[121.5022144317627,13.148889541625977],[121.55832099914551,12.601110458374023],[121.22054481506348,12.230554580688477],[120.30330848693848,13.443609237670898],[120.72165107727051,13.477777481079102]]],[[[120.28193855285645,13.754167556762695],[120.27469825744629,13.668333053588867],[120.07998847961426,13.849164962768555],[120.28193855285645,13.754167556762695]]],[[[124.28736305236816,13.946176528930664],[124.20804023742676,13.515275955200195],[124.03055000305176,13.663888931274414],[124.28736305236816,13.946176528930664]]],[[[124.30108833312988,13.95222282409668],[124.29414558410645,13.95805549621582],[124.30304145812988,13.96360969543457],[124.30108833312988,13.95222282409668]]],[[[124.34221076965332,13.942220687866211],[124.3127613067627,13.954999923706055],[124.32527351379395,13.981943130493164],[124.34221076965332,13.942220687866211]]],[[[122.17109870910645,13.99860954284668],[121.91748237609863,14.185277938842773],[122.12442207336426,14.088888168334961],[122.17109870910645,13.99860954284668]]],[[[122.25417518615723,14.722497940063477],[122.09860420227051,14.837778091430664],[122.21304512023926,14.839166641235352],[122.25417518615723,14.722497940063477]]],[[[122.05081367492676,14.996664047241211],[121.93081855773926,14.62916374206543],[121.81915473937988,14.991666793823242],[122.05081367492676,14.996664047241211]]],[[[120.00026893615723,16.225553512573242],[119.92442512512207,16.2994441986084],[119.97415351867676,16.34666633605957],[120.00277900695801,16.34055519104004],[120.00026893615723,16.225553512573242]]],[[[121.25665473937988,18.566110610961914],[121.93665504455566,18.269445419311523],[122.24165534973145,18.51277732849121],[122.17025947570801,17.607221603393555],[122.53333473205566,17.099443435668945],[121.37886238098145,15.332220077514648],[121.73387336730957,14.170831680297852],[122.23332405090332,13.897222518920898],[122.1655445098877,14.158056259155273],[122.71331977844238,14.33833122253418],[123.0999927520752,13.667497634887695],[123.34305000305176,14.086942672729492],[123.92498970031738,13.789167404174805],[123.53193855285645,13.575555801391602],[123.76277351379395,13.061666488647461],[124.19582557678223,13.057775497436523],[124.08276557922363,12.540555953979492],[123.84887886047363,12.731943130493164],[124.02858924865723,12.963052749633789],[123.32222175598145,13.008611679077148],[122.56099891662598,13.936567306518555],[122.60748481750488,13.163888931274414],[121.75470924377441,13.964445114135742],[121.27942848205566,13.593889236450195],[120.66110420227051,13.768331527709961],[120.59221076965332,14.231111526489258],[120.95665168762207,14.636945724487305],[120.5516529083252,14.826944351196289],[120.49331855773926,14.429719924926758],[120.08611488342285,14.785276412963867],[119.78692817687988,16.32305335998535],[119.92886543273926,16.38499641418457],[119.91914558410645,16.2902774810791],[119.93525886535645,16.242773056030273],[120.15664863586426,16.03611183166504],[120.42192268371582,16.155832290649414],[120.57054328918457,18.49083137512207],[121.25665473937988,18.566110610961914]],[[122.73526191711426,13.774168014526367],[122.74498176574707,13.781667709350586],[122.72747993469238,13.777223587036133],[122.73526191711426,13.774168014526367]]],[[[121.40054512023926,18.847219467163086],[121.27942848205566,18.86610984802246],[121.48442268371582,18.882776260375977],[121.40054512023926,18.847219467163086]]],[[[121.88275337219238,18.83333396911621],[121.83305549621582,18.880552291870117],[121.94609260559082,19.004446029663086],[121.88275337219238,18.83333396911621]]],[[[121.25139045715332,19.011945724487305],[121.20192909240723,19.065275192260742],[121.22026252746582,19.172773361206055],[121.25139045715332,19.011945724487305]]],[[[121.53970527648926,19.26666831970215],[121.37275886535645,19.364442825317383],[121.53055000305176,19.389719009399414],[121.53970527648926,19.26666831970215]]],[[[121.97470283508301,19.479997634887695],[121.90305519104004,19.550275802612305],[121.99359321594238,19.565275192260742],[121.97470283508301,19.479997634887695]]],[[[121.88693428039551,20.283334732055664],[121.84192848205566,20.282499313354492],[121.84636878967285,20.3527774810791],[121.88693428039551,20.283334732055664]]],[[[121.95443916320801,20.348608016967773],[121.92386817932129,20.4072208404541],[122.02665901184082,20.48333168029785],[121.95443916320801,20.348608016967773]]],[[[121.81218910217285,20.686662673950195],[121.87082099914551,20.8347225189209],[121.88333320617676,20.765275955200195],[121.81218910217285,20.686662673950195]]],[[[121.95694160461426,21.103609085083008],[121.94941902160645,21.106107711791992],[121.94970893859863,21.11805534362793],[121.95694160461426,21.103609085083008]]]]}},{"type":"Feature","properties":{"name":"Puerto Rico","iso2":"PR","iso3":"PRI"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-67.880569,18.048332],[-67.93084699999989,18.109722000000104],[-67.84668,18.10749800000012],[-67.880569,18.048332]]],[[[-65.441391,18.090275],[-65.580292,18.114719],[-65.301117,18.147778],[-65.441391,18.090275]]],[[[-65.242783,18.302219],[-65.27528399999989,18.276943],[-65.338898,18.346664],[-65.242783,18.302219]]],[[[-66.99667399999987,18.504997],[-65.603058,18.232498],[-67.1872249999999,17.932499],[-67.266113,18.368053],[-66.99667399999987,18.504997]]]]}},{"type":"Feature","properties":{"name":"Russia","iso2":"RU","iso3":"RUS"},"geometry":{"type":"MultiPolygon","coordinates":[[[[131.87329292297363,42.95694160461426],[131.77997016906738,43.04944038391113],[131.9172077178955,43.02110481262207],[131.87329292297363,42.95694160461426]]],[[[146.13748359680176,43.45888710021973],[146.07608222961426,43.51333045959473],[146.22607612609863,43.52555274963379],[146.13748359680176,43.45888710021973]]],[[[146.66998481750488,43.70443916320801],[146.60467720031738,43.80388069152832],[146.90497016906738,43.83999061584473],[146.66998481750488,43.70443916320801]]],[[[47.73971748352051,43.93221473693848],[47.62803840637207,43.974435806274414],[47.78555488586426,43.958879470825195],[47.73971748352051,43.93221473693848]]],[[[146.148042678833,44.50999641418457],[146.56802558898926,44.43832588195801],[145.4374713897705,43.716936111450195],[146.148042678833,44.50999641418457]]],[[[148.82525825500488,45.33499336242676],[146.84051704406738,44.415544509887695],[147.93274116516113,45.4213809967041],[148.82525825500488,45.33499336242676]]],[[[47.96249580383301,45.50499153137207],[47.960275650024414,45.65304756164551],[47.99387550354004,45.53665351867676],[47.96249580383301,45.50499153137207]]],[[[48.468881607055664,45.67388343811035],[48.33777046203613,45.79721260070801],[48.404428482055664,45.794992446899414],[48.468881607055664,45.67388343811035]]],[[[48.72331428527832,45.698320388793945],[48.591928482055664,45.74749183654785],[48.49582862854004,45.882211685180664],[48.72331428527832,45.698320388793945]]],[[[150.0663776397705,45.847490310668945],[149.4374713897705,45.58360481262207],[150.49856758117676,46.19249153137207],[150.0663776397705,45.847490310668945]]],[[[150.874116897583,46.44082832336426],[150.79852485656738,46.44998359680176],[150.84192085266113,46.47110176086426],[150.874116897583,46.44082832336426]]],[[[150.764986038208,46.70388221740723],[150.730806350708,46.72276496887207],[150.76220893859863,46.727487564086914],[150.764986038208,46.70388221740723]]],[[[152.22552680969238,47.17471504211426],[152.013032913208,46.88888740539551],[151.71219062805176,46.801103591918945],[152.22552680969238,47.17471504211426]]],[[[152.519136428833,47.30721473693848],[152.388032913208,47.34415626525879],[152.5038776397705,47.377214431762695],[152.519136428833,47.30721473693848]]],[[[153.0160846710205,47.69304847717285],[153.07412910461426,47.80832862854004],[153.08026313781738,47.71415901184082],[153.0160846710205,47.69304847717285]]],[[[153.29052925109863,48.053606033325195],[153.13775825500488,48.10110664367676],[153.22329902648926,48.1330509185791],[153.29052925109863,48.053606033325195]]],[[[154.01944160461426,48.72332191467285],[154.11218452453613,48.89499855041504],[154.228853225708,48.90249061584473],[154.01944160461426,48.72332191467285]]],[[[153.9819049835205,48.92666053771973],[153.90191841125488,48.969987869262695],[154.00470161437988,48.96360969543457],[153.9819049835205,48.92666053771973]]],[[[154.454683303833,49.16916084289551],[154.5988483428955,49.11194038391113],[154.50055122375488,49.07444190979004],[154.454683303833,49.16916084289551]]],[[[154.7157917022705,49.26388740539551],[154.60244941711426,49.373605728149414],[154.90442085266113,49.624162673950195],[154.7157917022705,49.26388740539551]]],[[[154.42498970031738,49.73360633850098],[154.3749713897705,49.82499885559082],[154.45996284484863,49.81388282775879],[154.42498970031738,49.73360633850098]]],[[[155.78552436828613,50.18499183654785],[155.208589553833,50.080827713012695],[156.10412788391113,50.76111030578613],[155.78552436828613,50.18499183654785]]],[[[156.4038257598877,50.653398513793945],[156.16443061828613,50.72860145568848],[156.46386909484863,50.86944007873535],[156.4038257598877,50.653398513793945]]],[[[155.62079048156738,50.806100845336914],[155.44775581359863,50.897775650024414],[155.63916206359863,50.92083168029785],[155.62079048156738,50.806100845336914]]],[[[143.66192817687988,49.312211990356445],[143.2460651397705,49.379159927368164],[143.32025337219238,49.313608169555664],[143.66192817687988,49.312211990356445],[143.01776313781738,49.139719009399414],[142.53470039367676,48.00277900695801],[143.08828926086426,46.80166053771973],[143.49164009094238,46.808603286743164],[143.4738483428955,46.0927677154541],[143.37857246398926,46.5483341217041],[142.7096881866455,46.744157791137695],[142.07745552062988,45.89138221740723],[141.81274604797363,46.58610725402832],[142.18887519836426,47.97526741027832],[141.85244941711426,48.75027656555176],[142.26721382141113,51.12027168273926],[141.638032913208,52.31582832336426],[141.766939163208,53.37137794494629],[142.7983112335205,53.69748878479004],[142.39386177062988,54.237497329711914],[142.696626663208,54.42471504211426],[143.29080390930176,53.13027381896973],[143.220796585083,51.521379470825195],[144.75164985656738,48.64193916320801],[143.66192817687988,49.312211990356445]]],[[[137.77997016906738,54.36638832092285],[137.70831489562988,54.368600845336914],[137.91388130187988,54.50777626037598],[137.77997016906738,54.36638832092285]]],[[[137.632173538208,54.41304969787598],[137.54886054992676,54.5049991607666],[137.61856269836426,54.56527137756348],[137.632173538208,54.41304969787598]]],[[[19.697778701782227,54.479440689086914],[19.65110969543457,54.455827713012695],[19.627260208129883,54.463274002075195],[19.898202896118164,54.625959396362305],[19.697778701782227,54.479440689086914]]],[[[167.855806350708,54.68138313293457],[168.1169147491455,54.50777626037598],[167.43298530578613,54.86307716369629],[167.855806350708,54.68138313293457]]],[[[137.18829536437988,55.10222053527832],[137.04608345031738,54.917497634887695],[136.66726875305176,54.90506172180176],[137.18829536437988,55.10222053527832]]],[[[137.99133491516113,54.88555335998535],[137.70718574523926,54.61832618713379],[137.22131538391113,54.77372169494629],[137.57831001281738,55.1905460357666],[138.20413398742676,55.04388618469238],[137.99133491516113,54.88555335998535]]],[[[21.431386947631836,55.25193977355957],[22.842496871948242,54.89694404602051],[22.785886764526367,54.363840103149414],[19.797006607055664,54.437551498413086],[20.405000686645508,54.67916297912598],[19.872713088989258,54.64055061340332],[19.96944236755371,54.95749855041504],[20.942834854125977,55.28720283508301],[20.98481559753418,55.27655220031738],[20.538053512573242,54.94943428039551],[21.222497940063477,54.93194007873535],[21.26393699645996,55.24898719787598],[21.431386947631836,55.25193977355957]]],[[[166.1191120147705,55.3286075592041],[166.66302680969238,54.67416572570801],[165.83801460266113,55.26444435119629],[166.1191120147705,55.3286075592041]]],[[[164.65692329406738,59.08443641662598],[163.38553047180176,58.559404373168945],[163.69940376281738,59.01444435119629],[164.65692329406738,59.08443641662598]]],[[[150.59051704406738,59.01971626281738],[150.4545612335205,59.01780128479004],[150.74383735656738,59.11194038391113],[150.59051704406738,59.01971626281738]]],[[[149.10467720031738,59.18776893615723],[148.941011428833,59.141672134399414],[149.00525093078613,59.21110725402832],[149.10467720031738,59.18776893615723]]],[[[155.55581855773926,59.32193946838379],[155.47830390930176,59.317216873168945],[155.55581855773926,59.35916328430176],[155.55581855773926,59.32193946838379]]],[[[28.693052291870117,60.267770767211914],[28.551111221313477,60.349435806274414],[28.714998245239258,60.31138038635254],[28.693052291870117,60.267770767211914]]],[[[35.991106033325195,64.3258228302002],[35.854440689086914,64.40582466125488],[36.047494888305664,64.35554695129395],[35.991106033325195,64.3258228302002]]],[[[-172.54446411132812,64.61331367492676],[-172.75808715820312,64.66079902648926],[-172.48831176757812,64.63360786437988],[-172.54446411132812,64.61331367492676]]],[[[40.412492752075195,64.65359687805176],[40.47137641906738,64.56608772277832],[39.97471046447754,64.6827564239502],[40.412492752075195,64.65359687805176]]],[[[-172.590576171875,64.70331001281738],[-172.53115844726562,64.8430347442627],[-172.17111206054688,64.79525947570801],[-172.590576171875,64.70331001281738]]],[[[35.79083442687988,64.97331428527832],[35.52469825744629,65.15887641906738],[35.83443641662598,65.16832160949707],[35.79083442687988,64.97331428527832]]],[[[36.061662673950195,65.19026374816895],[36.30082893371582,65.20109748840332],[35.94332313537598,65.18193244934082],[36.061662673950195,65.19026374816895]]],[[[-169.0533447265625,65.74914741516113],[-169.07501220703125,65.81552314758301],[-168.98974609375,65.8088550567627],[-169.0533447265625,65.74914741516113]]],[[[69.33499336242676,66.6544361114502],[69.24331855773926,66.69331550598145],[69.33333015441895,66.71887397766113],[69.33499336242676,66.6544361114502]]],[[[70.03387641906738,66.72387886047363],[69.78915596008301,66.78027534484863],[69.95359992980957,66.76111030578613],[70.03387641906738,66.72387886047363]]],[[[42.7066593170166,66.68637275695801],[42.43249702453613,66.75860786437988],[42.62276649475098,66.78221321105957],[42.7066593170166,66.68637275695801]]],[[[69.2522144317627,66.78997993469238],[70.05525398254395,66.70332527160645],[70.10443305969238,66.53109931945801],[69.84109687805176,66.47831916809082],[69.41943550109863,66.76971626281738],[69.12664985656738,66.7885913848877],[69.2522144317627,66.78997993469238]]],[[[54.21193885803223,68.24971199035645],[54.28305244445801,68.33665657043457],[54.33693885803223,68.30386543273926],[54.21193885803223,68.24971199035645]]],[[[53.949716567993164,68.29275703430176],[53.86888313293457,68.34610176086426],[54.01333045959473,68.3621997833252],[53.949716567993164,68.29275703430176]]],[[[50.814157485961914,68.3722095489502],[51.16388130187988,68.4952564239502],[51.4566593170166,68.47693061828613],[50.814157485961914,68.3722095489502]]],[[[57.92083168029785,68.80331611633301],[57.86471748352051,68.76193428039551],[57.19999885559082,68.71887397766113],[57.92083168029785,68.80331611633301]]],[[[67.38304328918457,68.7774829864502],[67.14888191223145,68.82193183898926],[67.33859443664551,68.81915473937988],[67.38304328918457,68.7774829864502]]],[[[55.47231483459473,68.90904426574707],[55.224565505981445,68.90986824035645],[55.50842475891113,68.91211128234863],[55.47231483459473,68.90904426574707]]],[[[-179.62612915039062,68.90635871887207],[-175.463623046875,67.70747566223145],[-175.19110107421875,67.51080513000488],[-175.38031005859375,67.3449878692627],[-174.83029174804688,67.38273811340332],[-174.7427978515625,66.77304267883301],[-175.00033569335938,66.67109870910645],[-174.46194458007812,66.30107307434082],[-173.7586669921875,66.44803047180176],[-174.30307006835938,66.57776069641113],[-173.995849609375,66.69134712219238],[-174.12527465820312,66.98913764953613],[-174.65252685546875,67.06360054016113],[-173.66696166992188,67.13165473937988],[-173.17669677734375,67.06331062316895],[-173.35250854492188,66.83886909484863],[-171.72610473632812,66.95524787902832],[-170.64447021484375,66.2371997833252],[-169.69110107421875,66.07249641418457],[-170.58779907226562,65.86360359191895],[-170.63558959960938,65.61053657531738],[-171.544189453125,65.83360481262207],[-171.11557006835938,65.47636604309082],[-172.80029296875,65.6816577911377],[-172.1905517578125,65.44662666320801],[-172.693359375,65.23275947570801],[-172.12612915039062,65.08636665344238],[-173.20086669921875,64.78608894348145],[-172.3558349609375,64.45831489562988],[-173.19140625,64.25442695617676],[-173.413330078125,64.61998176574707],[-173.68167114257812,64.34721565246582],[-175.44888305664062,64.78442573547363],[-176.07806396484375,65.47026252746582],[-178.56307983398438,65.51638984680176],[-178.46054077148438,65.73637580871582],[-178.90945434570312,65.99386787414551],[-178.51699829101562,66.40277290344238],[-179.69558715820312,66.18303108215332],[-179.79837036132812,65.87051582336426],[-179.31500244140625,65.53608894348145],[-180,65.06891059875488],[-180,68.98010444641113],[-179.62612915039062,68.90635871887207]]],[[[54.65416145324707,68.9558277130127],[54.56777381896973,68.9558277130127],[54.69415473937988,68.99136543273926],[54.65416145324707,68.9558277130127]]],[[[66.17192268371582,69.08777046203613],[66.53776741027832,68.94359016418457],[65.95193672180176,69.09387397766113],[66.17192268371582,69.08777046203613]]],[[[59.23943519592285,69.17581367492676],[58.76055335998535,69.33360481262207],[59.19388008117676,69.23387336730957],[59.23943519592285,69.17581367492676]]],[[[34.40471076965332,69.33943367004395],[33.97304725646973,69.36609077453613],[34.2133731842041,69.4027271270752],[34.40471076965332,69.33943367004395]]],[[[67.13109016418457,69.36137580871582],[66.93803596496582,69.44359016418457],[67.21054267883301,69.42581367492676],[67.13109016418457,69.36137580871582]]],[[[50.30526924133301,69.16192817687988],[48.91276741027832,68.7361011505127],[48.21610450744629,68.89499092102051],[48.31276893615723,69.27916145324707],[48.94332313537598,69.50694465637207],[50.30526924133301,69.16192817687988]]],[[[161.44330024719238,68.88998603820801],[161.45800971984863,68.99553108215332],[161.13443183898926,69.08970832824707],[161.09634590148926,69.47053718566895],[161.37774848937988,69.53221321105957],[161.3888874053955,69.45915412902832],[161.28933906555176,69.41586494445801],[161.36136054992676,69.35859870910645],[161.31997871398926,69.24109077453613],[161.38611030578613,69.10247993469238],[161.51526069641113,68.9871997833252],[161.50915718078613,68.9155445098877],[161.44330024719238,68.88998603820801]]],[[[67.25248908996582,69.44470405578613],[67.02110481262207,69.4861011505127],[67.33831977844238,69.5888843536377],[67.25248908996582,69.44470405578613]]],[[[161.43774604797363,69.40803718566895],[161.3949909210205,69.59082221984863],[161.62219429016113,69.58859443664551],[161.43774604797363,69.40803718566895]]],[[[170.1510944366455,69.7341480255127],[169.984956741333,69.74803352355957],[170.20331001281738,69.78831672668457],[170.1510944366455,69.7341480255127]]],[[[169.4474811553955,69.80887031555176],[168.86828804016113,69.5677661895752],[167.7519245147705,69.82748603820801],[169.4474811553955,69.80887031555176]]],[[[83.0969409942627,70.12498664855957],[82.76860237121582,70.2088794708252],[82.86387825012207,70.25166511535645],[83.08276557922363,70.21859931945801],[83.11360359191895,70.19331550598145],[83.0969409942627,70.12498664855957]]],[[[59.46110725402832,70.27665901184082],[60.54610633850098,69.79915046691895],[59.60166358947754,69.71249580383301],[58.40860176086426,70.25027656555176],[59.03305244445801,70.47886848449707],[59.46110725402832,70.27665901184082]]],[[[83.55026435852051,70.46360969543457],[83.61276435852051,70.4377613067627],[83.53360176086426,70.37719917297363],[83.37970161437988,70.36499214172363],[83.4124927520752,70.44026374816895],[83.62442207336426,70.52415657043457],[83.55026435852051,70.46360969543457]]],[[[57.20471382141113,70.50888252258301],[56.965829849243164,70.51748847961426],[56.84166145324707,70.59915351867676],[57.20471382141113,70.50888252258301]]],[[[162.38189888000488,70.67915534973145],[162.484956741333,70.65109443664551],[162.23663520812988,70.65915107727051],[162.38189888000488,70.67915534973145]]],[[[83.3722095489502,70.68609809875488],[83.0697193145752,70.39776802062988],[83.21415901184082,70.80720710754395],[83.3722095489502,70.68609809875488]]],[[[161.69384956359863,70.75027656555176],[161.46328926086426,70.80359077453613],[161.65774726867676,70.80859565734863],[161.69384956359863,70.75027656555176]]],[[[160.6191120147705,70.81469917297363],[160.40802192687988,70.91914558410645],[160.71978950500488,70.81851387023926],[160.6191120147705,70.81469917297363]]],[[[53.59527015686035,71.11026191711426],[53.43249702453613,71.13693428039551],[53.542497634887695,71.18387031555176],[53.59527015686035,71.11026191711426]]],[[[53.360551834106445,71.29220771789551],[53.20416450500488,71.31109809875488],[53.129159927368164,71.35859870910645],[53.360551834106445,71.29220771789551]]],[[[52.85860633850098,71.3783130645752],[53.20749855041504,71.25110054016113],[53.14193916320801,70.97831916809082],[52.20888710021973,71.30554389953613],[52.85860633850098,71.3783130645752]]],[[[-175.620849609375,71.37776374816895],[-175.92361450195312,71.42581367492676],[-175.76419067382812,71.42440986633301],[-175.620849609375,71.37776374816895]]],[[[137.96109199523926,71.50305366516113],[137.67691230773926,71.41165351867676],[136.99133491516113,71.51555061340332],[137.96109199523926,71.50305366516113]]],[[[180.00000190734863,71.53586006164551],[180.00000190734863,70.9972095489502],[178.79101753234863,70.7964038848877],[178.61773872375488,71.0355396270752],[180.00000190734863,71.53586006164551]]],[[[-178.568603515625,71.56414985656738],[-177.439453125,71.22693061828613],[-180,70.9972095489502],[-180,71.53584480285645],[-178.568603515625,71.56414985656738]]],[[[138.5160846710205,71.8560962677002],[138.27386665344238,71.85998725891113],[138.36245918273926,71.88554573059082],[138.5160846710205,71.8560962677002]]],[[[128.1430377960205,72.5788745880127],[129.56109809875488,72.22526741027832],[128.76361274719238,72.07415962219238],[127.54971504211426,72.43332099914551],[126.65027046203613,72.43609809875488],[128.1430377960205,72.5788745880127]]],[[[77.76249885559082,72.29525947570801],[76.85470771789551,72.32998847961426],[77.6202564239502,72.63054084777832],[78.39305305480957,72.4891529083252],[77.76249885559082,72.29525947570801]]],[[[128.83886909484863,72.57666206359863],[128.10052680969238,72.63195991516113],[128.97220039367676,72.59082221984863],[128.83886909484863,72.57666206359863]]],[[[72.99304389953613,72.60247993469238],[72.84054756164551,72.67498970031738],[72.98498725891113,72.67608833312988],[72.99304389953613,72.60247993469238]]],[[[129.355806350708,72.7027759552002],[127.31414985656738,72.65332221984863],[128.30191230773926,72.78776741027832],[129.355806350708,72.7027759552002]]],[[[129.23025703430176,72.83194160461426],[129.29803657531738,72.80026435852051],[128.29052925109863,72.86609077453613],[129.23025703430176,72.83194160461426]]],[[[122.95583534240723,72.86331367492676],[123.60582160949707,72.77777290344238],[122.30246925354004,72.93748664855957],[122.95583534240723,72.86331367492676]]],[[[74.86276435852051,73.08970832824707],[74.6544361114502,72.85582160949707],[74.08970832824707,73.02054023742676],[74.86276435852051,73.08970832824707]]],[[[79.57083320617676,72.73027229309082],[78.57859992980957,72.84553718566895],[79.19470405578613,73.09582710266113],[79.57083320617676,72.73027229309082]]],[[[120.2138843536377,73.04248237609863],[119.62970161437988,73.11470222473145],[120.0869312286377,73.1524829864502],[120.2138843536377,73.04248237609863]]],[[[76.4527759552002,73.19053840637207],[76.73748970031738,73.15359687805176],[76.12275886535645,73.20721626281738],[76.4527759552002,73.19053840637207]]],[[[71.34109687805176,73.32499885559082],[71.13998603820801,73.28970527648926],[71.26277351379395,73.41415596008301],[71.34109687805176,73.32499885559082]]],[[[55.33166694641113,73.32998847961426],[56.58860206604004,73.13749885559082],[55.61527442932129,72.96138191223145],[56.262216567993164,72.96081733703613],[55.4294376373291,72.78415107727051],[55.94554328918457,72.66665840148926],[55.118051528930664,72.44803047180176],[55.57583045959473,72.1958179473877],[55.221017837524414,71.92561531066895],[56.228044509887695,71.19413948059082],[57.63999366760254,70.72638130187988],[55.18631935119629,70.55206489562988],[53.46360969543457,70.81387519836426],[53.74332618713379,70.94304084777832],[53.50833320617676,71.08610725402832],[54.24499702453613,71.12664985656738],[53.453325271606445,71.26111030578613],[53.9294376373291,71.4669361114502],[53.480546951293945,71.29165840148926],[53.3558292388916,71.56721687316895],[51.79722023010254,71.4749927520752],[51.41610145568848,71.73776435852051],[51.57444190979004,72.07083320617676],[52.39721870422363,72.07609748840332],[53.097490310668945,72.59471321105957],[52.74888038635254,72.63304328918457],[53.219438552856445,72.64721870422363],[52.37638282775879,72.72470283508301],[53.38193702697754,72.88109016418457],[53.15332221984863,73.15582466125488],[54.914438247680664,73.42221260070801],[55.33166694641113,73.32998847961426]]],[[[71.04693794250488,73.50000190734863],[71.26500129699707,73.43637275695801],[70.99914741516113,73.28888130187988],[71.6766529083252,73.17692756652832],[69.86638069152832,73.03276252746582],[69.97442817687988,73.40721321105957],[71.04693794250488,73.50000190734863]]],[[[127.29637336730957,73.51721382141113],[129.11828804016113,73.09471321105957],[126.58943367004395,72.53581428527832],[126.52693367004395,72.40054512023926],[126.30246925354004,72.50110054016113],[126.44999885559082,72.7855396270752],[126.3338794708252,72.89721870422363],[126.77192878723145,73.07638740539551],[126.6594181060791,73.41693305969238],[127.29637336730957,73.51721382141113]]],[[[76.3902759552002,73.52083015441895],[76.76609992980957,73.43387031555176],[76.07415962219238,73.5213794708252],[76.3902759552002,73.52083015441895]]],[[[128.05554389953613,73.4830493927002],[127.38804817199707,73.52026557922363],[127.70776557922363,73.5355396270752],[128.05554389953613,73.4830493927002]]],[[[80.36053657531738,73.50027656555176],[80.05664253234863,73.55581855773926],[80.40359687805176,73.54609870910645],[80.36053657531738,73.50027656555176]]],[[[76.0777759552002,73.55803108215332],[75.30632209777832,73.41833686828613],[75.62109565734863,73.54998970031738],[76.0777759552002,73.55803108215332]]],[[[124.60443305969238,73.72859382629395],[125.56025886535645,73.40304756164551],[126.30887031555176,73.54582405090332],[126.15664863586426,73.37442207336426],[126.71499824523926,73.08442878723145],[126.27805519104004,72.87997627258301],[126.38582038879395,72.79275703430176],[126.24443244934082,72.51887702941895],[126.34832954406738,72.37997627258301],[126.12552833557129,72.30053901672363],[124.76500129699707,72.67082405090332],[122.42804145812988,72.98193550109863],[123.65886878967285,73.16804695129395],[123.21914863586426,73.40471076965332],[123.37692451477051,73.6624927520752],[124.60443305969238,73.72859382629395]]],[[[142.15497016906738,73.88998603820801],[143.43191719055176,73.52249336242676],[143.5058307647705,73.23027229309082],[139.65359687805176,73.40220832824707],[142.15497016906738,73.88998603820801]]],[[[124.54525947570801,73.85331916809082],[124.28777503967285,73.88443183898926],[124.65999031066895,73.89804267883301],[124.54525947570801,73.85331916809082]]],[[[86.4871997833252,73.90887641906738],[86.22331428527832,73.96638679504395],[86.30137825012207,73.97720527648926],[86.4871997833252,73.90887641906738]]],[[[84.41914558410645,74.03193855285645],[84.38943672180176,73.95555305480957],[83.87942695617676,74.00665473937988],[84.41914558410645,74.03193855285645]]],[[[82.60971260070801,74.0486011505127],[82.31469917297363,74.11442756652832],[82.73637580871582,74.09887886047363],[82.60971260070801,74.0486011505127]]],[[[83.61581611633301,74.09305000305176],[82.8158130645752,74.09109687805176],[83.2027759552002,74.14972114562988],[83.61581611633301,74.09305000305176]]],[[[85.53442573547363,74.12747383117676],[85.40887641906738,74.18969917297363],[85.73278999328613,74.16862678527832],[85.53442573547363,74.12747383117676]]],[[[135.649995803833,74.20359992980957],[136.27249336242676,73.9358081817627],[135.35357856750488,74.25277900695801],[135.649995803833,74.20359992980957]]],[[[141.02054023742676,73.99275398254395],[140.07275581359863,74.09776496887207],[140.87439155578613,74.27110481262207],[141.02054023742676,73.99275398254395]]],[[[116.06888008117676,74.28692817687988],[115.88582038879395,74.32026863098145],[116.06749153137207,74.36914253234863],[116.06888008117676,74.28692817687988]]],[[[59.033884048461914,74.34276008605957],[58.93499183654785,74.35832405090332],[59.08111000061035,74.40915107727051],[59.033884048461914,74.34276008605957]]],[[[84.94525337219238,74.47776985168457],[84.74443244934082,74.39526557922363],[84.37303352355957,74.44859504699707],[84.94525337219238,74.47776985168457]]],[[[112.71331977844238,74.49887275695801],[113.43332099914551,74.39387702941895],[112.78777503967285,74.0919361114502],[111.45555305480957,74.3166675567627],[112.71331977844238,74.49887275695801]]],[[[85.43942451477051,74.45359992980957],[85.14499092102051,74.54026985168457],[85.65332221984863,74.5294361114502],[85.43942451477051,74.45359992980957]]],[[[86.21249580383301,74.5183277130127],[85.65942573547363,74.47053718566895],[85.82361030578613,74.57026863098145],[86.21249580383301,74.5183277130127]]],[[[79.38611030578613,74.6172046661377],[79.6121997833252,74.5949878692627],[79.14915657043457,74.6030445098877],[79.38611030578613,74.6172046661377]]],[[[85.65555000305176,74.79165840148926],[85.70027351379395,74.72165107727051],[85.09553718566895,74.74775886535645],[85.65555000305176,74.79165840148926]]],[[[87.04971504211426,74.97915840148926],[86.83526802062988,74.82638740539551],[86.21110725402832,74.89860725402832],[87.04971504211426,74.97915840148926]]],[[[82.15193367004395,75.11554145812988],[82.02720832824707,75.1283130645752],[82.10748481750488,75.15832710266113],[82.15193367004395,75.11554145812988]]],[[[82.10582160949707,75.41220283508301],[82.29193305969238,75.33055305480957],[82.01193428039551,75.17221260070801],[81.49304389953613,75.35832405090332],[82.10582160949707,75.41220283508301]]],[[[147.01831245422363,75.33471870422363],[150.95303535461426,75.13943672180176],[148.70440864562988,74.75999641418457],[146.07025337219238,75.22665596008301],[146.41497993469238,75.58610725402832],[147.01831245422363,75.33471870422363]]],[[[140.745943069458,75.65185737609863],[140.51944160461426,75.7058277130127],[140.7699909210205,75.67720222473145],[140.745943069458,75.65185737609863]]],[[[135.65387153625488,75.36499214172363],[135.44412422180176,75.4408130645752],[135.70800971984863,75.8499927520752],[136.17776679992676,75.61914253234863],[135.65387153625488,75.36499214172363]]],[[[59.19249153137207,75.88804817199707],[58.993608474731445,75.89109992980957],[59.278329849243164,75.90832710266113],[59.19249153137207,75.88804817199707]]],[[[81.60026741027832,75.93525886535645],[82.25694465637207,75.86943244934082],[81.55081367492676,75.9236011505127],[81.60026741027832,75.93525886535645]]],[[[82.9730396270752,75.96914863586426],[83.30247688293457,75.94136238098145],[82.2572193145752,75.95860481262207],[82.9730396270752,75.96914863586426]]],[[[58.754716873168945,75.89694404602051],[58.694711685180664,75.8994312286377],[59.26693916320801,75.96943855285645],[58.754716873168945,75.89694404602051]]],[[[96.76693916320801,75.97526741027832],[96.6958179473877,76.01138496398926],[97.33728218078613,76.10208320617676],[96.76693916320801,75.97526741027832]]],[[[140.91079902648926,76.06694221496582],[140.84720039367676,76.09553718566895],[141.07940864562988,76.10942268371582],[140.91079902648926,76.06694221496582]]],[[[60.472490310668945,76.15999031066895],[59.866106033325195,76.10415840148926],[60.04110908508301,76.15693855285645],[60.472490310668945,76.15999031066895]]],[[[139.19079780578613,76.07222175598145],[140.47912788391113,75.63611030578613],[141.06079292297363,75.64526557922363],[140.9718952178955,76.03915596008301],[141.61969184875488,76.01249885559082],[141.35663032531738,76.18054389953613],[145.39471626281738,75.51748847961426],[143.94970893859863,75.02693367004395],[142.90359687805176,75.13388252258301],[142.50604438781738,75.45372200012207],[143.04052925109863,75.66971015930176],[142.4474811553955,75.71110725402832],[142.1552448272705,75.37553596496582],[142.61245918273926,75.09971809387207],[143.70691108703613,74.93858528137207],[139.6469440460205,74.97915840148926],[139.09607124328613,74.64721870422363],[136.86136054992676,75.34915351867676],[137.40497016906738,75.35220527648926],[136.95855903625488,75.60421943664551],[137.74469184875488,75.74832344055176],[137.44998359680176,75.95471382141113],[139.19079780578613,76.07222175598145]]],[[[152.74133491516113,76.10775947570801],[152.45523262023926,76.15693855285645],[152.75665473937988,76.2119312286377],[152.74133491516113,76.10775947570801]]],[[[95.19941902160645,76.15776252746582],[95.00277900695801,76.17248725891113],[95.08450508117676,76.22079658508301],[95.19941902160645,76.15776252746582]]],[[[94.99748420715332,76.26915168762207],[94.84027290344238,76.17943000793457],[94.40803718566895,76.20498847961426],[94.99748420715332,76.26915168762207]]],[[[96.36638069152832,76.30108833312988],[96.6494312286377,76.24887275695801],[95.26361274719238,76.21304512023926],[96.36638069152832,76.30108833312988]]],[[[96.75694465637207,76.3227710723877],[96.66470527648926,76.29248237609863],[96.38304328918457,76.33194160461426],[96.75694465637207,76.3227710723877]]],[[[96.99748420715332,76.27720832824707],[96.71110725402832,76.21360969543457],[96.83442878723145,76.3469409942627],[96.99748420715332,76.27720832824707]]],[[[113.43997383117676,76.36053657531738],[113.11876106262207,76.36999702453613],[113.25888252258301,76.43637275695801],[113.43997383117676,76.36053657531738]]],[[[94.35721015930176,76.57443428039551],[93.86998176574707,76.58499336242676],[93.95181465148926,76.60981941223145],[94.35721015930176,76.57443428039551]]],[[[112.52192878723145,76.62248420715332],[112.7138843536377,76.51054573059082],[111.95665168762207,76.59860420227051],[112.52192878723145,76.62248420715332]]],[[[95.59887886047363,76.66998481750488],[95.41276741027832,76.69970893859863],[95.83194160461426,76.68553352355957],[95.59887886047363,76.66998481750488]]],[[[95.13304328918457,76.7027759552002],[95.32693672180176,76.66110420227051],[94.81303596496582,76.64888191223145],[95.13304328918457,76.7027759552002]]],[[[96.46408271789551,76.70601081848145],[96.2422046661377,76.60971260070801],[95.88916206359863,76.62137031555176],[96.46408271789551,76.70601081848145]]],[[[97.54637336730957,76.58221626281738],[97.31637763977051,76.60664558410645],[97.44053840637207,76.71499824523926],[97.54637336730957,76.58221626281738]]],[[[149.3144245147705,76.75360298156738],[149.16885566711426,76.65054512023926],[148.39221382141113,76.64360237121582],[149.3144245147705,76.75360298156738]]],[[[97.86998176574707,76.77026557922363],[97.72943305969238,76.81833076477051],[97.91943550109863,76.83831977844238],[97.86998176574707,76.77026557922363]]],[[[68.26609992980957,76.95860481262207],[68.93136787414551,76.78276252746582],[68.8611011505127,76.54193305969238],[61.28777503967285,75.32609748840332],[59.925554275512695,74.99914741516113],[60.68027687072754,74.93332099914551],[60.31860542297363,74.76054573059082],[59.50999641418457,74.79498481750488],[59.773324966430664,74.59109687805176],[59.169443130493164,74.71971321105957],[59.14721870422363,74.43858528137207],[58.18335151672363,74.57353401184082],[58.74276924133301,74.26693916320801],[58.13582801818848,73.98526191711426],[57.25750160217285,74.07609748840332],[57.91166114807129,73.9155445098877],[57.71527290344238,73.71304512023926],[56.55582618713379,73.88220405578613],[57.61361122131348,73.66220283508301],[56.72304725646973,73.6736011505127],[57.25332832336426,73.48776435852051],[56.75889015197754,73.24693489074707],[55.90777015686035,73.44026374816895],[55.977487564086914,73.31749153137207],[54.97165870666504,73.44220161437988],[54.22054481506348,73.32304573059082],[55.176103591918945,73.70610237121582],[53.63054847717285,73.7552661895752],[55.86638832092285,74.10247993469238],[55.07332801818848,74.26443672180176],[56.29055213928223,74.49136543273926],[55.571664810180664,74.65971565246582],[56.98458290100098,74.6871509552002],[55.829721450805664,74.79609870910645],[56.678606033325195,74.95221138000488],[55.79777717590332,75.1463794708252],[57.73721504211426,75.32304573059082],[57.50332832336426,75.49247932434082],[58.194711685180664,75.58831977844238],[58.00139045715332,75.67415046691895],[60.75000190734863,76.00610542297363],[61.06638526916504,76.27388191223145],[64.10971260070801,76.31137275695801],[68.26609992980957,76.95860481262207]]],[[[88.66470527648926,77.09637641906738],[88.95721626281738,77.12581062316895],[88.78305244445801,77.00499153137207],[88.66470527648926,77.09637641906738]]],[[[96.57554817199707,77.1302661895752],[96.16609382629395,76.9891529083252],[95.22915840148926,76.99331855773926],[96.57554817199707,77.1302661895752]]],[[[156.61773872375488,77.10386848449707],[156.43414497375488,77.1352710723877],[156.73217964172363,77.12581062316895],[156.61773872375488,77.10386848449707]]],[[[90.18026924133301,77.11581611633301],[89.96721076965332,77.11303901672363],[89.82971382141113,77.14082527160645],[90.18026924133301,77.11581611633301]]],[[[105.88472175598145,77.26138496398926],[105.78055000305176,77.27415657043457],[106.00776863098145,77.2824878692627],[105.88472175598145,77.26138496398926]]],[[[89.6816577911377,77.28442573547363],[89.48526191711426,77.17997932434082],[89.13582038879395,77.20498847961426],[89.6816577911377,77.28442573547363]]],[[[106.4024829864502,77.30359077453613],[106.33167457580566,77.31805610656738],[106.45833015441895,77.31526374816895],[106.4024829864502,77.30359077453613]]],[[[107.56192207336426,77.25499153137207],[107.20027351379395,77.23387336730957],[107.66665840148926,77.3308277130127],[107.56192207336426,77.25499153137207]]],[[[106.64665412902832,77.37608528137207],[106.50417518615723,77.38998603820801],[106.90081977844238,77.45915412902832],[106.64665412902832,77.37608528137207]]],[[[82.56025886535645,77.4619312286377],[82.1202564239502,77.50638008117676],[82.4438648223877,77.5102710723877],[82.56025886535645,77.4619312286377]]],[[[91.96638679504395,77.5999927520752],[91.73970222473145,77.64721870422363],[92.03776741027832,77.63081550598145],[91.96638679504395,77.5999927520752]]],[[[104.26748847961426,77.67581367492676],[106.29193305969238,77.36276435852051],[104.1172046661377,77.09082221984863],[107.50360298156738,76.92221260070801],[106.40109443664551,76.50972175598145],[111.10386848449707,76.7552661895752],[112.74275398254395,76.32832527160645],[112.56667518615723,76.0405445098877],[113.24275398254395,76.26220893859863],[113.89248847961426,75.8499927520752],[113.50943183898926,75.5324878692627],[112.33719825744629,75.84665107727051],[113.71748542785645,75.40860176086426],[108.18969917297363,73.67025947570801],[107.14248847961426,73.61470222473145],[105.2119312286377,72.76471138000488],[106.3338794708252,73.18719673156738],[110.9143238067627,73.69668769836426],[109.52916145324707,73.77026557922363],[110.20041084289551,74.02444648742676],[111.54332160949707,74.04498481750488],[111.20139503479004,73.96748542785645],[112.24832344055176,73.70694160461426],[112.88777351379395,73.96499824523926],[113.49942207336426,73.33415412902832],[113.48636817932129,72.95833015441895],[113.10443305969238,72.85359382629395],[113.17859077453613,72.72360420227051],[114.04471015930176,72.59721565246582],[113.15109443664551,72.83943367004395],[113.53082466125488,72.96026802062988],[113.54694557189941,73.2422046661377],[114.03386878967285,73.3419361114502],[113.47527503967285,73.5041675567627],[118.63443183898926,73.57165718078613],[118.99387550354004,73.4891529083252],[118.39221382141113,73.23581123352051],[119.81775856018066,72.9358081817627],[121.86580848693848,72.96805000305176],[124.72971534729004,72.62637519836426],[126.11775398254395,72.26693916320801],[126.37248420715332,72.35331916809082],[127.1294116973877,71.8510913848877],[127.22054481506348,71.39248847961426],[127.32608222961426,71.89804267883301],[126.71914863586426,72.38888740539551],[127.65860176086426,72.34749031066895],[128.7116413116455,71.77054023742676],[129.17993354797363,71.80026435852051],[129.0724811553955,72.00193977355957],[129.53994941711426,71.72221565246582],[128.84744453430176,71.60138130187988],[131.13025093078613,70.7310962677002],[132.18469429016113,71.21470832824707],[131.946626663208,71.28915596008301],[132.72802925109863,71.94192695617676],[133.67914009094238,71.43332099914551],[135.8649616241455,71.63971138000488],[137.85412788391113,71.11137580871582],[138.22134590148926,71.26220893859863],[137.82412910461426,71.38388252258301],[138.06607246398926,71.57361030578613],[139.932466506958,71.48498725891113],[139.3366413116455,71.94552803039551],[140.19830513000488,72.20332527160645],[139.08523750305176,72.23332405090332],[141.0241413116455,72.58581733703613],[140.74884223937988,72.88943672180176],[146.84802436828613,72.34749031066895],[144.13858222961426,72.27083015441895],[144.391939163208,72.17192268371582],[145.08636665344238,72.25915718078613],[146.930269241333,72.30941963195801],[145.96466255187988,71.8469409942627],[145.98855781555176,72.02554512023926],[146.33996772766113,72.12803840637207],[145.98550605773926,72.06137275695801],[145.89831733703613,72.20610237121582],[145.7116413116455,72.2522144317627],[145.60830879211426,72.24359321594238],[145.749116897583,72.20721626281738],[145.6149616241455,72.08055305480957],[145.80240058898926,71.92553901672363],[144.95691108703613,71.95833015441895],[145.21634101867676,71.82721138000488],[144.9133014678955,71.6958179473877],[145.31884956359863,71.65803718566895],[146.08828926086426,71.79387092590332],[147.13971138000488,72.31721687316895],[149.18524360656738,72.22249031066895],[150.07525825500488,71.88388252258301],[148.823579788208,71.66998481750488],[150.66775703430176,71.48942756652832],[150.02359199523926,71.20749092102051],[151.45331001281738,71.34332466125488],[152.1410846710205,70.99748420715332],[151.66360664367676,70.98082160949707],[152.5383014678955,70.83777046203613],[155.93719673156738,71.09443855285645],[159.05386543273926,70.86914253234863],[160.03802680969238,70.40555000305176],[159.72967720031738,69.83471870422363],[160.99524116516113,69.58831977844238],[160.96386909484863,69.10359382629395],[161.41165351867676,68.97970771789551],[161.06607246398926,68.56331062316895],[160.84607124328613,68.52276802062988],[161.12774848937988,68.55525398254395],[161.319429397583,68.79248237609863],[161.579683303833,68.91499519348145],[161.44607734680176,69.38554573059082],[164.01443672180176,69.76748847961426],[166.86050605773926,69.49054145812988],[167.78692817687988,69.77609443664551],[168.28332710266113,69.24165534973145],[170.61194038391113,68.75633430480957],[171.03192329406738,69.04220771789551],[170.60913276672363,69.58027839660645],[170.12384223937988,69.60998725891113],[170.56720161437988,69.77804756164551],[170.4718952178955,70.13415718078613],[173.19192695617676,69.77971076965332],[176.111909866333,69.89055061340332],[180.00000190734863,68.98010444641113],[180.00000190734863,65.06891059875488],[178.52221870422363,64.58804512023926],[178.75555610656738,64.68220710754395],[177.60940742492676,64.71805000305176],[176.89972114562988,65.08360481262207],[176.30276679992676,65.04998970031738],[177.303316116333,64.8277759552002],[174.43664741516113,64.68831062316895],[177.48608589172363,64.76138496398926],[177.63189888000488,64.31888008117676],[178.36746406555176,64.27388191223145],[178.75747871398926,63.63999366760254],[178.26165962219238,63.5624942779541],[178.68802070617676,63.3830509185791],[178.77221870422363,63.59499549865723],[179.40860176086426,63.142770767211914],[179.23663520812988,62.994157791137695],[179.56109809875488,62.62137794494629],[179.061372756958,62.28472328186035],[176.97552680969238,62.865549087524414],[177.26553535461426,62.574716567993164],[172.710786819458,61.42999458312988],[172.95608711242676,61.30277442932129],[170.641939163208,60.417497634887695],[170.24884223937988,59.909433364868164],[169.21023750305176,60.62276649475098],[167.0502643585205,60.32388496398926],[166.13775825500488,59.81527137756348],[166.34857368469238,60.48638343811035],[164.99719429016113,60.12943458557129],[165.182466506958,59.98110389709473],[164.83218574523926,59.78110694885254],[164.46856880187988,60.11138343811035],[164.15555000305176,59.8527774810791],[163.63553047180176,60.045549392700195],[163.17303657531738,59.559160232543945],[163.1935749053955,59.053606033325195],[162.87634468078613,59.1280460357666],[163.044771194458,59.01031684875488],[161.93887519836426,58.07444190979004],[162.34607124328613,57.68471717834473],[162.57107734680176,57.95110511779785],[163.2135944366455,57.83610725402832],[162.736909866333,57.35777473449707],[162.791353225708,56.79110908508301],[163.21386909484863,56.740549087524414],[163.35467720031738,56.1986026763916],[162.64526557922363,56.19193458557129],[163.08914375305176,56.53416633605957],[162.39358711242676,56.39999580383301],[162.57220649719238,56.26721382141113],[162.03692817687988,56.061662673950195],[161.71246528625488,55.4969425201416],[162.11218452453613,54.76194190979004],[160.0058307647705,54.13916206359863],[159.79165840148926,53.514719009399414],[160.05523872375488,53.09360694885254],[158.43054389953613,53.02193641662598],[158.64471626281738,52.89471626281738],[158.27581977844238,51.936655044555664],[156.668306350708,50.881662368774414],[155.54413032531738,55.303606033325195],[155.94885444641113,56.66610145568848],[156.9777545928955,57.414438247680664],[156.74884223937988,57.72832679748535],[158.23330879211426,58.01944160461426],[161.91443061828613,60.42276954650879],[163.65832710266113,60.87193489074707],[164.12774848937988,62.28277015686035],[165.64248847961426,62.452775955200195],[164.35940742492676,62.71221351623535],[163.26361274719238,62.545000076293945],[162.95025825500488,61.80638313293457],[163.28802680969238,61.664438247680664],[162.40332221984863,61.672494888305664],[160.13775825500488,60.58360481262207],[160.39135932922363,61.025827407836914],[159.78055000305176,60.94082832336426],[159.82718086242676,61.26138496398926],[160.3549518585205,61.94748878479004],[159.531099319458,61.66276741027832],[159.24746894836426,61.92222023010254],[157.48663520812988,61.80332374572754],[154.23272895812988,59.88193702697754],[154.11413764953613,59.45971870422363],[155.190523147583,59.357805252075195],[154.74164009094238,59.12693977355957],[153.36856269836426,59.243051528930664],[152.8771686553955,58.917497634887695],[151.309419631958,58.83693885803223],[151.073579788208,59.110551834106445],[152.28775215148926,59.226938247680664],[149.59857368469238,59.771379470825195],[148.743013381958,59.49166297912598],[148.898042678833,59.23916053771973],[143.926362991333,59.4133243560791],[142.15970039367676,59.069162368774414],[140.688570022583,58.2338809967041],[140.49633979797363,57.82332801818848],[135.15442085266113,54.85943794250488],[135.73663520812988,54.5705509185791],[136.81607246398926,54.651384353637695],[136.76080513000488,53.76860237121582],[137.17248725891113,53.83471870422363],[137.28912544250488,54.03360939025879],[137.06189155578613,54.14083290100098],[137.18716621398926,54.2147159576416],[137.738862991333,54.317216873168945],[137.30798530578613,54.11444282531738],[137.85913276672363,53.961381912231445],[137.31079292297363,53.53277015686035],[138.55386543273926,53.98943519592285],[138.23941230773926,53.5624942779541],[138.44412422180176,53.51055335998535],[138.641939163208,54.29527473449707],[139.74633979797363,54.30888557434082],[141.41913032531738,53.2902774810791],[141.19998359680176,52.98638343811035],[140.7055377960205,53.113054275512695],[141.51416206359863,52.213327407836914],[140.46051216125488,50.7066593170166],[140.69580268859863,50.08749580383301],[140.40747261047363,49.871660232543945],[140.17581367492676,48.4486026763916],[135.12967109680176,43.49888038635254],[133.15136909484863,42.68221473693848],[132.3105182647705,42.844438552856445],[132.35217475891113,43.29277229309082],[131.94302558898926,43.06388282775879],[132.0563678741455,43.31332588195801],[131.8105182647705,43.3255558013916],[131.22134590148926,42.55582618713379],[130.69998359680176,42.67916297912598],[130.69742012023926,42.29220771789551],[130.6388874053955,42.406938552856445],[130.60437202453613,42.42186164855957],[130.4052448272705,42.71805000305176],[131.12329292297363,42.91082191467285],[131.311372756958,43.392221450805664],[130.94998359680176,44.84110450744629],[131.86468696594238,45.34554481506348],[133.12219429016113,45.12860298156738],[133.90017890930176,46.250314712524414],[134.182466506958,47.32332801818848],[134.76721382141113,47.70749855041504],[134.74075508117676,48.26712989807129],[133.08856391906738,48.10166358947754],[132.521089553833,47.710275650024414],[130.98855781555176,47.68860054016113],[130.52163887023926,48.60777473449707],[130.67163276672363,48.864999771118164],[127.52942848205566,49.78916358947754],[127.58606910705566,50.208566665649414],[126.09554481506348,52.76444435119629],[123.38220405578613,53.52665901184082],[120.86387825012207,53.27971839904785],[120.02916145324707,52.76805305480957],[120.71360969543457,52.54471778869629],[120.77665901184082,52.114999771118164],[119.13860511779785,50.39471626281738],[119.36136817932129,50.33693885803223],[119.21415901184082,50.015275955200195],[117.87471199035645,49.520578384399414],[116.71138191223145,49.83046913146973],[114.31302833557129,50.28416633605957],[113.09082221984863,49.59860420227051],[110.7885913848877,49.14943885803223],[108.57222175598145,49.33360481262207],[107.94914436340332,49.678049087524414],[107.97712898254395,49.94362831115723],[106.66304206848145,50.33860206604004],[102.91858863830566,50.31527137756348],[102.32776832580566,50.569719314575195],[102.21887397766113,51.33360481262207],[98.93026924133301,52.14361000061035],[97.8277759552002,51.001108169555664],[98.28970527648926,50.29388618469238],[97.34082221984863,49.73443794250488],[94.6352710723877,50.02443885803223],[94.27499580383301,50.56944465637207],[92.3227710723877,50.81499671936035],[87.84070014953613,49.17295265197754],[87.34820747375488,49.09262275695801],[86.61665534973145,49.58721351623535],[86.77499580383301,49.788888931274414],[86.19108772277832,49.472490310668945],[85.25860786437988,49.591379165649414],[85.01443672180176,50.07583045959473],[84.36303901672363,50.21221351623535],[83.45637702941895,51.00249671936035],[81.46805000305176,50.74221992492676],[80.68783760070801,51.31472206115723],[80.07795906066895,50.75808906555176],[77.90803718566895,53.27110481262207],[76.52165412902832,53.99388313293457],[76.81164741516113,54.447771072387695],[74.42915534973145,53.47860145568848],[73.43719673156738,53.436105728149414],[73.23858833312988,53.64444160461426],[73.76388740539551,54.0655460357666],[72.61331367492676,54.145273208618164],[72.46859931945801,53.908884048461914],[72.0516529083252,54.387773513793945],[72.19609260559082,54.13749885559082],[71.18553352355957,54.10332679748535],[70.99693489074707,54.33915901184082],[71.27887153625488,54.69027137756348],[70.84332466125488,55.30193519592285],[69.18553352355957,55.343881607055664],[65.48332405090332,54.63804817199707],[65.21638679504395,54.31888771057129],[63.17222023010254,54.18638038635254],[62.547494888305664,53.87943458557129],[61.01416206359863,53.94748878479004],[61.226938247680664,53.81193733215332],[60.90555000305176,53.62027168273926],[61.57749366760254,53.51333045959473],[61.18471717834473,53.306657791137695],[62.11832618713379,53.004167556762695],[61.09916114807129,52.98166084289551],[60.69415473937988,52.68082618713379],[61.06193733215332,52.34249305725098],[60.00222206115723,51.958330154418945],[61.68582344055176,51.26583290100098],[61.38138008117676,50.78360939025879],[60.04361152648926,50.86332893371582],[59.542497634887695,50.47832679748535],[58.33777046203613,51.15609931945801],[57.48193550109863,50.86471748352051],[56.51082801818848,51.083330154418945],[55.69249153137207,50.53249549865723],[54.64721870422363,51.036943435668945],[54.523935317993164,50.52884101867676],[54.50638771057129,50.856943130493164],[53.428606033325195,51.49166297912598],[52.60332679748535,51.45694160461426],[52.338327407836914,51.78221321105957],[51.303049087524414,51.47971534729004],[50.77330207824707,51.769182205200195],[48.69748878479004,50.591936111450195],[48.796945571899414,49.94193458557129],[48.251665115356445,49.86971473693848],[47.520830154418945,50.43638038635254],[46.9294376373291,49.86361122131348],[46.79583168029785,49.3397159576416],[47.06276893615723,49.142770767211914],[46.499162673950195,48.417497634887695],[47.12276649475098,48.27166175842285],[47.38332557678223,47.68888282775879],[48.20443153381348,47.70498847961426],[49.02720832824707,46.77609443664551],[48.56054878234863,46.56499671936035],[49.2225284576416,46.3463077545166],[48.627763748168945,46.08276557922363],[48.713327407836914,45.830270767211914],[48.56582069396973,45.965829849243164],[47.83054542541504,45.65582466125488],[47.55221748352051,45.76944160461426],[47.637216567993164,45.55304145812988],[47.38027381896973,45.74471473693848],[47.56915473937988,45.5574893951416],[46.67971229553223,44.52304267883301],[47.35026741027832,44.02665138244629],[47.40720558166504,43.50110054016113],[47.698320388793945,43.86887550354004],[47.46221351623535,43.01915168762207],[48.58395576477051,41.835771560668945],[47.76693153381348,41.19609260559082],[46.57138252258301,41.87193489074707],[46.45175361633301,41.89705848693848],[44.934709548950195,42.76027870178223],[43.911935806274414,42.583322525024414],[42.849992752075195,43.179155349731445],[40.25338935852051,43.58252143859863],[40.00296974182129,43.3792667388916],[38.76027870178223,44.27026557922363],[36.575273513793945,45.184709548950195],[36.96054267883301,45.27499580383301],[36.830827713012695,45.43664741516113],[37.73720741271973,45.29916572570801],[37.59137153625488,45.62748146057129],[37.940263748168945,46.025827407836914],[38.57443428039551,46.08970832824707],[37.734994888305664,46.66916084289551],[38.5816593170166,46.650827407836914],[38.41081428527832,46.82805061340332],[39.29998970031738,47.07693672180176],[38.23582649230957,47.10943031311035],[38.30332374572754,47.55859565734863],[38.85360145568848,47.86082649230957],[39.79638862609863,47.85721778869629],[39.99888038635254,48.29722023010254],[39.656938552856445,48.61666297912598],[40.07666206359863,48.8749942779541],[39.69665718078613,49.01082801818848],[40.166940689086914,49.248605728149414],[40.1397647857666,49.60105323791504],[38.30777168273926,50.07388496398926],[38.02422523498535,49.903085708618164],[37.45860481262207,50.439714431762695],[35.60665321350098,50.36944007873535],[35.37188911437988,51.04143714904785],[34.382211685180664,51.26361274719238],[34.09804725646973,51.653879165649414],[34.41971778869629,51.80888557434082],[33.838884353637695,52.360551834106445],[33.41770362854004,52.35540199279785],[31.78388786315918,52.108049392700195],[31.266942977905273,53.02471351623535],[32.741106033325195,53.46305274963379],[31.76422691345215,53.802621841430664],[31.84416389465332,54.06443977355957],[30.781389236450195,54.79361152648926],[31.029722213745117,55.0433292388916],[30.92624855041504,55.60257148742676],[28.168012619018555,56.150156021118164],[27.701662063598633,56.91471290588379],[27.861108779907227,57.30221748352051],[27.372060775756836,57.5356388092041],[27.82305335998535,57.87388038635254],[27.42610740661621,58.813608169555664],[28.170358657836914,59.30978202819824],[28.015832901000977,59.47860145568848],[28.080278396606445,59.79638862609863],[30.24582862854004,59.97526741027832],[28.60194206237793,60.38443946838379],[28.686662673950195,60.73582649230957],[27.807832717895508,60.546403884887695],[31.588930130004883,62.91441535949707],[29.99333381652832,63.743608474731445],[30.578054428100586,64.22137641906738],[29.636667251586914,64.92805671691895],[29.81888771057129,65.65332221984863],[30.134164810180664,65.71916389465332],[29.07499885559082,66.89583015441895],[30.02861213684082,67.6947193145752],[28.693334579467773,68.19749641418457],[28.45749855041504,68.53193855285645],[28.820554733276367,68.84443855285645],[28.431943893432617,68.89694404602051],[28.95734214782715,69.05162239074707],[30.103334426879883,69.66305732727051],[30.910001754760742,69.54887580871582],[30.854841232299805,69.79231452941895],[33.09360694885254,69.74748420715332],[32.02639579772949,69.63653755187988],[33.02941703796387,69.47186470031738],[32.80999183654785,69.29609870910645],[33.52166175842285,69.42192268371582],[33.02276802062988,68.95332527160645],[33.71915626525879,69.33137702941895],[35.974992752075195,69.17303657531738],[40.99221992492676,67.71609687805176],[41.39055061340332,67.12275886535645],[41.21971321105957,66.83777046203613],[40.07332801818848,66.27777290344238],[38.60777473449707,66.05220222473145],[31.854997634887695,67.15387153625488],[33.732492446899414,66.42387580871582],[33.31276893615723,66.31608772277832],[34.847490310668945,65.90109443664551],[34.96360969543457,65.71776008605957],[34.69082832336426,65.80386543273926],[34.68166542053223,65.45109748840332],[34.37777137756348,65.3783130645752],[34.936105728149414,64.83831977844238],[34.78777503967285,64.54776191711426],[37.414995193481445,63.80388069152832],[38.07749366760254,64.01721382141113],[37.9788761138916,64.3166675567627],[37.14471626281738,64.40887641906738],[36.439714431762695,64.94275093078613],[37.03221321105957,65.20833015441895],[38.40860176086426,64.85887336730957],[38.046945571899414,64.64109992980957],[40.50583076477051,64.53526496887207],[39.75139045715332,65.55081367492676],[42.1683292388916,66.52276802062988],[43.29972267150879,66.42221260070801],[43.69748878479004,66.23581123352051],[43.35471534729004,66.0385913848877],[43.858049392700195,66.17692756652832],[44.17444038391113,65.87469673156738],[44.49638557434082,66.9074878692627],[43.75193977355957,67.31888008117676],[44.24582862854004,68.27026557922363],[43.311662673950195,68.68498420715332],[45.90332221984863,68.48221015930176],[46.520830154418945,68.14415168762207],[46.70694160461426,67.81303596496582],[45.38249397277832,67.73553657531738],[44.911935806274414,67.37275886535645],[46.60083198547363,66.85331916809082],[46.38555335998535,66.73970222473145],[47.699716567993164,66.98637580871582],[47.99499702453613,67.65027046203613],[49.10110664367676,67.62803840637207],[48.59110450744629,67.93498420715332],[52.074716567993164,68.54443550109863],[52.26860237121582,68.30581855773926],[52.733049392700195,68.46638679504395],[52.28833198547363,68.6141529083252],[53.78360939025879,68.96805000305176],[54.56082344055176,68.99247932434082],[53.59887886047363,68.90803718566895],[54.0191593170166,68.85525703430176],[53.71971321105957,68.65193367004395],[53.94582557678223,68.39999580383301],[53.20999336242676,68.26138496398926],[54.791940689086914,68.16304206848145],[55.32473182678223,68.55000495910645],[57.27610206604004,68.55581855773926],[58.898332595825195,68.99971199035645],[59.42721748352051,68.7452564239502],[59.07332801818848,68.42137336730957],[59.83610725402832,68.36665534973145],[59.811662673950195,68.68193244934082],[60.914438247680664,68.90471076965332],[60.14055061340332,69.57415962219238],[60.87443733215332,69.86360359191895],[64.15054512023926,69.54193305969238],[65.00277900695801,69.29803657531738],[64.78776741027832,69.14276313781738],[67.11609077453613,68.84276008605957],[67.03915596008301,68.78970527648926],[67.19304084777832,68.70471382141113],[68.15942573547363,68.41137886047363],[68.26500129699707,68.18748664855957],[68.43637275695801,68.2249927520752],[69.22026252746582,68.95721626281738],[68.45971870422363,68.9780445098877],[68.10165596008301,69.5466480255127],[67.00055122375488,69.69970893859863],[66.95027351379395,69.52887153625488],[66.79915046691895,69.57415962219238],[66.8733081817627,70.00110054016113],[67.3277759552002,70.09749031066895],[67.08804512023926,70.21721076965332],[67.33970832824707,70.75027656555176],[66.68887519836426,70.76054573059082],[66.89166450500488,71.07748603820801],[66.62303352355957,71.0516529083252],[68.46554756164551,71.81889533996582],[69.3338794708252,72.9488697052002],[71.56053352355957,72.90971565246582],[72.83333015441895,72.70860481262207],[72.88192939758301,72.28137397766113],[71.80247688293457,71.47249031066895],[72.84054756164551,70.86526679992676],[72.77804756164551,70.41804695129395],[72.4246997833252,70.27026557922363],[72.68637275695801,69.84971809387207],[72.55386543273926,68.97665596008301],[73.64804267883301,68.45776557922363],[73.0980396270752,68.2169361114502],[73.04081916809082,67.72415351867676],[72.0405445098877,67.29693794250488],[72.2310962677002,67.1605396270752],[71.41026496887207,66.9669361114502],[71.55859565734863,66.64526557922363],[70.69497871398926,66.50804328918457],[70.29136848449707,66.62387275695801],[70.73082160949707,66.7572193145752],[68.96776008605957,66.80415534973145],[69.38611030578613,66.50749397277832],[72.00000190734863,66.21943855285645],[73.84721565246582,66.9810962677002],[73.90887641906738,67.29803657531738],[74.73997688293457,67.69165229797363],[74.73166084289551,68.14305305480957],[74.33276557922363,68.3802661895752],[74.64055061340332,68.76915168762207],[76.59166145324707,68.96832466125488],[77.32443428039551,68.51693916320801],[77.0919361114502,67.77859687805176],[79.04484748840332,67.5671558380127],[77.46249580383301,67.76220893859863],[77.55859565734863,68.14387702941895],[78.1746997833252,68.26500129699707],[77.63499641418457,68.90776252746582],[76.03720283508301,69.2371997833252],[73.74942207336426,69.16804695129395],[73.89444160461426,69.42581367492676],[73.51638984680176,69.75555610656738],[74.31498908996582,70.6736011505127],[73.0152759552002,71.4216480255127],[73.53219795227051,71.81915473937988],[74.95804023742676,72.10942268371582],[74.82998847961426,72.83415412902832],[75.71582221984863,72.55664253234863],[75.24193000793457,71.37608528137207],[76.91581916809082,71.0697193145752],[79.11276435852051,71.00248908996582],[76.27054023742676,71.57165718078613],[76.09749031066895,71.92859077453613],[78.10473823547363,71.87614631652832],[77.36998176574707,72.09887886047363],[78.53804206848145,72.40359687805176],[81.65304756164551,71.70804023742676],[83.26164436340332,71.7210865020752],[82.25749397277832,71.25972175598145],[82.41443061828613,70.77110481262207],[82.08110237121582,70.5677661895752],[82.34610176086426,70.19859504699707],[82.16026496887207,70.57748603820801],[83.11886787414551,70.88749885559082],[82.63916206359863,70.17442512512207],[83.10693550109863,70.06860542297363],[83.19359016418457,70.1233081817627],[83.13054084777832,70.20804023742676],[82.95166206359863,70.32054328918457],[83.53166389465332,70.33915901184082],[83.74553108215332,70.45999336242676],[83.1483325958252,71.2361011505127],[83.62858772277832,71.62387275695801],[82.19247627258301,72.28305244445801],[80.72137641906738,72.52609443664551],[80.81721687316895,72.96609687805176],[80.2310962677002,73.1736011505127],[80.57249641418457,73.22053718566895],[80.24859809875488,73.31414985656738],[80.50999641418457,73.57165718078613],[87.0869312286377,73.85942268371582],[85.77832221984863,73.45971870422363],[86.78360176086426,72.99408149719238],[85.8480396270752,73.47526741027832],[87.66499519348145,73.89471626281738],[85.95109748840332,74.28082466125488],[87.13275337219238,74.36914253234863],[85.78915596008301,74.63081550598145],[86.02916145324707,74.81303596496582],[86.91304206848145,74.61248970031738],[87.38665962219238,74.94304084777832],[87.1816577911377,74.98997688293457],[87.78581428527832,75.02221870422363],[86.99498176574707,75.1513843536377],[94.16192817687988,75.94275093078613],[92.86526679992676,75.94832038879395],[93.15555000305176,76.09776496887207],[96.19775581359863,76.08526802062988],[95.74386787414551,75.85054206848145],[99.27693367004395,76.21415901184082],[99.7683277130127,76.03109931945801],[99.09443855285645,75.55497932434082],[100.18625831604004,75.16853523254395],[99.17192268371582,75.56999397277832],[99.87719917297363,76.09166145324707],[98.81387519836426,76.49275398254395],[102.23359870910645,76.37719917297363],[100.8783130645752,76.55137825012207],[101.23471260070801,76.75305366516113],[100.84971809387207,76.87858772277832],[103.10555458068848,77.63192939758301],[104.26748847961426,77.67581367492676]],[[86.90220832824707,73.69748115539551],[86.39499092102051,73.58831977844238],[86.73665046691895,73.59526252746582],[86.90220832824707,73.69748115539551]],[[40.27443885803223,64.87414741516113],[40.278879165649414,64.9458179473877],[40.20971870422363,64.99247932434082],[40.27443885803223,64.87414741516113]]],[[[107.6352710723877,78.16609382629395],[107.43887519836426,78.04942512512207],[106.49304389953613,78.12164497375488],[107.6352710723877,78.16609382629395]]],[[[93.75055122375488,78.15582466125488],[93.51971626281738,78.1877613067627],[93.6402759552002,78.22276496887207],[93.75055122375488,78.15582466125488]]],[[[106.76138496398926,78.30359077453613],[105.99275398254395,78.21415901184082],[106.45860481262207,78.33471870422363],[106.76138496398926,78.30359077453613]]],[[[92.70221138000488,79.07138252258301],[92.18261909484863,79.12718391418457],[92.72554206848145,79.07499885559082],[92.70221138000488,79.07138252258301]]],[[[102.97276496887207,79.33137702941895],[102.39333534240723,78.82859992980957],[103.94693183898926,79.13333320617676],[105.41443061828613,78.56469917297363],[99.34137153625488,78.01999092102051],[100.3783130645752,78.7452564239502],[101.16805458068848,78.75833320617676],[100.89388465881348,78.97665596008301],[101.62442207336426,78.98221015930176],[100.98887825012207,79.06109809875488],[101.55081367492676,79.34832954406738],[102.97276496887207,79.33137702941895]]],[[[92.80554389953613,79.38247871398926],[92.58221626281738,79.40693855285645],[92.98776435852051,79.41693305969238],[92.80554389953613,79.38247871398926]]],[[[92.46748542785645,79.42997932434082],[92.24359321594238,79.37997627258301],[91.80415534973145,79.4124927520752],[92.46748542785645,79.42997932434082]]],[[[99.9458179473877,79.4013843536377],[99.85054206848145,79.4155445098877],[100.01776313781738,79.43304634094238],[99.9458179473877,79.4013843536377]]],[[[91.46859931945801,79.45471382141113],[90.78193855285645,79.54915046691895],[91.16609382629395,79.52693367004395],[91.46859931945801,79.45471382141113]]],[[[76.23248481750488,79.60138130187988],[76.04193305969238,79.63472175598145],[77.61970710754395,79.51220893859863],[76.23248481750488,79.60138130187988]]],[[[100.01082038879395,79.6222095489502],[100.30664253234863,79.66470527648926],[99.90359687805176,79.5999927520752],[100.01082038879395,79.6222095489502]]],[[[91.65109443664551,79.65109443664551],[91.12442207336426,79.72249031066895],[91.85887336730957,79.66470527648926],[91.65109443664551,79.65109443664551]]],[[[58.68638038635254,79.94470405578613],[58.988046646118164,79.89554023742676],[58.27916145324707,79.9266529083252],[58.68638038635254,79.94470405578613]]],[[[94.3077564239502,80.01693916320801],[93.92747688293457,79.96832466125488],[93.98825263977051,80.0097827911377],[94.3077564239502,80.01693916320801]]],[[[49.379159927368164,79.9891529083252],[49.19360542297363,80.03221321105957],[49.43526649475098,80.00248908996582],[49.379159927368164,79.9891529083252]]],[[[51.20499610900879,80.03804206848145],[51.50193977355957,79.9316577911377],[50.04388618469238,79.9730396270752],[51.20499610900879,80.03804206848145]]],[[[91.17637825012207,80.05304145812988],[93.80859565734863,79.8883228302002],[91.9216480255127,79.67331123352051],[92.3499927520752,79.72776985168457],[90.86442756652832,80.05720710754395],[91.17637825012207,80.05304145812988]]],[[[59.42222023010254,79.92025947570801],[58.759164810180664,80.02276802062988],[59.84471321105957,80.06833076477051],[59.42222023010254,79.92025947570801]]],[[[49.59610176086426,80.0727710723877],[49.683053970336914,80.03637886047363],[49.330278396606445,80.06192207336426],[49.59610176086426,80.0727710723877]]],[[[50.25277900695801,80.1463794708252],[49.972490310668945,80.05415534973145],[49.53221321105957,80.15220832824707],[50.25277900695801,80.1463794708252]]],[[[97.61499214172363,80.1655445098877],[98.03442573547363,80.06749153137207],[97.19304084777832,79.70221138000488],[98.52859687805176,80.05247688293457],[100.01526832580566,79.82415962219238],[99.65915107727051,79.29582405090332],[99.03526496887207,79.29026985168457],[99.93887519836426,78.95332527160645],[97.3047046661377,78.84526252746582],[94.77720832824707,79.08442878723145],[94.33249092102051,79.46554756164551],[93.6988697052002,79.45610237121582],[93.87803840637207,79.60138130187988],[92.85081672668457,79.55386543273926],[94.61609077453613,79.81192207336426],[94.22221565246582,79.89776802062988],[94.93664741516113,80.09942817687988],[95.26944160461426,80.01638984680176],[95.58027839660645,80.11137580871582],[97.61499214172363,80.1655445098877]]],[[[60.261667251586914,80.16331672668457],[59.897775650024414,80.19165229797363],[60.289438247680664,80.16693305969238],[60.261667251586914,80.16331672668457]]],[[[55.15110206604004,80.22026252746582],[54.857500076293945,80.25248908996582],[55.54388618469238,80.29387092590332],[55.15110206604004,80.22026252746582]]],[[[53.621103286743164,80.29498481750488],[53.871660232543945,80.25665473937988],[52.18138313293457,80.27192878723145],[53.621103286743164,80.29498481750488]]],[[[54.221933364868164,80.20416450500488],[54.151384353637695,80.29942512512207],[54.439714431762695,80.2986011505127],[54.221933364868164,80.20416450500488]]],[[[57.096940994262695,80.34305000305176],[57.050546646118164,80.07499885559082],[55.71360969543457,80.1010913848877],[57.096940994262695,80.34305000305176]]],[[[52.45249366760254,80.32110786437988],[52.16666603088379,80.35026741027832],[52.521379470825195,80.3308277130127],[52.45249366760254,80.32110786437988]]],[[[55.3669376373291,80.42886543273926],[55.167497634887695,80.36943244934082],[54.977487564086914,80.41693305969238],[55.3669376373291,80.42886543273926]]],[[[56.30804634094238,80.3813648223877],[55.78611183166504,80.40721321105957],[55.87304878234863,80.43525886535645],[56.30804634094238,80.3813648223877]]],[[[54.637216567993164,80.39360237121582],[54.37027168273926,80.40582466125488],[54.863054275512695,80.45027351379395],[54.637216567993164,80.39360237121582]]],[[[57.96832466125488,80.48942756652832],[59.276384353637695,80.33415412902832],[57.71859931945801,80.09832954406738],[56.94638252258301,80.47442817687988],[57.96832466125488,80.48942756652832]]],[[[54.30166053771973,80.41914558410645],[53.77999305725098,80.46943855285645],[54.45888710021973,80.49803352355957],[54.30166053771973,80.41914558410645]]],[[[55.01583290100098,80.55693244934082],[55.16304969787598,80.49470710754395],[54.6411075592041,80.52804756164551],[55.01583290100098,80.55693244934082]]],[[[53.442216873168945,80.48498725891113],[53.10527229309082,80.61998176574707],[53.39860725402832,80.62664985656738],[53.442216873168945,80.48498725891113]]],[[[58.85527229309082,80.6402759552002],[58.80638313293457,80.58276557922363],[58.53777503967285,80.60582160949707],[58.85527229309082,80.6402759552002]]],[[[58.01055335998535,80.64109992980957],[57.87082862854004,80.55331611633301],[57.21305274963379,80.60359382629395],[58.01055335998535,80.64109992980957]]],[[[56.778879165649414,80.73581123352051],[56.9486026763916,80.69275093078613],[55.43249702453613,80.70833015441895],[56.778879165649414,80.73581123352051]]],[[[47.897775650024414,80.80331611633301],[48.76638984680176,80.6463794708252],[47.751665115356445,80.76638984680176],[47.30332374572754,80.6574878692627],[47.42360877990723,80.5888843536377],[46.08416175842285,80.43692207336426],[46.036386489868164,80.57222175598145],[44.857500076293945,80.61638069152832],[47.897775650024414,80.80331611633301]]],[[[62.21832466125488,80.81109809875488],[61.06610298156738,80.40359687805176],[59.22082710266113,80.64276313781738],[62.21832466125488,80.81109809875488]]],[[[55.44999885559082,80.85138130187988],[55.98276710510254,80.79582405090332],[53.97554969787598,80.81749153137207],[55.44999885559082,80.85138130187988]]],[[[58.98665809631348,80.79165840148926],[57.81638526916504,80.80581855773926],[58.756662368774414,80.89610481262207],[58.98665809631348,80.79165840148926]]],[[[50.1330509185791,80.84665107727051],[51.7469425201416,80.71220588684082],[48.80971717834473,80.37637519836426],[48.62276649475098,80.30026435852051],[49.113054275512695,80.1827564239502],[48.374162673950195,80.08720588684082],[46.61638832092285,80.29081916809082],[48.18387794494629,80.33137702941895],[47.38027381896973,80.45054817199707],[49.192216873168945,80.5213794708252],[49.68138313293457,80.71748542785645],[48.95416450500488,80.73137092590332],[50.44137763977051,80.90387153625488],[50.1330509185791,80.84665107727051]]],[[[79.97720527648926,80.95248603820801],[80.4377613067627,80.92637825012207],[78.97276496887207,80.83749580383301],[79.97720527648926,80.95248603820801]]],[[[58.533334732055664,80.95305061340332],[57.83416175842285,81.04525947570801],[58.69887733459473,81.02554512023926],[58.533334732055664,80.95305061340332]]],[[[50.59721565246582,81.04609870910645],[50.347490310668945,81.09027290344238],[50.98333168029785,81.10054206848145],[50.59721565246582,81.04609870910645]]],[[[56.24249458312988,81.1010913848877],[58.27860450744629,80.91971015930176],[56.096384048461914,81.08915901184082],[56.24249458312988,81.1010913848877]]],[[[58.7580509185791,81.07332038879395],[58.515275955200195,81.10443305969238],[58.80804634094238,81.09749031066895],[58.7580509185791,81.07332038879395]]],[[[54.74943733215332,81.10971260070801],[57.72082710266113,80.79248237609863],[54.4183292388916,81.00610542297363],[54.74943733215332,81.10971260070801]]],[[[60.98526954650879,80.91609382629395],[60.02499580383301,80.99165534973145],[61.65416145324707,81.11081123352051],[60.98526954650879,80.91609382629395]]],[[[58.445268630981445,81.1141529083252],[58.14943885803223,81.12886238098145],[58.64860725402832,81.13499641418457],[58.445268630981445,81.1141529083252]]],[[[91.25027656555176,81.06303596496582],[89.89360237121582,81.1685962677002],[91.57721138000488,81.14305305480957],[91.25027656555176,81.06303596496582]]],[[[65.45248603820801,81.02777290344238],[64.30304145812988,80.72998237609863],[62.504167556762695,80.81833076477051],[64.48359870910645,81.19108772277832],[65.45248603820801,81.02777290344238]]],[[[59.76638984680176,81.17025947570801],[59.01082801818848,81.20721626281738],[59.84471321105957,81.17997932434082],[59.76638984680176,81.17025947570801]]],[[[57.56499671936035,81.1252613067627],[56.99471473693848,81.1655445098877],[58.08055305480957,81.20971870422363],[57.56499671936035,81.1252613067627]]],[[[95.95860481262207,81.21721076965332],[97.96943855285645,80.71554756164551],[97.12915229797363,80.66276741027832],[97.42637825012207,80.3108081817627],[97.15887641906738,80.23359870910645],[94.8097095489502,80.13998603820801],[93.75305366516113,79.99582099914551],[92.06164741516113,80.17025947570801],[93.24664497375488,80.30554389953613],[91.42137336730957,80.3077564239502],[92.62387275695801,80.38499641418457],[91.88943672180176,80.45776557922363],[93.32554817199707,80.80581855773926],[92.48748970031738,80.76748847961426],[93.06860542297363,80.99443244934082],[95.95860481262207,81.21721076965332]]],[[[60.63888740539551,81.27221870422363],[60.37748908996582,81.24414253234863],[59.72221565246582,81.28332710266113],[60.63888740539551,81.27221870422363]]],[[[57.45804786682129,81.31360054016113],[57.90277290344238,81.29026985168457],[55.43166542053223,81.27165412902832],[57.45804786682129,81.31360054016113]]],[[[59.05332374572754,81.28499031066895],[58.46193885803223,81.33859443664551],[59.381662368774414,81.32415962219238],[59.05332374572754,81.28499031066895]]],[[[54.29361152648926,81.33333015441895],[54.42193794250488,81.27026557922363],[54.11471748352051,81.34721565246582],[54.29361152648926,81.33333015441895]]],[[[57.79666328430176,81.52998542785645],[58.57249641418457,81.41192817687988],[56.74138069152832,81.44859504699707],[57.79666328430176,81.52998542785645]]],[[[58.49083137512207,81.55887031555176],[58.22665596008301,81.58137702941895],[58.71971321105957,81.59971809387207],[58.49083137512207,81.55887031555176]]],[[[62.080827713012695,81.54414558410645],[61.654436111450195,81.6030445098877],[62.2036075592041,81.56498908996582],[62.080827713012695,81.54414558410645]]],[[[62.7933292388916,81.70860481262207],[63.80277442932129,81.65332221984863],[62.10416603088379,81.67248725891113],[62.7933292388916,81.70860481262207]]],[[[59.28750038146973,81.74275398254395],[57.88888740539551,81.70694160461426],[59.43776893615723,81.8166675567627],[59.28750038146973,81.74275398254395]]]]}},{"type":"Feature","properties":{"name":"Rwanda","iso2":"RW","iso3":"RWA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[29.952221,-2.309445],[29.85083,-2.759722],[29.024441,-2.744722],[28.868332,-2.394444],[29.596943,-1.385834],[29.974998,-1.464445],[30.48222,-1.063334],[30.894165,-2.076111],[30.57333,-2.399167],[29.952221,-2.309445]]]]}},{"type":"Feature","properties":{"name":"Saudi Arabia","iso2":"SA","iso3":"SAU"},"geometry":{"type":"MultiPolygon","coordinates":[[[[41.957773208618164,16.708887100219727],[41.753610610961914,16.87611198425293],[42.17999458312988,16.566946029663086],[41.957773208618164,16.708887100219727]]],[[[41.98666572570801,16.753332138061523],[41.83722114562988,16.86861228942871],[41.84555244445801,17.009164810180664],[41.98666572570801,16.753332138061523]]],[[[37.08055305480957,24.959165573120117],[37.03582954406738,24.963056564331055],[37.04166603088379,24.996946334838867],[37.08055305480957,24.959165573120117]]],[[[35.754716873168945,27.0947208404541],[35.75777626037598,27.07694435119629],[35.726388931274414,27.128610610961914],[35.754716873168945,27.0947208404541]]],[[[49.53721046447754,27.36360740661621],[49.63861274719238,27.31638526916504],[49.45221138000488,27.285829544067383],[49.53721046447754,27.36360740661621]]],[[[34.59360694885254,27.90916633605957],[34.49221992492676,27.996110916137695],[34.54666328430176,27.99860954284668],[34.59360694885254,27.90916633605957]]],[[[44.721662521362305,29.198331832885742],[46.546945571899414,29.10420036315918],[47.45999336242676,28.999441146850586],[47.68888282775879,28.53888511657715],[48.41658973693848,28.545278549194336],[48.838876724243164,27.619718551635742],[50.15916633605957,26.656667709350586],[49.9938907623291,26.01999855041504],[50.83095741271973,24.749967575073242],[51.215166091918945,24.62088966369629],[51.5836124420166,24.259721755981445],[52.583330154418945,22.93889045715332],[55.199167251586914,22.69972038269043],[55.66610908508301,21.999723434448242],[55.00000190734863,20.000001907348633],[51.99929237365723,18.999345779418945],[48.76638984680176,18.266389846801758],[46.33305549621582,15.616945266723633],[46.333330154418945,16.66666603088379],[44.46750068664551,17.411943435668945],[43.3094425201416,17.457223892211914],[43.20611000061035,16.672224044799805],[42.789682388305664,16.377504348754883],[40.75999641418457,19.760278701782227],[39.17694282531738,21.099164962768555],[39.06277656555176,22.58333396911621],[38.452775955200195,23.782499313354492],[37.441667556762695,24.371389389038086],[37.235551834106445,25.1825008392334],[35.16055488586426,28.056665420532227],[34.571664810180664,28.08888816833496],[34.96138954162598,29.3608341217041],[36.07000160217285,29.18889045715332],[36.743608474731445,29.864721298217773],[37.50277900695801,30.002222061157227],[38.00139045715332,30.504167556762695],[37.00527381896973,31.505556106567383],[39.19674491882324,32.15494346618652],[40.41333198547363,31.948331832885742],[42.08500099182129,31.111661911010742],[44.721662521362305,29.198331832885742]]]]}},{"type":"Feature","properties":{"name":"Saint Kitts and Nevis","iso2":"KN","iso3":"KNA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-62.55278,17.094166],[-62.62194799999989,17.111385],[-62.599724,17.19722],[-62.55278,17.094166]]],[[[-62.70166799999987,17.336941],[-62.62528199999986,17.220833],[-62.863892,17.370831000000138],[-62.70166799999987,17.336941]]]]}},{"type":"Feature","properties":{"name":"Seychelles","iso2":"SC","iso3":"SYC"},"geometry":{"type":"MultiPolygon","coordinates":[[[[46.491386,-9.754446],[46.476105,-9.744167],[46.508331,-9.717779],[46.491386,-9.754446]]],[[[46.510551,-9.396946],[46.269165000000186,-9.463057],[46.204163,-9.389446],[46.510551,-9.396946]]],[[[46.413887,-9.358891],[46.276665,-9.346111],[46.42694100000014,-9.342779],[46.413887,-9.358891]]],[[[56.282219,-7.134167],[56.247215000000125,-7.194445],[56.278610000000214,-7.110834],[56.282219,-7.134167]]],[[[55.53527100000011,-4.763056],[55.376106,-4.627223],[55.45916,-4.55139],[55.53527100000011,-4.763056]]],[[[55.246109,-4.506945],[55.23166700000016,-4.448056],[55.26722000000015,-4.481668],[55.246109,-4.506945]]],[[[55.775833,-4.348333],[55.687218,-4.2875],[55.77166,-4.315556],[55.775833,-4.348333]]]]}},{"type":"Feature","properties":{"name":"South Africa","iso2":"ZA","iso3":"ZAF"},"geometry":{"type":"MultiPolygon","coordinates":[[[[37.85083,-46.956947],[37.576385000000215,-46.909447],[37.781944,-46.83223],[37.85083,-46.956947]]],[[[37.959442000000166,-46.658615],[37.856941,-46.626945],[37.942772,-46.60334],[37.959442000000166,-46.658615]]],[[[29.893887,-22.194447],[31.297504000000146,-22.414764],[32.016106,-24.459446],[31.96851,-25.95784],[31.33083,-25.751392],[30.902048,-26.305254],[30.818886000000106,-26.810558],[31.161663,-27.203056],[31.987499,-27.316113],[32.1334,-26.839626],[32.890427,-26.847145],[32.39027400000012,-28.537781],[31.325832,-29.390835],[30.0238880000002,-31.281113],[27.899998,-33.040558],[26.53055200000017,-33.753334],[25.724998,-33.767227],[25.701942,-34.031952],[22.544998,-34.005005],[20,-34.822002],[18.817776,-34.377785],[18.793331,-34.08667],[18.40472000000011,-34.30278],[18.441109,-33.706673],[17.8475,-32.830833],[18.292221,-32.624451],[18.27861000000013,-31.89278],[16.48959,-28.578178],[17.06361,-28.028614],[17.40472,-28.713612],[18.175831,-28.908611],[19.123055000000107,-28.962223],[19.99612,-28.421448],[20.000942,-24.765408],[20.811386,-25.883335],[20.642498,-26.828056],[21.667221,-26.864445],[22.624809000000113,-26.111565],[23.014832000000126,-25.299725],[24.6772,-25.827824],[25.50972,-25.67778],[25.871387,-24.744446],[26.845276,-24.264446],[26.95919,-23.752075],[28.29833200000013,-22.609447],[29.373623,-22.19241],[29.893887,-22.194447]],[[28.565552,-28.610001],[27.011108,-29.625278],[27.564617,-30.404911],[28.079937,-30.650528],[28.377777,-30.16028],[29.168888,-29.913891],[29.430832,-29.278614],[28.565552,-28.610001]]]]}},{"type":"Feature","properties":{"name":"Lesotho","iso2":"LS","iso3":"LSO"},"geometry":{"type":"MultiPolygon","coordinates":[[[[27.564617,-30.404911],[27.011108,-29.625278],[28.565552,-28.610001],[29.430832,-29.278614],[29.168888,-29.913891],[28.377777,-30.16028],[28.079937,-30.650528],[27.564617,-30.404911]]]]}},{"type":"Feature","properties":{"name":"Botswana","iso2":"BW","iso3":"BWA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[26.95919,-23.752075],[26.845276,-24.264446],[25.871387,-24.744446],[25.50972,-25.67778],[24.6772,-25.827824],[23.014832000000126,-25.299725],[22.624809000000113,-26.111565],[21.667221,-26.864445],[20.642498,-26.828056],[20.811386,-25.883335],[20.000942,-24.765408],[19.996666,-22.005001],[20.991943,-21.996948],[20.993286,-18.318417],[23.297108,-17.995949],[23.615578,-18.485069],[24.362499,-17.948612],[25.264431,-17.80225],[26.166111,-19.527779],[27.219997,-20.091667],[27.287453,-20.494965],[27.713165,-20.506432],[28.015831,-21.566113],[29.060555,-21.798058],[29.373623,-22.19241],[28.29833200000013,-22.609447],[26.95919,-23.752075]]]]}},{"type":"Feature","properties":{"name":"Senegal","iso2":"SN","iso3":"SEN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-17.148308,14.61392],[-17.537224,14.756109],[-16.878334,15.224998],[-16.527679,16.060249],[-16.280834,16.519722],[-14.345278,16.638611],[-12.244833,14.764385],[-12.057222,13.664721],[-11.378056,12.988054],[-11.373058,12.407774],[-12.345404,12.301748],[-13.713139,12.677221],[-14.516945,12.67972200000014],[-16.71777,12.322426],[-16.586945,12.632776],[-15.626945,12.531111],[-15.390001,12.831944],[-15.650002,12.555555],[-16.598057,12.791666],[-16.756111,12.564999],[-16.750874,13.059977],[-15.809723,13.159721],[-15.803612,13.347776],[-15.285002,13.374443],[-15.111668,13.595833],[-14.351112,13.237778],[-13.798613,13.406387],[-15.070278,13.826387],[-16.56567,13.589998],[-16.490837,13.958055],[-16.747223,13.951944],[-16.363056,14.166111],[-16.775837,14.012499],[-17.148308,14.61392]]]]}},{"type":"Feature","properties":{"name":"Slovenia","iso2":"SI","iso3":"SVN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[13.718655,46.526611],[14.544998,46.407494],[16.111805,46.86972],[16.607872,46.476234],[16.572498,46.475273],[15.654722,46.219444],[15.697777,45.844162],[15.174458,45.425819],[14.601387,45.675278],[13.591740000000101,45.481697],[13.716944,45.596107],[13.919167,45.637497],[13.480000000000103,46.011108],[13.669167,46.177498],[13.383055,46.297218],[13.718655,46.526611]]]]}},{"type":"Feature","properties":{"name":"Sierra Leone","iso2":"SL","iso3":"SLE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-12.525278,7.431389],[-12.952778,7.568333],[-12.591112,7.634444],[-12.525278,7.431389]]],[[[-11.214444999999898,9.997499],[-10.571526,9.059532],[-10.695835,8.298611],[-10.266651,8.488377],[-11.492331,6.927091000000132],[-12.958612,7.9],[-13.288057,8.496111000000127],[-13.05139,8.36861],[-13.120278999999897,8.461666000000122],[-12.897500999999863,8.567778],[-13.165279,8.51861],[-13.2425,8.802500000000123],[-13.132223,8.861944],[-13.29561,9.032143],[-12.456112,9.888332],[-11.214444999999898,9.997499]]]]}},{"type":"Feature","properties":{"name":"Singapore","iso2":"SG","iso3":"SGP"},"geometry":{"type":"MultiPolygon","coordinates":[[[[103.99054,1.383291],[103.640808,1.315555],[103.713593,1.429444],[103.99054,1.383291]]]]}},{"type":"Feature","properties":{"name":"Somalia","iso2":"SO","iso3":"SOM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[42.944092,11.002438],[43.249222,11.469534],[44.278328,10.447777],[44.898331,10.420555],[45.759995,10.875277],[46.448051,10.688889],[47.398888,11.179998],[50.085548,11.511944],[50.76944,11.979166],[51.277222,11.836666],[51.01416,10.442778],[51.412636,10.451515],[50.896942,10.319721],[50.83625,9.432688],[47.954437,4.463888],[46.014717,2.427778],[43.488609,0.649999],[41.558159,-1.674868],[40.998329,-0.866111],[40.98659500000011,2.829956],[41.905167,3.980322],[43.686386,4.891944],[44.950829,4.902499],[47.988243,8.004107],[47.01194,8.00111],[44.010551,9.007221],[42.848053,10.22361],[42.663055,10.6325],[42.944092,11.002438]]]]}},{"type":"Feature","properties":{"name":"Spain","iso2":"ES","iso3":"ESP"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-17.91278076171875,27.771665573120117],[-17.98278045654297,27.63749885559082],[-18.17055892944336,27.73722267150879],[-17.91278076171875,27.771665573120117]]],[[[-15.554166793823242,27.755834579467773],[-15.70250129699707,28.156110763549805],[-15.365556716918945,28.010278701782227],[-15.554166793823242,27.755834579467773]]],[[[-17.175003051757812,28.016942977905273],[-17.31694793701172,28.172224044799805],[-17.101947784423828,28.134721755981445],[-17.175003051757812,28.016942977905273]]],[[[-16.341114044189453,28.37027931213379],[-16.671390533447266,27.984167098999023],[-16.91278076171875,28.34139060974121],[-16.15694808959961,28.572221755981445],[-16.341114044189453,28.37027931213379]]],[[[-14.32722282409668,28.046388626098633],[-13.869722366333008,28.75139045715332],[-13.923055648803711,28.24916648864746],[-14.32722282409668,28.046388626098633]]],[[[-17.831947326660156,28.453889846801758],[-17.90444564819336,28.849443435668945],[-17.716392517089844,28.746110916137695],[-17.831947326660156,28.453889846801758]]],[[[-13.609724044799805,28.926389694213867],[-13.852222442626953,28.906389236450195],[-13.442501068115234,29.23166847229004],[-13.609724044799805,28.926389694213867]]],[[[-2.925277709960938,35.26666450500488],[-2.946945190429688,35.32916450500488],[-2.914722442626953,35.27360725402832],[-2.925277709960938,35.26666450500488]]],[[[-5.31944465637207,35.87693977355957],[-5.345832824707031,35.84166145324707],[-5.395557403564453,35.916337966918945],[-5.31944465637207,35.87693977355957]]],[[[-3.036109924316406,35.91277503967285],[-3.051111221313477,35.91583442687988],[-3.0272216796875,35.92444038391113],[-3.036109924316406,35.91277503967285]]],[[[1.577779769897461,38.68777656555176],[1.390279769897461,38.643327713012695],[1.383054733276367,38.72055244445801],[1.577779769897461,38.68777656555176]]],[[[1.531667709350586,38.95194435119629],[1.211946487426758,38.898332595825195],[1.519723892211914,39.11833381652832],[1.531667709350586,38.95194435119629]]],[[[3.247777938842773,39.73472023010254],[3.47972297668457,39.71110725402832],[3.06361198425293,39.26361274719238],[2.364168167114258,39.55583381652832],[2.98777961730957,39.91111183166504],[3.247777938842773,39.73472023010254]]],[[[4.273332595825195,39.96138954162598],[4.276388168334961,39.8063907623291],[3.796945571899414,40.017221450805664],[4.273332595825195,39.96138954162598]]],[[[-7.855554580688477,43.75999641418457],[-7.044818878173828,43.49040412902832],[-1.780876159667969,43.35992622375488],[-0.562221527099609,42.781389236450195],[1.445833206176758,42.601945877075195],[1.723611831665039,42.50943946838379],[3.177656173706055,42.43680763244629],[3.17527961730957,41.86749458312988],[0.964445114135742,41.03277778625488],[0.048891067504883,40.03610420227051],[-0.338054656982422,39.435556411743164],[0.207223892211914,38.73221015930176],[-0.511667251586914,38.32499885559082],[-0.715555191040039,37.606943130493164],[-1.643610000610352,37.37277412414551],[-2.129165649414063,36.73138618469238],[-4.398332595825195,36.72222328186035],[-5.334506988525391,36.16256141662598],[-5.355798721313477,36.16330909729004],[-6.037500381469727,36.18027687072754],[-6.355554580688477,36.8608341217041],[-7.431854248046875,37.253190994262695],[-7.446945190429688,37.69944190979004],[-6.939167022705078,38.178056716918945],[-7.321111679077148,38.44944190979004],[-6.954792022705078,39.026384353637695],[-7.532505035400391,39.66942024230957],[-7.017221450805664,39.674997329711914],[-6.931667327880859,41.01805305480957],[-6.187221527099609,41.579721450805664],[-6.594165802001953,41.9536075592041],[-8.204723358154297,41.87471961975098],[-8.201223373413086,42.15274238586426],[-8.74500846862793,41.95250129699707],[-8.898612976074219,42.10805702209473],[-8.579723358154297,42.35166358947754],[-8.86916732788086,42.25139045715332],[-8.719446182250977,42.69583320617676],[-9.041389465332031,42.528886795043945],[-9.20944595336914,43.15277290344238],[-7.855554580688477,43.75999641418457]],[[-6.924999237060547,37.17083168029785],[-6.973054885864258,37.210275650024414],[-6.954166412353516,37.18027687072754],[-6.924999237060547,37.17083168029785]]]]}},{"type":"Feature","properties":{"name":"Saint Lucia","iso2":"LC","iso3":"LCA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-60.954727,13.709444],[-61.079445,13.879999],[-60.930283,14.109444],[-60.954727,13.709444]]]]}},{"type":"Feature","properties":{"name":"Sudan","iso2":"SD","iso3":"SDN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[37.268608000000114,20.75111],[37.242218,20.785831],[37.263855,20.84972400000011],[37.268608000000114,20.75111]]],[[[31.453888,21.998333000000102],[36.888466,22.000111000000132],[37.309441,21.060276],[37.10527000000016,21.212219],[37.433327000000105,18.858055],[38.600693,17.994881],[37.423286000000104,17.034214],[36.995827,17.073887],[36.97305300000019,16.269444],[36.44328300000021,15.149952],[36.5428160000001,14.262053],[36.142693,12.706923000000117],[35.70108,12.666115],[35.096939000000106,11.826944],[34.864441,10.734999],[34.594444,10.887777],[34.28611,10.554165],[34.120552,8.577221000000122],[33.252777,8.458611000000118],[32.991104,7.924999],[33.711388,7.660277],[34.70472,6.677777000000106],[35.30194100000014,5.378055],[35.821663,5.32861],[35.940552,4.622499],[34.388191,4.609682],[33.996666,4.222777000000136],[33.516937,3.752222],[33.016663,3.888611000000111],[32.193329,3.511389000000108],[31.176666,3.795278],[30.858818,3.493394000000137],[29.64333,4.643611000000135],[28.363052,4.29],[27.455276,5.016388],[27.142776,5.771944],[26.437496000000124,6.077777],[26.404999,6.646388],[25.206944000000135,7.497499],[25.25333,7.850555],[24.192497000000117,8.30361],[24.201111,8.686943],[23.517776,8.714167],[23.669167,9.866943],[22.866505,10.922447],[22.46694200000013,12.621666],[21.827774,12.797499000000144],[22.294167,13.35861],[22.084442,13.779165],[22.55499600000013,14.125555000000148],[22.384163,14.55416500000014],[22.935833,15.11611],[22.937222000000105,15.561943],[23.999603,15.698709],[24.002747,19.499065],[24.000832000000116,20.001942],[25.000832,19.999119],[25.001423,21.999695],[31.271111000000104,21.998333000000102],[31.455555000000146,22.23222],[31.453888,21.998333000000102]]]]}},{"type":"Feature","properties":{"name":"Sweden","iso2":"SE","iso3":"SWE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[16.836666,56.82694200000013],[16.420830000000194,56.211105],[17.105553,57.348328],[16.836666,56.82694200000013]]],[[[18.206108,56.91194200000011],[18.119164,57.531105],[19.004719000000136,57.908607],[18.206108,56.91194200000011]]],[[[19.334442,57.955826],[19.12611,57.839722],[19.034443,57.901108],[19.334442,57.955826]]],[[[11.594444,57.932495000000145],[11.501944,58.036659],[11.735884,58.041714],[11.594444,57.932495000000145]]],[[[16.816666,58.116104],[16.77861,58.100555],[16.801109,58.12332900000011],[16.816666,58.116104]]],[[[11.806389000000195,58.120552],[11.40111,58.13027200000012],[11.6775,58.286659000000114],[11.806389000000195,58.120552]]],[[[19.236942,58.337219],[19.186665,58.391388],[19.331108,58.366104],[19.236942,58.337219]]],[[[17.691387,58.91693900000014],[17.639164,58.971107],[17.6758310000001,59.054718],[17.691387,58.91693900000014]]],[[[18.40583,59.023888],[18.35722,59.034996],[18.479164000000196,59.11999500000012],[18.40583,59.023888]]],[[[18.537220000000133,59.223885],[18.389442000000145,59.284721],[18.610275000000144,59.254166000000126],[18.537220000000133,59.223885]]],[[[17.786942,59.310555],[17.6055530000001,59.416664],[17.773888,59.372772],[17.786942,59.310555]]],[[[17.734722000000147,59.296104],[17.817497,59.2777710000001],[17.62277600000013,59.30527500000012],[17.52027500000011,59.418327],[17.734722000000147,59.296104]]],[[[17.266388000000177,59.374443],[17.07,59.459442],[17.266941,59.44416],[17.266388000000177,59.374443]]],[[[18.575554,59.448326],[18.570274,59.526382],[18.746944,59.544998],[18.575554,59.448326]]],[[[18.57,60.307777],[18.401108,60.36527300000013],[18.374165000000175,60.4997180000001],[18.57,60.307777]]],[[[17.509163,62.363327],[17.367222000000197,62.471664],[17.472221,62.458328],[17.509163,62.363327]]],[[[18.060833000000173,62.67083],[18.039165,62.73555000000012],[18.153053000000142,62.728882],[18.060833000000173,62.67083]]],[[[20.885555,63.751663000000136],[20.83805500000011,63.773331],[20.928608000000168,63.773331],[20.885555,63.751663000000136]]],[[[21.809166,68.570541],[23.66611100000017,67.941666],[23.431110000000103,67.46554600000015],[23.76777600000011,67.41610700000014],[23.571663,67.15666200000011],[24.007774,66.800552],[23.661942,66.31221],[24.167007000000126,65.814026],[22.644722,65.905548],[22.3291660000001,65.829712],[22.40583,65.535263],[21.766941,65.722488],[22.199165,65.54527300000014],[21.260555,65.337494],[21.621387,65.142212],[21.03611000000018,64.8244320000001],[21.584999,64.439713],[20.777775,63.869164],[19.428055,63.549438],[18.20861100000019,62.77861],[17.696663,62.991943],[18.048054,62.601387],[17.32888800000012,62.486938],[17.654720000000168,62.23111],[17.34972000000016,61.945274],[17.498886,61.63582600000014],[17.140274,61.719719],[17.150555,60.945],[19.081944000000192,59.75972],[17.941109,59.335548],[17.764442,59.400551],[17.845276,59.53305100000013],[17.71722000000011,59.66333],[17.59222,59.656105000000125],[17.648331,59.66583300000015],[17.654163,59.718048],[17.594166,59.80693800000013],[17.4447210000001,59.676109],[17.543152000000163,59.573006],[17.513054000000125,59.706383],[17.618332,59.73138400000012],[17.561171000000172,59.668449],[17.786663,59.535828],[17.73111,59.442772],[17.38361,59.654999],[16.020275,59.49499500000012],[16.88999900000016,59.383331],[16.692776,59.471382],[16.84027500000019,59.48944100000013],[17.375832,59.247498],[17.35083,59.32444],[17.847221,59.264442],[18.289444000000174,59.368607],[18.466663,59.330276000000126],[18.434444,59.433609],[18.640274,59.338882],[18.277222,59.31082900000011],[18.311386,59.1325],[17.894722000000115,58.858887],[17.663887,59.168327],[17.349998,58.75222000000015],[16.193607,58.62749500000011],[16.93861,58.4841610000001],[16.413330000000116,58.474716],[16.824718,58.19944],[16.613888,57.98693800000011],[16.770554000000175,57.884438],[16.495552,57.98555],[16.70070600000011,57.74015],[16.418610000000115,57.893326],[16.693333,57.469162],[15.865555,56.092216],[14.696665,56.161110000000164],[14.217222,55.830276000000126],[14.193546,55.386147],[12.982222,55.400551],[13.059721,55.693054],[12.451666000000102,56.2977750000001],[12.813332000000145,56.23277300000011],[12.622221,56.411942],[12.887499000000162,56.638329],[11.698889000000179,57.697220000000144],[11.88611,58.211937],[11.798054,58.318329],[11.201387000000182,58.399437],[11.113333000000125,59.00360900000011],[11.429192000000114,58.98764],[11.751110000000153,59.0902710000001],[11.815960000000189,59.8461],[12.494165,60.1111070000001],[12.594444000000124,60.516937],[12.209999,61.002495],[12.85611,61.36249500000012],[12.124443,61.728607],[12.295832000000132,62.261665],[11.936388,63.272217],[12.139444000000111,63.58416],[12.938055,64.05332900000015],[13.988333000000154,64.01805100000014],[14.116388,64.470551],[13.662498,64.58276400000013],[14.49305500000014,65.313599],[14.504999,66.13249200000014],[15.468054000000109,66.283875],[15.362778,66.479996],[16.353886,67.017776],[16.085831,67.41165200000013],[16.726944000000174,67.899155],[17.884163,67.945541],[18.090832,68.50776700000013],[19.937775,68.33749400000012],[20.350277000000176,68.7866520000001],[20.096943,69.042221],[20.580929,69.060303],[21.809166,68.570541]]]]}},{"type":"Feature","properties":{"name":"Syrian Arab Republic","iso2":"SY","iso3":"SYR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[42.355614,37.106926],[41.290276,36.355553],[41.003876,34.419434],[38.794701,33.377594],[36.837776,32.313606],[35.648888,32.685272],[35.623634,33.245728],[36.623741,34.204994],[36.459999,34.635277],[35.972771,34.647499],[35.733887,35.581665],[35.92244,35.926994],[36.69026900000014,36.236107],[36.659943,36.83371],[39.229996,36.665276],[40.770821,37.11805],[42.355614,37.106926]]]]}},{"type":"Feature","properties":{"name":"Switzerland","iso2":"CH","iso3":"CHE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[7.697223,47.543327000000104],[8.576420000000155,47.59137],[8.566111,47.806938],[9.566724,47.540451],[9.533569,47.274544],[9.474637,47.057457],[9.598635,47.063835],[10.471235,46.871353],[10.465277000000128,46.546387],[10.050278000000105,46.539993],[10.129999000000112,46.22721900000015],[9.281944000000124,46.49582700000015],[9.036665,45.837776],[8.436388000000136,46.463333000000105],[7.855742,45.91905200000012],[7.038054,45.93193800000013],[6.791389000000152,46.434166],[5.966666,46.209442],[6.990555000000143,47.497215],[7.588268,47.58448],[7.697223,47.543327000000104]],[[8.710255,47.696808],[8.670555,47.711105],[8.678595,47.693344],[8.710255,47.696808]]]]}},{"type":"Feature","properties":{"name":"Trinidad and Tobago","iso2":"TT","iso3":"TTO"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-60.923058,10.797222],[-61.008057,10.140554000000122],[-61.91806,10.042776],[-61.458336,10.278332],[-61.662224,10.709166000000124],[-60.923058,10.797222]]],[[[-60.63945,11.203054],[-60.847504,11.158333000000141],[-60.526672,11.346109],[-60.63945,11.203054]]]]}},{"type":"Feature","properties":{"name":"Thailand","iso2":"TH","iso3":"THA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[99.219162,6.532499],[99.159988,6.548888],[99.256119,6.571944],[99.219162,6.532499]]],[[[99.668045,6.496387],[99.594986,6.593888],[99.66281100000012,6.702995],[99.668045,6.496387]]],[[[100.536087,7.15611000000014],[100.520813,7.154999],[100.534973,7.174166],[100.536087,7.15611000000014]]],[[[99.38916,7.194721],[99.39360000000013,7.270555000000144],[99.419144,7.234165000000147],[99.38916,7.194721]]],[[[99.110809,7.46805500000012],[99.04248,7.525832],[99.0241550000002,7.636666],[99.110809,7.46805500000012]]],[[[99.11970500000021,7.591944],[99.045822,7.669443000000101],[99.12191800000014,7.665277],[99.11970500000021,7.591944]]],[[[98.434708,7.930554],[98.418045,7.93611],[98.43692,7.94361],[98.434708,7.930554]]],[[[98.603592,7.901111],[98.526093,8.121386],[98.61192300000013,8.048609],[98.603592,7.901111]]],[[[98.39984100000018,7.941753],[98.305252,7.757222],[98.282486,8.186386000000155],[98.39984100000018,7.941753]]],[[[98.616653,8.084442000000124],[98.568329,8.11722],[98.628311,8.189165],[98.616653,8.084442000000124]]],[[[98.266663,9.030554],[98.28082300000014,9.158054],[98.324432,9.084164],[98.266663,9.030554]]],[[[97.87915,9.381941000000126],[97.835266,9.402777000000142],[97.847214,9.43222],[97.87915,9.381941000000126]]],[[[97.89888,9.437498],[97.847488,9.45860900000011],[97.883881,9.475554],[97.89888,9.437498]]],[[[99.681366,9.506109],[99.664993,9.524443],[99.7086029999999,9.53861],[99.681366,9.506109]]],[[[98.467484,9.574999000000105],[98.45776400000014,9.573887000000113],[98.464432,9.585554],[98.467484,9.574999000000105]]],[[[99.976089,9.41361000000012],[99.93220500000015,9.546944],[100.080833,9.58861],[99.976089,9.41361000000012]]],[[[99.685532,9.606665],[99.676651,9.607498],[99.67359900000011,9.629164],[99.685532,9.606665]]],[[[98.407211,9.714165],[98.380814,9.732775000000103],[98.40832500000013,9.770832],[98.407211,9.714165]]],[[[100.08167300000011,9.686665],[99.99054,9.711388000000142],[99.987488,9.796387],[100.08167300000011,9.686665]]],[[[102.59552,11.56361],[102.531357,11.601387],[102.560226,11.754396],[102.59552,11.56361]]],[[[102.435791,11.954165],[102.29135100000022,11.97444200000011],[102.250549,12.15],[102.435791,11.954165]]],[[[102.241089,12.283888],[102.235527,12.285276],[102.2397,12.299442],[102.241089,12.283888]]],[[[100.68887300000014,12.923609],[100.671654,12.938332],[100.676376,12.952776],[100.68887300000014,12.923609]]],[[[100.816673,13.129442],[100.807213,13.180277],[100.821381,13.15055500000011],[100.816673,13.129442]]],[[[100.08132200000014,20.348841],[100.09137,20.348606],[100.58046,20.157768000000104],[100.50360100000015,19.526665],[101.281097,19.562218],[100.921371,17.56721900000015],[101.162773,17.459995],[102.089394,18.214983000000146],[102.683594,17.819996],[103.397217,18.434994],[103.985527,18.321663],[104.71832300000014,17.50333],[104.747208,16.528332],[105.637772,15.659721],[105.536102,14.563332000000116],[105.210602,14.349648],[103.180542,14.32972],[102.37719700000011,13.573887],[102.916092,11.635851],[102.06025700000012,12.567497],[100.85386700000018,12.682775],[100.976349,13.462809],[100.066673,13.41999800000012],[100.021378,12.194164],[99.149155,10.365553],[99.237488,9.25416600000014],[99.847763,9.30083100000013],[100.421082,7.159444000000136],[101.541367,6.851388],[102.09523,6.236138],[101.833862,5.743332],[101.56997700000014,5.916666],[101.139687,5.631943],[101.11551700000021,6.248888000000122],[100.654968,6.448332],[100.214981,6.711110000000119],[100.127113,6.424947],[98.656372,8.38361],[98.27415500000015,8.274443000000119],[98.742752,10.348608],[99.661652,11.826942],[99.112198,13.055832],[99.173965,13.727781],[98.201096,15.074999],[98.92804,16.38583],[98.68969700000011,16.284996],[97.346375,18.562496000000138],[97.774704,18.569996],[98.049988,19.807499000000135],[98.995529,19.780552],[99.522766,20.352776000000134],[100.08132200000014,20.348841]]]]}},{"type":"Feature","properties":{"name":"Tajikistan","iso2":"TJ","iso3":"TJK"},"geometry":{"type":"MultiPolygon","coordinates":[[[[74.915741,37.237328],[73.307205,37.462753],[71.6772,36.67601],[71.429428,37.075829],[71.591934,37.902618],[71.252777,37.922035],[71.363037,38.248497],[70.967209,38.472115],[70.161377,37.933372],[70.155823,37.536232],[69.515823,37.580826],[69.315262,37.115273],[68.887772,37.3386],[68.058014,36.932526],[67.779877,37.185822],[68.384155,38.195541],[68.123871,38.98555],[67.376373,39.212494],[67.441956,39.483582],[68.540268,39.55471],[69.009995,40.089714],[68.600815,40.178329],[69.308029,40.201385],[69.356094,40.772491],[69.732483,40.638603],[70.423874,41.049118],[70.796799,40.725594],[70.375534,40.376404],[70.98204,40.244843],[70.498032,39.90683],[69.540817,40.131378],[69.306091,39.539436],[70.997757,39.40094],[71.473038,39.6213],[72.248596,39.191856],[73.655685,39.454826],[73.817764,38.607712],[74.8566440000001,38.470482],[74.902771,37.647156],[75.187485,37.406586000000104],[74.915741,37.237328]]]]}},{"type":"Feature","properties":{"name":"Tokelau","iso2":"TK","iso3":"TKL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-171.214722,-9.377499],[-171.223907,-9.378889],[-171.224701,-9.345556],[-171.214722,-9.377499]]],[[[-171.843079,-9.207502],[-171.860535,-9.206667],[-171.853882,-9.168058],[-171.843079,-9.207502]]],[[[-172.483917,-8.587221],[-172.496979,-8.553888],[-172.483612,-8.566666],[-172.483917,-8.587221]]]]}},{"type":"Feature","properties":{"name":"Tonga","iso2":"TO","iso3":"TON"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-174.91085815429688,-21.426666259765625],[-174.97470092773438,-21.365833282470703],[-174.91143798828125,-21.306110382080078],[-174.91085815429688,-21.426666259765625]]],[[[-175.14584350585938,-21.178058624267578],[-175.35946655273438,-21.099170684814453],[-175.0472412109375,-21.139442443847656],[-175.14584350585938,-21.178058624267578]]],[[[-174.76083374023438,-20.276390075683594],[-174.79196166992188,-20.234722137451172],[-174.76004028320312,-20.237224578857422],[-174.76083374023438,-20.276390075683594]]],[[[-174.4139404296875,-19.926666259765625],[-174.42254638671875,-19.910003662109375],[-174.390869140625,-19.881668090820312],[-174.4139404296875,-19.926666259765625]]],[[[-174.318603515625,-19.821945190429688],[-174.35498046875,-19.81195068359375],[-174.31585693359375,-19.764171600341797],[-174.318603515625,-19.821945190429688]]],[[[-175.05667114257812,-19.800838470458984],[-175.09860229492188,-19.749725341796875],[-175.08169555664062,-19.706390380859375],[-175.05667114257812,-19.800838470458984]]],[[[-174.27252197265625,-19.752784729003906],[-174.30722045898438,-19.740833282470703],[-174.25613403320312,-19.688053131103516],[-174.27252197265625,-19.752784729003906]]],[[[-175.01834106445312,-19.691387176513672],[-175.03585815429688,-19.676666259765625],[-175.00558471679688,-19.65250015258789],[-175.01834106445312,-19.691387176513672]]],[[[-174.24447631835938,-19.656112670898438],[-174.28195190429688,-19.634445190429688],[-174.29196166992188,-19.594444274902344],[-174.24447631835938,-19.656112670898438]]],[[[-174.64697265625,-18.830280303955078],[-174.675048828125,-18.804447174072266],[-174.6497802734375,-18.783058166503906],[-174.62307739257812,-18.809444427490234],[-174.64697265625,-18.830280303955078]]],[[[-174.0614013671875,-18.704723358154297],[-174.09780883789062,-18.696388244628906],[-174.07363891601562,-18.681110382080078],[-174.0614013671875,-18.704723358154297]]],[[[-174.01974487304688,-18.717220306396484],[-174.0433349609375,-18.680835723876953],[-174.01919555664062,-18.694446563720703],[-174.01974487304688,-18.717220306396484]]],[[[-174.0897216796875,-18.674171447753906],[-174.1280517578125,-18.70333480834961],[-174.11581420898438,-18.671390533447266],[-174.0897216796875,-18.674171447753906]]],[[[-173.91055297851562,-18.638057708740234],[-174.07058715820312,-18.632503509521484],[-173.939208984375,-18.568893432617188],[-173.91055297851562,-18.638057708740234]]],[[[-175.64474487304688,-15.629167556762695],[-175.68392944335938,-15.589723587036133],[-175.62139892578125,-15.560834884643555],[-175.64474487304688,-15.629167556762695]]]]}},{"type":"Feature","properties":{"name":"Togo","iso2":"TG","iso3":"TGO"},"geometry":{"type":"MultiPolygon","coordinates":[[[[1.398542,9.429901],[1.635404,6.218721],[1.198891,6.100546],[0.525,6.947778],[0.727222,8.321388],[0.382735,8.760756],[0.550833,9.411388],[0.2175,9.457222],[0.368333,10.259443],[-0.149762,11.13854],[0.91797,10.996399],[0.776667,10.376665],[1.355,9.995277],[1.398542,9.429901]]]]}},{"type":"Feature","properties":{"name":"Sao Tome and Principe","iso2":"ST","iso3":"STP"},"geometry":{"type":"MultiPolygon","coordinates":[[[[6.523889000000139,0.018333],[6.467222,0.259722000000139],[6.687778,0.402222],[6.523889000000139,0.018333]]],[[[7.423055,1.556111],[7.327222,1.607222000000107],[7.406666000000143,1.701944000000154],[7.423055,1.556111]]]]}},{"type":"Feature","properties":{"name":"Tunisia","iso2":"TN","iso3":"TUN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[10.99361,33.75],[10.865,33.638611],[10.72611,33.880829],[10.99361,33.75]]],[[[11.064722,34.64054900000015],[11.03500000000011,34.617493000000124],[10.961111000000102,34.655273],[11.064722,34.64054900000015]]],[[[11.13722,34.675278],[11.230833,34.821106],[11.302221,34.80332900000012],[11.13722,34.675278]]],[[[10.808611,37.119438],[10.791943,37.126389],[10.814722,37.125275000000116],[10.808611,37.119438]]],[[[9.845247000000143,37.139351],[10.252499,37.186386],[10.381943000000149,36.723328],[11.067778000000118,37.051384],[10.455276,36.123329],[11.128887,35.23583200000017],[10.005833,34.16693900000011],[10.331944,33.700272],[11.048611,33.61694300000012],[11.17111,33.210831],[11.526081,33.171135],[11.567499,32.442215],[10.287222,31.694164],[10.21361,30.730831],[9.537113,30.23439],[9.055277,32.099998],[8.34861,32.533333],[7.492499000000123,33.887497],[8.251665,34.64444],[8.183611,36.524162],[8.62203,36.941368],[9.672499000000187,37.338051],[9.845247000000143,37.139351]]],[[[8.917776000000174,37.510826],[8.896111000000133,37.525833],[8.9447210000001,37.538055],[8.917776000000174,37.510826]]]]}},{"type":"Feature","properties":{"name":"Turkey","iso2":"TR","iso3":"TUR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[26.078053,39.783600000000106],[25.97499500000015,39.829987],[26.07582900000017,39.839722],[26.078053,39.783600000000106]]],[[[25.824444,40.100266],[25.66388300000017,40.126389],[26.013611,40.157494],[25.824444,40.100266]]],[[[27.607220000000154,40.57222],[27.531109,40.648331],[27.735271,40.634438000000145],[27.607220000000154,40.57222]]],[[[35.09693100000018,41.961655],[35.506386000000106,41.638054],[36.051102,41.691933],[36.429153,41.242775],[38.361382,40.909431],[40.149994,40.920273],[41.531559,41.523876],[42.827492,41.584991],[43.46077,41.112961],[43.75193800000014,40.739998],[43.65749400000013,40.10859700000016],[44.347214,40.023888],[44.778862,39.70638300000017],[44.813042,39.630814],[44.605820000000136,39.78054],[44.4161,39.425262],[44.034157,39.3849950000001],[44.484154,38.345543],[44.223969,37.899151],[44.61805,37.727768],[44.787338,37.149712],[44.317215,36.970543],[44.116379,37.316376],[42.790825000000126,37.384720000000144],[42.355614,37.106926],[40.770821,37.11805],[39.229996,36.665276],[36.659943,36.83371],[36.69026900000014,36.236107],[35.92244,35.926994],[35.783875,36.312485],[36.217766,36.654999],[36.02193500000013,36.926384],[35.339989,36.539162],[34.659431,36.805275],[33.98860200000016,36.277771],[32.808884,36.02555100000011],[31.046661,36.849152],[30.623333000000144,36.850822],[30.40694,36.203606],[29.67721600000013,36.11833200000014],[28.454163,36.881386],[27.983887,36.55277300000013],[28.118332,36.800278],[27.37944000000016,36.680832],[28.328606,37.039719],[27.252499,36.96749900000013],[27.595276,37.232491],[27.193886,37.350822],[27.267773000000147,37.955544],[26.275829,38.264435],[26.369999,38.661942],[26.682217,38.307487],[27.161942000000124,38.443886],[26.730827,38.645821],[27.064442,38.874435],[26.644722000000144,39.263054],[26.951664,39.552773],[26.067219,39.483047],[26.707222,40.384995],[28.985271,40.356934],[28.795277,40.551384],[29.938049,40.723885],[29.12944000000016,40.914444],[29.166111,41.226662],[31.23111,41.0888750000001],[33.33387800000017,42.020264],[35.09693100000018,41.961655]]],[[[27.394997,42.008041],[28.013054,41.982216],[28.090549000000124,41.631386],[29.039162,41.057213],[27.50972,40.983597],[26.181107,40.045273],[26.826939,40.594437],[26.044720000000154,40.735825],[26.63388400000011,41.35443900000014],[26.361095,41.711052],[27.394997,42.008041]]]]}},{"type":"Feature","properties":{"name":"Tuvalu","iso2":"TV","iso3":"TUV"},"geometry":{"type":"MultiPolygon","coordinates":[[[[179.222366,-8.554146],[179.203705,-8.462443],[179.231094,-8.50492],[179.222366,-8.554146]]],[[[178.366913,-8.062778],[178.355804,-8.06139],[178.36969,-8.0275],[178.366913,-8.062778]]],[[[178.39776599999985,-8.015278],[178.39151,-8],[178.4030460000001,-7.991388],[178.39776599999985,-8.015278]]],[[[178.700531,-7.482223],[178.687469,-7.478889],[178.690796,-7.464445],[178.700531,-7.482223]]],[[[177.158875,-7.187778],[177.146362,-7.188611],[177.142212,-7.173611],[177.158875,-7.187778]]],[[[176.310242,-6.285556],[176.295258,-6.278056],[176.30886800000016,-6.257501],[176.310242,-6.285556]]],[[[177.295807,-6.113889],[177.28137200000012,-6.089444],[177.308868,-6.098889],[177.295807,-6.113889]]],[[[176.139709,-5.690556],[176.130249,-5.693333],[176.12939500000013,-5.675],[176.139709,-5.690556]]],[[[176.08136,-5.665277],[176.066376,-5.665277],[176.079407,-5.657778],[176.08136,-5.665277]]]]}},{"type":"Feature","properties":{"name":"Turkmenistan","iso2":"TM","iso3":"TKM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[53.069719314575195,38.89972114562988],[53.0786075592041,39.093881607055664],[53.10000038146973,38.751108169555664],[53.069719314575195,38.89972114562988]]],[[[58.78055000305176,42.65804481506348],[60.01444435119629,42.21749305725098],[60.140275955200195,41.38110542297363],[61.874162673950195,41.12555122375488],[62.551103591918945,39.934160232543945],[64.38302803039551,38.95312690734863],[66.64387702941895,38.00305366516113],[66.5377368927002,37.36638069152832],[65.7088794708252,37.53860664367676],[64.79803657531738,37.1249942779541],[64.50360298156738,36.28055000305176],[63.11944007873535,35.86194038391113],[63.10527229309082,35.45083045959473],[62.72221565246582,35.254716873168945],[62.309160232543945,35.14166450500488],[61.276559829711914,35.607248306274414],[61.15721321105957,36.64999580383301],[60.33305549621582,36.65609931945801],[59.338884353637695,37.53916358947754],[57.450273513793945,37.939157485961914],[57.21221351623535,38.281938552856445],[55.442766189575195,38.08610725402832],[54.681108474731445,37.44360542297363],[53.90564155578613,37.35085487365723],[53.9838809967041,38.91582679748535],[53.54138374328613,39.335824966430664],[53.162492752075195,39.175554275512695],[53.26416206359863,39.6552677154541],[53.73443794250488,39.523881912231445],[53.40832710266113,39.66582679748535],[53.57583045959473,39.96610450744629],[52.93471717834473,39.990549087524414],[53.004716873168945,39.762216567993164],[52.721933364868164,40.44610023498535],[52.91860389709473,41.08166694641113],[53.74638557434082,40.61527442932129],[54.41777229309082,40.7036075592041],[54.24471473693848,40.88027381896973],[54.7338809967041,41.10222053527832],[54.072771072387695,41.47554969787598],[53.80388069152832,42.12388038635254],[52.94665718078613,41.97304725646973],[52.81582832336426,41.69582557678223],[52.88193702697754,41.04722023010254],[52.440073013305664,41.74093818664551],[53.01500129699707,42.13888740539551],[54.173051834106445,42.33721351623535],[55.45694160461426,41.28666114807129],[56.00096321105957,41.32845497131348],[57.04471778869629,41.26027870178223],[56.98694038391113,41.89305305480957],[58.0266056060791,42.50464057922363],[58.51555061340332,42.3044376373291],[58.164438247680664,42.651933670043945],[58.78055000305176,42.65804481506348]]]]}},{"type":"Feature","properties":{"name":"United Republic of Tanzania","iso2":"TZ","iso3":"TZA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[39.682495,-7.993334],[39.591385,-7.945834],[39.901108,-7.638889],[39.682495,-7.993334]]],[[[39.4466630000002,-6.210556],[39.516106,-6.468612],[39.201385,-6.226945],[39.304161,-5.723889],[39.4466630000002,-6.210556]]],[[[39.736107,-5.462778],[39.676941,-4.941389],[39.857216,-4.908611],[39.736107,-5.462778]]],[[[31.677219,-0.999722],[33.920273,-1.001111],[37.602776,-2.995833],[37.613609,-3.504167],[39.20302600000011,-4.669618],[38.776382,-6.045556],[39.5478820000001,-6.994313],[39.274437,-7.579167],[39.387772,-8.9025],[39.8263850000001,-9.993057],[40.43681300000017,-10.478174],[39.268051000000156,-11.168056],[37.941383,-11.285002],[37.462044,-11.727329],[36.18972,-11.706667],[35.838333,-11.414722],[34.966728,-11.572111],[34.325272,-9.732779],[33.13472000000016,-9.494167],[32.940399,-9.405077],[31.041111,-8.590279],[30.77124000000012,-8.192247],[29.550278,-6.295279],[29.423885,-4.448056],[30.026108000000107,-4.269444],[30.83499900000018,-3.256945],[30.843662,-2.978794],[30.4175,-2.861945],[30.57333,-2.399167],[30.894165,-2.076111],[30.48222,-1.063334],[31.677219,-0.999722]]]]}},{"type":"Feature","properties":{"name":"Uganda","iso2":"UG","iso3":"UGA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[33.996666,4.222777000000136],[34.463333,3.671389],[35.0097200000001,1.895278],[33.907219,0.103056],[33.920273,-1.001111],[31.677219,-0.999722],[30.48222,-1.063334],[29.974998,-1.464445],[29.596943,-1.385834],[29.960552,0.825555],[31.302776,2.121388],[30.729721000000126,2.448055],[30.858818,3.493394000000137],[31.176666,3.795278],[32.193329,3.511389000000108],[33.016663,3.888611000000111],[33.516937,3.752222],[33.996666,4.222777000000136]]]]}},{"type":"Feature","properties":{"name":"United Kingdom","iso2":"GB","iso3":"GBR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-6.29083251953125,49.91221809387207],[-6.317499160766602,49.9152774810791],[-6.295000076293945,49.93388557434082],[-6.29083251953125,49.91221809387207]]],[[[-1.059720993041992,50.6874942779541],[-1.569999694824219,50.66055488586426],[-1.296943664550781,50.77194404602051],[-1.059720993041992,50.6874942779541]]],[[[-0.938331604003906,50.77749824523926],[-1.022499084472656,50.78582954406738],[-0.970832824707031,50.830827713012695],[-0.938331604003906,50.77749824523926]]],[[[-4.651666641235352,51.159440994262695],[-4.673334121704102,51.161386489868164],[-4.665555953979492,51.19500160217285],[-4.651666641235352,51.159440994262695]]],[[[-4.571388244628906,53.23861122131348],[-4.693889617919922,53.3013858795166],[-4.621665954589844,53.32139015197754],[-4.571388244628906,53.23861122131348]]],[[[-4.15333366394043,53.22555732727051],[-4.4022216796875,53.12583351135254],[-4.56916618347168,53.3880558013916],[-4.15333366394043,53.22555732727051]]],[[[-6.35333251953125,55.23777961730957],[-5.688055038452148,54.806108474731445],[-5.908332824707031,54.60472297668457],[-5.429721832275391,54.48360633850098],[-6.266975402832031,54.09983253479004],[-7.030834197998047,54.41777229309082],[-7.559444427490234,54.12693977355957],[-8.159444808959961,54.44194221496582],[-7.406389236450195,54.95333290100098],[-7.252506256103516,55.07059669494629],[-6.35333251953125,55.23777961730957]]],[[[-6.17277717590332,55.29305458068848],[-6.188333511352539,55.259721755981445],[-6.282499313354492,55.29222297668457],[-6.17277717590332,55.29305458068848]]],[[[-5.103610992431641,55.438608169555664],[-5.381111145019531,55.66861152648926],[-5.1602783203125,55.67916297912598],[-5.103610992431641,55.438608169555664]]],[[[-6.121665954589844,55.87888526916504],[-6.076665878295898,55.64999580383301],[-6.509166717529297,55.68222236633301],[-6.121665954589844,55.87888526916504]]],[[[-5.016387939453125,55.721940994262695],[-5.206388473510742,55.89943885803223],[-5.036388397216797,55.837778091430664],[-5.016387939453125,55.721940994262695]]],[[[-6.193889617919922,56.02916145324707],[-6.263055801391602,56.03611183166504],[-6.130832672119141,56.12082862854004],[-6.193889617919922,56.02916145324707]]],[[[-5.946945190429688,55.82999610900879],[-6.078887939453125,55.90555000305176],[-5.69444465637207,56.14721870422363],[-5.946945190429688,55.82999610900879]]],[[[-5.735000610351563,56.15805244445801],[-5.675277709960938,56.19194221496582],[-5.675832748413086,56.169443130493164],[-5.735000610351563,56.15805244445801]]],[[[-5.629999160766602,56.19693946838379],[-5.641944885253906,56.26027870178223],[-5.606388092041016,56.25444221496582],[-5.629999160766602,56.19693946838379]]],[[[-5.616666793823242,56.26888465881348],[-5.64555549621582,56.30111122131348],[-5.583889007568359,56.319719314575195],[-5.616666793823242,56.26888465881348]]],[[[-6.404722213745117,56.303606033325195],[-6.43638801574707,56.310556411743164],[-6.38194465637207,56.340829849243164],[-6.404722213745117,56.303606033325195]]],[[[-5.543611526489258,56.38277626037598],[-5.587778091430664,56.38916206359863],[-5.510000228881836,56.41111183166504],[-5.543611526489258,56.38277626037598]]],[[[-6.16583251953125,56.46472358703613],[-6.260000228881836,56.481943130493164],[-6.215555191040039,56.49777412414551],[-6.16583251953125,56.46472358703613]]],[[[-6.739166259765625,56.51583290100098],[-6.892778396606445,56.438608169555664],[-6.990833282470703,56.49444007873535],[-6.739166259765625,56.51583290100098]]],[[[-5.783611297607422,56.50889015197754],[-5.648332595825195,56.43583106994629],[-5.808610916137695,56.3174991607666],[-6.366111755371094,56.30888557434082],[-6.017778396606445,56.37471961975098],[-6.193611145019531,56.36138343811035],[-6.002777099609375,56.49416542053223],[-6.319999694824219,56.60305213928223],[-5.783611297607422,56.50889015197754]]],[[[-6.589166641235352,56.57999610900879],[-6.698888778686523,56.57999610900879],[-6.454444885253906,56.686105728149414],[-6.589166641235352,56.57999610900879]]],[[[-6.144721984863281,56.86999702453613],[-6.213054656982422,56.90694618225098],[-6.113611221313477,56.93249702453613],[-6.144721984863281,56.86999702453613]]],[[[-6.317499160766602,56.93416786193848],[-6.451665878295898,57.00610542297363],[-6.261667251586914,57.03777503967285],[-6.317499160766602,56.93416786193848]]],[[[-7.466943740844727,56.94082832336426],[-7.559999465942383,56.960275650024414],[-7.439722061157227,57.05444526672363],[-7.466943740844727,56.94082832336426]]],[[[-6.499166488647461,57.05221748352051],[-6.602500915527344,57.04638862609863],[-6.549444198608398,57.06805610656738],[-6.499166488647461,57.05221748352051]]],[[[-5.939167022705078,57.27805519104004],[-6.017778396606445,57.311662673950195],[-5.933889389038086,57.311662673950195],[-5.939167022705078,57.27805519104004]]],[[[-7.223054885864258,57.33749580383301],[-7.381389617919922,57.10860633850098],[-7.424999237060547,57.382219314575195],[-7.223054885864258,57.33749580383301]]],[[[-7.268888473510742,57.39888954162598],[-7.406389236450195,57.46416664123535],[-7.204721450805664,57.460832595825195],[-7.268888473510742,57.39888954162598]]],[[[-6.026945114135742,57.3286075592041],[-6.078332901000977,57.39416694641113],[-5.979999542236328,57.49582862854004],[-6.026945114135742,57.3286075592041]]],[[[-6.143888473510742,57.56805610656738],[-6.127222061157227,57.306108474731445],[-5.663888931274414,57.20499610900879],[-6.011943817138672,57.02221870422363],[-6.785833358764648,57.44610786437988],[-6.143888473510742,57.56805610656738]]],[[[-5.967777252197266,57.522775650024414],[-5.990833282470703,57.54083442687988],[-5.961666107177734,57.57499885559082],[-5.967777252197266,57.522775650024414]]],[[[-7.18861198425293,57.68721961975098],[-7.153888702392578,57.50943946838379],[-7.543333053588867,57.590829849243164],[-7.18861198425293,57.68721961975098]]],[[[-7.196666717529297,57.702219009399414],[-7.219165802001953,57.707773208618164],[-7.144721984863281,57.72361183166504],[-7.196666717529297,57.702219009399414]]],[[[-8.555278778076172,57.81083106994629],[-8.582500457763672,57.79888343811035],[-8.621389389038086,57.82277870178223],[-8.555278778076172,57.81083106994629]]],[[[-7.006389617919922,57.88138771057129],[-7.077777862548828,57.8799991607666],[-6.993610382080078,57.91861152648926],[-7.006389617919922,57.88138771057129]]],[[[-6.204166412353516,58.35611152648926],[-6.473888397216797,57.94027900695801],[-7.123056411743164,57.8174991607666],[-6.830278396606445,57.900835037231445],[-7.040555953979492,58.23333168029785],[-6.204166412353516,58.35611152648926]],[[-6.802221298217773,58.20305061340332],[-6.88972282409668,58.25249671936035],[-6.869167327880859,58.20388984680176],[-6.802221298217773,58.20305061340332]]],[[[-4.15333366394043,53.22555732727051],[-2.702499389648438,53.346384048461914],[-3.107500076293945,53.55166816711426],[-2.81361198425293,54.2227725982666],[-3.226110458374023,54.09861183166504],[-3.634166717529297,54.51194190979004],[-3.023056030273438,54.97055244445801],[-4.393054962158203,54.90805244445801],[-4.387222290039063,54.675554275512695],[-4.852222442626953,54.868608474731445],[-4.941110610961914,54.64888954162598],[-5.174165725708008,55.00055122375488],[-4.613332748413086,55.49499702453613],[-4.879722595214844,55.936105728149414],[-4.481668472290039,55.92110633850098],[-4.828605651855469,56.1131649017334],[-5.303333282470703,55.85055732727051],[-5.032222747802734,56.232500076293945],[-5.777500152587891,55.29666328430176],[-5.573610305786133,56.324716567993164],[-5.107778549194336,56.50777626037598],[-5.398666381835938,56.47866630554199],[-5.120000839233398,56.816667556762695],[-5.676944732666016,56.4938907623291],[-6.008333206176758,56.63749885559082],[-5.546943664550781,56.69194221496582],[-6.235000610351563,56.71916389465332],[-5.399723052978516,57.1058292388916],[-5.64961051940918,57.161611557006836],[-5.450277328491211,57.42027473449707],[-5.81916618347168,57.3638858795166],[-5.508611679077148,57.53472328186035],[-5.816667556762695,57.821664810180664],[-5.102777481079102,57.85083198547363],[-5.455278396606445,58.07638740539551],[-5.004722595214844,58.62333106994629],[-3.025554656982422,58.64750099182129],[-3.208610534667969,58.30444526672363],[-4.392221450805664,57.90527534484863],[-3.773056030273438,57.85110664367676],[-4.435832977294922,57.57499885559082],[-2.075555801391602,57.69944190979004],[-1.773332595825195,57.45805549621582],[-2.5272216796875,56.5786075592041],[-3.278055191040039,56.357500076293945],[-2.58277702331543,56.26805305480957],[-3.725276947021484,56.02749824523926],[-2.631111145019531,56.05471992492676],[-1.633888244628906,55.580827713012695],[-1.29749870300293,54.76361274719238],[-0.07499885559082,54.11194038391113],[0.11805534362793,53.56443977355957],[-0.718889236450195,53.699716567993164],[0.235555648803711,53.39943885803223],[0.341669082641602,53.095834732055664],[0.000036239624023,52.87954902648926],[1.282224655151367,52.927499771118164],[1.749444961547852,52.455827713012695],[1.223611831665039,51.80888557434082],[0.699724197387695,51.71944618225098],[0.950555801391602,51.60638618469238],[0.382780075073242,51.4505558013916],[1.385557174682617,51.387773513793945],[0.975000381469727,50.93194007873535],[0.242223739624023,50.738054275512695],[-0.254999160766602,50.82638740539551],[-0.796388626098633,50.72527503967285],[-0.926942825317383,50.83944129943848],[-1.154722213745117,50.84416389465332],[-2.434450149536133,50.541791915893555],[-2.924722671508789,50.731943130493164],[-3.716667175292969,50.20666694641113],[-4.379999160766602,50.3638858795166],[-5.193056106567383,49.955278396606445],[-5.712499618530273,50.053606033325195],[-4.226388931274414,51.189165115356445],[-3.02833366394043,51.20611000061035],[-2.379999160766602,51.75555610656738],[-3.346111297607422,51.378610610961914],[-5.246944427490234,51.73027229309082],[-4.130832672119141,52.33471870422363],[-4.133611679077148,52.914445877075195],[-4.760862350463867,52.78897285461426],[-4.15333366394043,53.22555732727051]],[[0.904722213745117,51.35805702209473],[0.908891677856445,51.416940689086914],[0.735002517700195,51.408334732055664],[0.904722213745117,51.35805702209473]]],[[[-2.918333053588867,58.731943130493164],[-3.036945343017578,58.81805610656738],[-2.886388778686523,58.83194160461426],[-2.918333053588867,58.731943130493164]]],[[[-3.231388092041016,58.77555274963379],[-3.418054580688477,58.90416145324707],[-3.134721755981445,58.80082893371582],[-3.231388092041016,58.77555274963379]]],[[[-2.793054580688477,58.95138740539551],[-3.194999694824219,58.91111183166504],[-3.351388931274414,59.10638618469238],[-2.793054580688477,58.95138740539551]]],[[[-2.681388854980469,59.19583320617676],[-2.55555534362793,59.303056716918945],[-2.390277862548828,59.28305244445801],[-2.681388854980469,59.19583320617676]]],[[[-2.889999389648438,59.29527473449707],[-2.877498626708984,59.22860908508301],[-3.076389312744141,59.33138465881348],[-2.889999389648438,59.29527473449707]]],[[[-1.296110153198242,60.491106033325195],[-1.037221908569336,60.444162368774414],[-1.268610000610352,59.85110664367676],[-1.291389465332031,60.24138832092285],[-1.693056106567383,60.27971839904785],[-1.296110153198242,60.491106033325195]]],[[[-1.029443740844727,60.49582862854004],[-1.170276641845703,60.52722358703613],[-1.098609924316406,60.729997634887695],[-1.029443740844727,60.49582862854004]]],[[[-0.819721221923828,60.68889045715332],[-0.965555191040039,60.68805122375488],[-0.878332138061523,60.84444618225098],[-0.758054733276367,60.81777381896973],[-0.819721221923828,60.68889045715332]]]]}},{"type":"Feature","properties":{"name":"Ukraine","iso2":"UA","iso3":"UKR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[33.040276000000205,46.011375],[32.759438,46.036110000000136],[32.965271,46.049431],[33.040276000000205,46.011375]]],[[[34.227486,46.061928],[34.158043000000106,46.100548],[34.229149,46.187759000000156],[34.227486,46.061928]]],[[[32.16776300000018,46.14582100000011],[31.584164,46.253319],[31.501106000000135,46.366653],[32.16776300000018,46.14582100000011]]],[[[33.41770200000022,52.3554],[33.838882,52.36055],[34.419716,51.808884],[34.098045000000155,51.65387700000015],[34.38221,51.263611],[35.37188700000016,51.041435],[35.606651,50.369438],[37.458603000000124,50.439713],[38.024223,49.903084],[38.30777,50.073883],[40.13976300000016,49.601051],[40.16693900000021,49.248604],[39.69665500000016,49.010826],[40.07666,48.87499200000012],[39.656937,48.616661],[39.998878,48.297218],[39.796387,47.857216],[38.853600000000114,47.860825],[38.303322,47.558594],[38.23582500000012,47.109428],[35.907204,46.65109300000013],[34.98526800000016,46.075829],[35.198044,46.443314],[35.05304,46.258041],[34.702492,46.175819],[34.561661000000214,45.984993],[34.401649000000106,46.013878],[34.542496,46.187485],[33.671928,46.220818],[34.63332400000016,45.94165],[34.46054100000012,45.7672120000001],[35.126656,45.326096],[35.34304,45.332497],[35.050262,45.613884],[34.763054,46.01554900000012],[34.666939,46.093597],[34.82720900000018,46.069443],[35.05387900000014,45.65387],[35.311661,45.38304100000012],[35.475266,45.29110000000016],[36.637215,45.376099],[36.439713,45.065536],[35.515266,45.116096],[33.955544000000174,44.38110400000012],[33.366936,44.579163],[33.54193900000021,45.111931],[32.48053700000017,45.395821],[33.771935,45.920540000000116],[33.611382,46.14721700000017],[31.791943000000146,46.2830510000001],[32.05915100000013,46.395821],[31.507771,46.57972],[32.647217,46.641106],[32.019707,46.629433000000134],[31.749435,47.25331900000013],[31.907494000000185,46.648872],[30.832771,46.548325],[30.25165900000016,45.876656],[29.746941000000135,45.619431],[29.633606,45.821106000000114],[29.664331,45.211803],[28.21484,45.448647],[28.971935,46.006653],[28.994434,46.47832500000011],[30.11694,46.386101],[29.949997,46.814156],[29.184441,47.443047],[29.141937000000155,47.98609200000014],[27.755554,48.451385],[26.634995,48.257164],[24.91944100000012,47.711662],[22.894804,47.95454],[22.151442,48.411919],[22.558052,49.079437],[22.886074,49.002914],[22.680828000000105,49.572495],[24.111385,50.56694],[23.604633,51.527695],[24.396664,51.886658],[25.775829000000158,51.939156],[30.551414000000108,51.251846],[30.94309600000011,52.073792000000125],[31.783886,52.108047],[33.41770200000022,52.3554]]]]}},{"type":"Feature","properties":{"name":"United States","iso2":"US","iso3":"USA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-75.1702880859375,19.9313907623291],[-75.22372436523438,19.90155601501465],[-75.1591796875,19.960695266723633],[-75.1702880859375,19.9313907623291]]],[[[-75.12139892578125,19.88749885559082],[-75.13973999023438,19.962873458862305],[-75.08528137207031,19.893041610717773],[-75.12139892578125,19.88749885559082]]],[[[-155.00558471679688,19.328882217407227],[-155.85946655273438,19.032777786254883],[-155.86444091796875,20.269163131713867],[-155.15863037109375,19.962495803833008],[-154.79281616210938,19.538610458374023],[-155.00558471679688,19.328882217407227]]],[[[-156.5472412109375,20.5252742767334],[-156.69863891601562,20.534719467163086],[-156.58529663085938,20.607221603393555],[-156.5472412109375,20.5252742767334]]],[[[-156.89199829101562,20.74416160583496],[-157.04837036132812,20.918054580688477],[-156.812255859375,20.843610763549805],[-156.89199829101562,20.74416160583496]]],[[[-156.47335815429688,20.89805030822754],[-155.98861694335938,20.7480525970459],[-156.42001342773438,20.58860969543457],[-156.70223999023438,20.924436569213867],[-156.47335815429688,20.89805030822754]]],[[[-156.89447021484375,21.161104202270508],[-156.70391845703125,21.158052444458008],[-157.30474853515625,21.100553512573242],[-156.89447021484375,21.161104202270508]]],[[[-160.53060913085938,21.643888473510742],[-160.53778076171875,21.63221549987793],[-160.5411376953125,21.641382217407227],[-160.53060913085938,21.643888473510742]]],[[[-157.73031616210938,21.41166114807129],[-158.1036376953125,21.295278549194336],[-158.27337646484375,21.580549240112305],[-157.971923828125,21.699438095092773],[-157.73031616210938,21.41166114807129]]],[[[-160.114990234375,21.88749885559082],[-160.24777221679688,21.813608169555664],[-160.0614013671875,22.013883590698242],[-160.114990234375,21.88749885559082]]],[[[-159.43362426757812,21.88138771057129],[-159.78530883789062,22.061384201049805],[-159.35165405273438,22.22138023376465],[-159.43362426757812,21.88138771057129]]],[[[-161.94168090820312,23.039438247680664],[-161.94833374023438,23.047216415405273],[-161.93832397460938,23.046388626098633],[-161.94168090820312,23.039438247680664]]],[[[-164.69613647460938,23.56471824645996],[-164.70751953125,23.5766658782959],[-164.69668579101562,23.578054428100586],[-164.69613647460938,23.56471824645996]]],[[[-81.77389526367188,24.544721603393555],[-81.8134994506836,24.54387092590332],[-81.72917175292969,24.560556411743164],[-81.77389526367188,24.544721603393555]]],[[[-82.11444091796875,24.54583168029785],[-82.13722229003906,24.593889236450195],[-82.09999084472656,24.58305549621582],[-82.11444091796875,24.54583168029785]]],[[[-81.71511840820312,24.553117752075195],[-81.71073913574219,24.595720291137695],[-81.64622497558594,24.577550888061523],[-81.71511840820312,24.553117752075195]]],[[[-81.47721862792969,24.636384963989258],[-81.51777458190918,24.684995651245117],[-81.47860717773438,24.67777442932129],[-81.47721862792969,24.636384963989258]]],[[[-81.58833312988281,24.589998245239258],[-81.55305480957031,24.687219619750977],[-81.50834655761719,24.6299991607666],[-81.58833312988281,24.589998245239258]]],[[[-81.10861206054688,24.706106185913086],[-81.13777160644531,24.70168113708496],[-81.05267333984375,24.71653175354004],[-81.10861206054688,24.706106185913086]]],[[[-81.34944152832031,24.62972068786621],[-81.42805480957031,24.748605728149414],[-81.36082458496094,24.700830459594727],[-81.34944152832031,24.62972068786621]]],[[[-80.96888732910156,24.742773056030273],[-81.02668762207031,24.71858787536621],[-80.9234619140625,24.769208908081055],[-80.96888732910156,24.742773056030273]]],[[[-80.84611511230469,24.79749870300293],[-80.82417297363281,24.82111167907715],[-80.78617095947266,24.82293128967285],[-80.84611511230469,24.79749870300293]]],[[[-80.6986083984375,24.866666793823242],[-80.74583435058594,24.842496871948242],[-80.70249938964844,24.880830764770508],[-80.6986083984375,24.866666793823242]]],[[[-80.64666557312012,24.902219772338867],[-80.66444396972656,24.89499855041504],[-80.62388610839844,24.932775497436523],[-80.64666557312012,24.902219772338867]]],[[[-167.99057006835938,25.002500534057617],[-168.00115966796875,25.00388526916504],[-168.00588989257812,25.01749610900879],[-167.99057006835938,25.002500534057617]]],[[[-80.57722473144531,24.9455509185791],[-80.25750732421875,25.34638786315918],[-80.37193298339844,25.143888473510742],[-80.57722473144531,24.9455509185791]]],[[[-80.22500610351562,25.40110969543457],[-80.23416137695312,25.402219772338867],[-80.1885986328125,25.49416160583496],[-80.22500610351562,25.40110969543457]]],[[[-80.16221618652344,25.669443130493164],[-80.185546875,25.68943977355957],[-80.15638732910156,25.73333168029785],[-80.16221618652344,25.669443130493164]]],[[[-171.72360229492188,25.76249885559082],[-171.73138427734375,25.760831832885742],[-171.72470092773438,25.791662216186523],[-171.72360229492188,25.76249885559082]]],[[[-81.68415832519531,25.8447208404541],[-81.7147216796875,25.888608932495117],[-81.66416931152344,25.888608932495117],[-81.68415832519531,25.8447208404541]]],[[[-173.94613647460938,26.06333351135254],[-173.96084594726562,26.079439163208008],[-173.94473266601562,26.08083152770996],[-173.94613647460938,26.06333351135254]]],[[[-82.12638854980469,26.44999885559082],[-82.20639038085938,26.54583168029785],[-82.02888488769531,26.444997787475586],[-82.12638854980469,26.44999885559082]]],[[[-82.22166442871094,26.612497329711914],[-82.2449951171875,26.63499641418457],[-82.2550048828125,26.698606491088867],[-82.22166442871094,26.612497329711914]]],[[[-82.07945251464844,26.487775802612305],[-82.17971801757812,26.69916343688965],[-82.13333129882812,26.69110679626465],[-82.07945251464844,26.487775802612305]]],[[[-82.26362609863281,26.716386795043945],[-82.28138732910156,26.808889389038086],[-82.25527954101562,26.759443283081055],[-82.26362609863281,26.716386795043945]]],[[[-97.17778015136719,26.0847225189209],[-97.38575744628906,26.838224411010742],[-97.38362121582031,27.20722007751465],[-97.17778015136719,26.0847225189209]]],[[[-82.58750915527344,27.32111167907715],[-82.68055725097656,27.42582893371582],[-82.6541748046875,27.418607711791992],[-82.58750915527344,27.32111167907715]]],[[[-97.38221740722656,27.21888542175293],[-97.31723022460938,27.49582862854004],[-97.04554557800293,27.843889236450195],[-97.38221740722656,27.21888542175293]]],[[[-96.88778686523438,28.030553817749023],[-97.03582763671875,27.875276565551758],[-96.86776733398438,28.13499641418457],[-96.88778686523438,28.030553817749023]]],[[[-96.55194091796875,28.26666831970215],[-96.81361389160156,28.092496871948242],[-96.40472412109375,28.392221450805664],[-96.55194091796875,28.26666831970215]]],[[[-96.36082458496094,28.402498245239258],[-96.31304931640625,28.45527458190918],[-96.22999572753906,28.485551834106445],[-96.36082458496094,28.402498245239258]]],[[[-80.66389465332031,28.258333206176758],[-80.74028015136719,28.478330612182617],[-80.62527465820312,28.59055519104004],[-80.66389465332031,28.258333206176758]]],[[[-90.87265014648438,29.046133041381836],[-90.95039367675781,29.06000328063965],[-90.92361450195312,29.060556411743164],[-90.87265014648438,29.046133041381836]]],[[[-90.73916625976562,29.045000076293945],[-90.75834655761719,29.048608779907227],[-90.64250183105469,29.073331832885742],[-90.73916625976562,29.045000076293945]]],[[[-90.33555603027344,29.057222366333008],[-90.2852783203125,29.08305549621582],[-90.29833984375,29.06694221496582],[-90.33555603027344,29.057222366333008]]],[[[-89.97528076171875,29.242773056030273],[-90.03111267089844,29.211942672729492],[-89.95500183105469,29.268056869506836],[-89.97528076171875,29.242773056030273]]],[[[-89.92832946777344,29.27861213684082],[-89.93527221679688,29.287500381469727],[-89.90750122070312,29.302221298217773],[-89.92832946777344,29.27861213684082]]],[[[-89.86000061035156,29.310277938842773],[-89.89389038085938,29.32305335998535],[-89.86972045898438,29.335275650024414],[-89.86000061035156,29.310277938842773]]],[[[-95.11111450195312,29.098054885864258],[-94.82139587402344,29.33860969543457],[-94.78472900390625,29.308053970336914],[-95.11111450195312,29.098054885864258]]],[[[-89.17054557800293,29.473051071166992],[-89.21916198730469,29.464719772338867],[-89.15695190429688,29.492494583129883],[-89.17054557800293,29.473051071166992]]],[[[-89.60110473632812,29.513887405395508],[-89.61833190917969,29.538331985473633],[-89.59028625488281,29.560556411743164],[-89.56582641601562,29.554719924926758],[-89.56221008300781,29.5211124420166],[-89.60110473632812,29.513887405395508]]],[[[-89.08029174804688,29.521387100219727],[-89.07888793945312,29.54555320739746],[-89.03721618652344,29.573610305786133],[-89.08029174804688,29.521387100219727]]],[[[-91.78666687011719,29.486108779907227],[-92.03443908691406,29.591665267944336],[-91.85638427734375,29.63499641418457],[-91.78666687011719,29.486108779907227]]],[[[-85.11111450195312,29.632219314575195],[-85.19804382324219,29.685274124145508],[-85.08168029785156,29.679162979125977],[-85.11111450195312,29.632219314575195]]],[[[-89.42860412597656,29.692773818969727],[-89.46861267089844,29.728609085083008],[-89.42250061035156,29.7227725982666],[-89.42860412597656,29.692773818969727]]],[[[-84.9727783203125,29.608888626098633],[-85.09500122070312,29.62388801574707],[-84.69221496582031,29.758333206176758],[-84.9727783203125,29.608888626098633]]],[[[-89.42416381835938,29.74083137512207],[-89.4888916015625,29.73805046081543],[-89.49110412597656,29.793054580688477],[-89.42416381835938,29.74083137512207]]],[[[-89.2852783203125,29.771387100219727],[-89.3416748046875,29.80388832092285],[-89.27555847167969,29.80916404724121],[-89.2852783203125,29.771387100219727]]],[[[-84.63890075683594,29.77833366394043],[-84.66722106933594,29.776945114135742],[-84.57342529296875,29.819997787475586],[-84.63890075683594,29.77833366394043]]],[[[-88.84584045410156,29.77638816833496],[-88.86874389648438,30.060606002807617],[-88.80583190917969,29.90638542175293],[-88.84584045410156,29.77638816833496]]],[[[-89.31777954101562,30.040834426879883],[-89.34638977050781,30.0594425201416],[-89.18499755859375,30.16666603088379],[-89.31777954101562,30.040834426879883]]],[[[-88.43777465820312,30.206106185913086],[-88.50056457519531,30.21888542175293],[-88.42805480957031,30.2127742767334],[-88.43777465820312,30.206106185913086]]],[[[-88.55221557617188,30.214719772338867],[-88.75418090820312,30.244718551635742],[-88.52639770507812,30.223051071166992],[-88.55221557617188,30.214719772338867]]],[[[-89.08111572265625,30.19972038269043],[-89.0916748046875,30.216665267944336],[-89.06051635742188,30.246675491333008],[-89.08111572265625,30.19972038269043]]],[[[-88.0947265625,30.241106033325195],[-88.3125,30.23277473449707],[-88.10777282714844,30.273611068725586],[-88.0947265625,30.241106033325195]]],[[[-86.5291748046875,30.40083122253418],[-87.29222106933594,30.33277702331543],[-86.7630615234375,30.404996871948242],[-86.5291748046875,30.40083122253418]]],[[[-118.40695190429688,32.816667556762695],[-118.59249877929688,33.046945571899414],[-118.3691635131836,32.85471534729004],[-118.40695190429688,32.816667556762695]]],[[[-79.36500358581543,33.00305366516113],[-79.36111450195312,33.049997329711914],[-79.33612060546875,33.067216873168945],[-79.36500358581543,33.00305366516113]]],[[[-119.44415283203125,33.21666145324707],[-119.5666732788086,33.28277015686035],[-119.48056030273438,33.27443885803223],[-119.44415283203125,33.21666145324707]]],[[[-118.30194091796875,33.30943489074707],[-118.44888305664062,33.32749366760254],[-118.59221458435059,33.48665809631348],[-118.30194091796875,33.30943489074707]]],[[[-77.96083068847656,33.85000038146973],[-78.01640319824219,33.874162673950195],[-77.94972229003906,33.91304969787598],[-77.96083068847656,33.85000038146973]]],[[[-120.0352783203125,34.023881912231445],[-120.10749816894531,33.90555000305176],[-120.2260971069336,34.00610542297363],[-120.0352783203125,34.023881912231445]]],[[[-120.29778289794922,34.02860450744629],[-120.43804931640625,34.036943435668945],[-120.3638916015625,34.0655460357666],[-120.29778289794922,34.02860450744629]]],[[[-119.86805725097656,34.08416175842285],[-119.51363372802734,34.04277229309082],[-119.788330078125,33.96721076965332],[-119.86805725097656,34.08416175842285]]],[[[-76.5352783203125,34.63555335998535],[-76.65472412109375,34.686105728149414],[-76.55915832519531,34.664995193481445],[-76.5352783203125,34.63555335998535]]],[[[-76.6824951171875,34.702219009399414],[-77.09805297851562,34.65054512023926],[-76.93110656738281,34.69137763977051],[-76.6824951171875,34.702219009399414]]],[[[-76.53195190429688,34.585824966430664],[-76.42083740234375,34.775827407836914],[-76.19972229003906,34.941659927368164],[-76.53195190429688,34.585824966430664]]],[[[-76.06777954101562,35.039438247680664],[-76.131103515625,35.00193977355957],[-76.03944396972656,35.061105728149414],[-76.06777954101562,35.039438247680664]]],[[[-76.01083374023438,35.074167251586914],[-75.98110961914062,35.114999771118164],[-75.76695251464844,35.19388008117676],[-76.01083374023438,35.074167251586914]]],[[[-75.5272216796875,35.235551834106445],[-75.65361022949219,35.22554969787598],[-75.51251220703125,35.7772159576416],[-75.5272216796875,35.235551834106445]]],[[[-75.61944580078125,35.82138252258301],[-75.72332763671875,35.941659927368164],[-75.66583251953125,35.92694282531738],[-75.61944580078125,35.82138252258301]]],[[[-75.90611267089844,37.112497329711914],[-75.89889526367188,37.13694190979004],[-75.87249755859375,37.1491641998291],[-75.90611267089844,37.112497329711914]]],[[[-75.788330078125,37.238046646118164],[-75.83750915527344,37.22776985168457],[-75.7852783203125,37.29860877990723],[-75.788330078125,37.238046646118164]]],[[[-75.6966552734375,37.40277290344238],[-75.71083068847656,37.390275955200195],[-75.6683349609375,37.460275650024414],[-75.6966552734375,37.40277290344238]]],[[[-121.8013916015625,38.05526924133301],[-121.82000732421875,38.06805610656738],[-121.79638671875,38.066667556762695],[-121.8013916015625,38.05526924133301]]],[[[-75.35417175292969,37.86666297912598],[-75.38417053222656,37.87221717834473],[-75.12110900878906,38.2630558013916],[-75.35417175292969,37.86666297912598]]],[[[-74.32945251464844,39.42166328430176],[-74.39445495605469,39.38249397277832],[-74.44415283203125,39.406938552856445],[-74.37625122070312,39.42074394226074],[-74.34805297851562,39.474435806274414],[-74.32945251464844,39.42166328430176]]],[[[-74.2469482421875,39.52555274963379],[-74.09999084472656,39.75083351135254],[-74.13833618164062,39.659433364868164],[-74.2469482421875,39.52555274963379]]],[[[-74.22000122070312,40.511667251586914],[-74.17694091796875,40.64193916320801],[-74.06277465820312,40.63943672180176],[-74.22000122070312,40.511667251586914]]],[[[-73.22332763671875,40.635271072387695],[-73.29472351074219,40.63388252258301],[-72.76666259765625,40.7661075592041],[-73.22332763671875,40.635271072387695]]],[[[-72.26222229003906,41.12526893615723],[-72.62110900878906,40.91304969787598],[-71.85610961914062,41.069162368774414],[-73.58277893066406,40.59610176086426],[-74.03250122070312,40.62582588195801],[-72.26222229003906,41.12526893615723]]],[[[-69.9949951171875,41.32805061340332],[-69.99388122558594,41.25027656555176],[-70.23416137695312,41.28360939025879],[-69.9949951171875,41.32805061340332]]],[[[-70.50639343261719,41.35721778869629],[-70.83805847167969,41.359994888305664],[-70.61721801757812,41.47387886047363],[-70.50639343261719,41.35721778869629]]],[[[-71.29750061035156,41.45860481262207],[-71.35833740234375,41.45916175842285],[-71.22250366210938,41.65416145324707],[-71.29750061035156,41.45860481262207]]],[[[-68.80332946777344,44.048051834106445],[-68.89805603027344,44.12388038635254],[-68.76445007324219,44.09499549865723],[-68.80332946777344,44.048051834106445]]],[[[-68.65083312988281,44.16888618469238],[-68.72138977050781,44.2288761138916],[-68.66806030273438,44.2852725982666],[-68.65083312988281,44.16888618469238]]],[[[-68.32084655761719,44.23721504211426],[-68.42832946777344,44.31999397277832],[-68.2630615234375,44.452775955200195],[-68.1683349609375,44.34554481506348],[-68.32084655761719,44.23721504211426]]],[[[-123.93804931640625,46.431108474731445],[-123.94915771484375,46.431108474731445],[-123.98306274414062,46.46915626525879],[-123.97250366210938,46.515275955200195],[-123.93804931640625,46.431108474731445]]],[[[-122.84306335449219,47.20694160461426],[-122.9022216796875,47.297494888305664],[-122.84555053710938,47.3124942779541],[-122.84306335449219,47.20694160461426]]],[[[-122.48222351074219,47.34971809387207],[-122.4505615234375,47.518327713012695],[-122.381103515625,47.39471626281738],[-122.48222351074219,47.34971809387207]]],[[[-122.50473022460938,48.30971717834473],[-122.37222290039062,47.919443130493164],[-122.75778198242188,48.2338809967041],[-122.50473022460938,48.30971717834473]]],[[[-122.8166732788086,48.416940689086914],[-122.93611145019531,48.457773208618164],[-122.87666320800781,48.564157485961914],[-122.8166732788086,48.416940689086914]]],[[[-123,48.44610023498535],[-123.17832946777344,48.59221839904785],[-122.99500274658203,48.52971839904785],[-123,48.44610023498535]]],[[[-122.92250061035156,48.7116641998291],[-122.74916076660156,48.651384353637695],[-123.0102767944336,48.60360908508301],[-122.92250061035156,48.7116641998291]]],[[[-123.05332946777344,48.97387886047363],[-123.09375,48.99943733215332],[-123.03431701660156,48.99943733215332],[-123.05332946777344,48.97387886047363]]],[[[-95.07806396484375,49.35916328430176],[-94.6058349609375,48.724435806274414],[-92.95306396484375,48.62332344055176],[-91.4183349609375,48.04110908508301],[-90.86860656738281,48.237497329711914],[-89.35665893554688,47.97971534729004],[-88.36805725097656,48.312211990356445],[-84.85694885253906,46.9022159576416],[-84.56500244140625,46.466386795043945],[-84.12638854980469,46.531938552856445],[-83.95889282226562,46.071664810180664],[-83.57749938964844,46.10527229309082],[-83.5977783203125,45.827219009399414],[-82.54306030273438,45.3558292388916],[-82.13027954101562,43.58526802062988],[-82.52139282226562,42.61888313293457],[-83.16860961914062,42.04610633850098],[-82.6966552734375,41.68387794494629],[-78.9869384765625,42.81999397277832],[-79.18472290039062,43.46554756164551],[-78.72471618652344,43.62943458557129],[-76.80194091796875,43.63360786437988],[-74.99082946777344,44.98665809631348],[-70.87860107421875,45.238603591918945],[-69.23249816894531,47.47137641906738],[-67.79499816894531,47.06999397277832],[-67.79916381835938,45.70110511779785],[-67.20654296875,45.18303871154785],[-66.96888732910156,44.83111000061035],[-67.18693542480469,44.661935806274414],[-67.55110168457031,44.66610145568848],[-67.56527709960938,44.55027198791504],[-67.77528381347656,44.546945571899414],[-68.04750061035156,44.346940994262695],[-68.10861206054688,44.460275650024414],[-68.32115173339844,44.46588325500488],[-68.55915832519531,44.41888618469238],[-68.54750061035156,44.31777381896973],[-68.61582946777344,44.30638313293457],[-68.79527282714844,44.579721450805664],[-69.0675048828125,44.06332588195801],[-69.72193908691406,43.78582954406738],[-69.77333068847656,44.07916450500488],[-69.82389831542969,43.71444129943848],[-70.17250061035156,43.78055000305176],[-70.72917175292969,43.12276649475098],[-70.58056640625,42.651933670043945],[-71.04444885253906,42.311105728149414],[-70.32472229003906,41.711381912231445],[-70.01112365722656,41.79722023010254],[-70.07888793945312,42.062211990356445],[-69.93638610839844,41.669443130493164],[-71.18582153320312,41.46666145324707],[-71.11111450195312,41.795000076293945],[-71.39138793945312,41.81193733215332],[-71.50527954101562,41.3669376373291],[-72.90638732910156,41.28611183166504],[-73.99748992919922,40.71346092224121],[-73.9566650390625,41.30526924133301],[-74.2691650390625,40.47471046447754],[-73.95222473144531,40.299997329711914],[-74.07640075683594,39.77694129943848],[-74.05387878417969,40.05749702453613],[-74.15028381347656,39.70499610900879],[-74.40556335449219,39.5161075592041],[-74.46259307861328,39.42106819152832],[-74.41555786132812,39.35527229309082],[-74.95500183105469,38.92416572570801],[-74.89277458190918,39.16777229309082],[-75.5574951171875,39.618051528930664],[-75.02851867675781,40.01230812072754],[-75.58860778808594,39.648881912231445],[-75.04388427734375,38.42166328430176],[-75.96083068847656,37.1522159576416],[-75.64404296875,37.9611759185791],[-75.88082885742188,37.94943428039551],[-75.83805847167969,38.398881912231445],[-76.24249267578125,38.3669376373291],[-75.9566650390625,38.64860725402832],[-76.36000061035156,38.85721778869629],[-75.83168029785156,39.57749366760254],[-76.61860656738281,39.254167556762695],[-76.3760986328125,38.36361122131348],[-76.66610717773438,38.480546951293945],[-76.30999755859375,38.04638862609863],[-77.24444580078125,38.398332595825195],[-77.06111145019531,38.9052677154541],[-77.32000732421875,38.34527015686035],[-76.24166870117188,37.90499305725098],[-76.35360717773438,37.618600845336914],[-77.13389587402344,38.17276954650879],[-76.28666687011719,37.5674991607666],[-76.381103515625,37.273881912231445],[-76.68276977539062,37.42971992492676],[-76.26806640625,37.07888221740723],[-77.23222351074219,37.29638862609863],[-75.989990234375,36.91388130187988],[-75.5291748046875,35.80388069152832],[-75.93888854980469,36.71666145324707],[-75.78555297851562,36.06999397277832],[-76.19554138183594,36.31999397277832],[-76.06304931640625,36.15332221984863],[-76.65666198730469,36.03110694885254],[-76.70611572265625,36.26416206359863],[-76.73056030273438,35.93943214416504],[-76.07084655761719,35.9919376373291],[-76.0352783203125,35.64999580383301],[-75.85360717773438,35.974992752075195],[-75.72027587890625,35.81443977355957],[-76.149169921875,35.33693885803223],[-77.05082702636719,35.53027534484863],[-76.46888732910156,35.27166175842285],[-76.76139831542969,34.98777198791504],[-77.07640075683594,35.15609931945801],[-76.94444274902344,34.977487564086914],[-76.33583068847656,34.88694190979004],[-77.42887878417969,34.7419376373291],[-77.93083190917969,33.92777442932129],[-77.961669921875,34.15860176086426],[-78.01362609863281,33.89193916320801],[-78.82749938964844,33.73027229309082],[-79.19644165039062,33.278940200805664],[-79.1885986328125,33.43638038635254],[-79.27139282226562,33.37332344055176],[-79.20584106445312,33.165544509887695],[-79.37171936035156,33.05894660949707],[-79.38194274902344,33.009721755981445],[-80.67166137695312,32.52166175842285],[-80.46722412109375,32.31582832336426],[-80.83694458007812,32.51666450500488],[-80.66999816894531,32.21415901184082],[-81.4969482421875,31.12555503845215],[-81.25527954101562,29.796667098999023],[-80.552490234375,28.524999618530273],[-80.4466552734375,27.864442825317383],[-80.60221862792969,28.607500076293945],[-80.84416198730469,28.790555953979492],[-80.75556945800781,28.415830612182617],[-80.0333251953125,26.786664962768555],[-80.39862060546875,25.184720993041992],[-81.08805847167969,25.11555290222168],[-80.915283203125,25.25139045715332],[-81.336669921875,25.80499839782715],[-81.73658752441406,25.959444046020508],[-81.97005462646484,26.482831954956055],[-81.77778625488281,26.710554122924805],[-82.06416320800781,26.545000076293945],[-82.01722717285156,26.964719772338867],[-82.30278015136719,26.837221145629883],[-82.6552734375,27.4616641998291],[-82.42250061035156,27.917497634887695],[-82.69137573242188,28.0322208404541],[-82.72250366210938,27.65694236755371],[-82.85333251953125,27.855276107788086],[-82.631103515625,28.88499641418457],[-83.66944885253906,29.90610694885254],[-84.20750427246094,30.105554580688477],[-85.35417175292969,29.676664352416992],[-85.63394165039062,30.104440689086914],[-85.39222717285156,30.0494441986084],[-86.26333618164062,30.49666404724121],[-88.02362060546875,30.21944236755371],[-87.75639343261719,30.285276412963867],[-88.02027893066406,30.701108932495117],[-88.13276672363281,30.314443588256836],[-90.41972351074219,30.198331832885742],[-89.66722106933594,30.167776107788086],[-89.65805053710938,29.87388801574707],[-89.39944458007812,30.050832748413086],[-89.75334167480469,29.630830764770508],[-89.6763916015625,29.523889541625977],[-89.18721008300781,29.339719772338867],[-89.00834655761719,29.176942825317383],[-89.40499877929688,28.926664352416992],[-89.27278137207031,29.155832290649414],[-90.17832946777344,29.572500228881836],[-90.2066650390625,29.091943740844727],[-91.2469482421875,29.24083137512207],[-91.8416748046875,29.830278396606445],[-92.30833435058594,29.53972053527832],[-93.84028625488281,29.704164505004883],[-93.84527587890625,29.98805046081543],[-93.85749816894531,29.67610740661621],[-94.77250671386719,29.3638858795166],[-94.475830078125,29.56138801574707],[-95.05943298339844,29.71888542175293],[-94.8880615234375,29.37555503845215],[-94.90278625488281,29.314443588256836],[-95.09388732910156,29.17777442932129],[-95.14083862304688,29.0575008392334],[-96.21278381347656,28.485551834106445],[-95.98582458496094,28.6491641998291],[-96.64167785644531,28.719717025756836],[-96.39834594726562,28.43610954284668],[-96.80360412597656,28.473051071166992],[-97.18472290039062,27.827497482299805],[-97.52055358886719,27.86638832092285],[-97.41111755371094,27.327497482299805],[-97.77389526367188,27.458887100219727],[-97.42388916015625,27.267499923706055],[-97.55943298339844,26.836111068725586],[-97.14073944091797,25.966428756713867],[-99.104736328125,26.434999465942383],[-99.5050048828125,27.570276260375977],[-101.40501403808594,29.77277946472168],[-102.30584716796875,29.88944435119629],[-103.375,29.023611068725586],[-104.54000854492188,29.671110153198242],[-104.90055847167969,30.572778701782227],[-106.40084838867188,31.750276565551758],[-108.2086181640625,31.783334732055664],[-108.20834350585938,31.33305549621582],[-111.04583740234375,31.33305549621582],[-113.05288696289062,31.971071243286133],[-114.80982971191406,32.50699043273926],[-114.7190933227539,32.71845817565918],[-117.12237358093262,32.53533363342285],[-117.48082733154297,33.32749366760254],[-118.53472900390625,34.05082893371582],[-120.62026977539062,34.57083320617676],[-120.61416625976562,35.13582801818848],[-121.86749267578125,36.3124942779541],[-121.79638671875,36.87943458557129],[-122.48805236816406,37.518327713012695],[-122.38694763183594,37.816667556762695],[-122.00583457946777,37.47137641906738],[-122.39334106445312,37.957773208618164],[-122.24054718017578,38.059160232543945],[-121.41999816894531,38.012773513793945],[-121.5766830444336,38.11583137512207],[-121.7361068725586,38.04471778869629],[-122.01862335205078,38.148115158081055],[-122.10973358154297,38.06138038635254],[-122.36528015136719,38.15555000305176],[-122.49137878417969,37.827775955200195],[-122.9970703125,38.005109786987305],[-122.96456146240234,38.239614486694336],[-122.8035945892334,38.08804512023926],[-123.10472106933594,38.46110725402832],[-123.70361328125,38.93249702453613],[-123.77583312988281,39.71721076965332],[-124.33222961425781,40.2661075592041],[-124.03999328613281,41.431108474731445],[-124.5244369506836,42.866106033325195],[-124.13834381103516,43.371103286743164],[-123.95195007324219,46.181108474731445],[-123.16357421875,46.19519233703613],[-124,46.32361030578613],[-124.04277038574219,46.65804481506348],[-124.01583862304688,46.654436111450195],[-123.989990234375,46.397775650024414],[-123.9416732788086,46.3911075592041],[-123.7525634765625,46.693071365356445],[-124.09750366210938,46.86138343811035],[-123.79666137695312,46.97609901428223],[-124.16194152832031,46.94110298156738],[-124.7158432006836,48.395273208618164],[-122.75110626220703,48.16110420227051],[-122.63027954101562,47.91582679748535],[-123.14750671386719,47.368600845336914],[-122.8364028930664,47.439157485961914],[-123.10249328613281,47.39972114562988],[-122.5655517578125,47.93804359436035],[-122.45472717285156,47.77443885803223],[-122.54998779296875,47.28277015686035],[-122.6191635131836,47.420549392700195],[-122.75862121582031,47.189714431762695],[-122.79750061035156,47.395273208618164],[-123.06861877441406,47.15165901184082],[-122.87860107421875,47.064157485961914],[-122.30972290039062,47.40110206604004],[-122.3791732788086,48.29166603088379],[-122.70445251464844,48.48610877990723],[-122.4375,48.59804725646973],[-122.76029968261719,48.99943733215332],[-95.1541748046875,48.99943733215332],[-95.07806396484375,49.35916328430176]],[[-122.4958267211914,47.59554481506348],[-122.50334167480469,47.71527290344238],[-122.58168029785156,47.67166328430176],[-122.4958267211914,47.59554481506348]],[[-123.9385986328125,45.53666114807129],[-123.91694641113281,45.56443977355957],[-123.93443298339844,45.55832862854004],[-123.9385986328125,45.53666114807129]],[[-77.85166931152344,34.11110877990723],[-77.82084655761719,34.17527198791504],[-77.8558349609375,34.1491641998291],[-77.85166931152344,34.11110877990723]]],[[[-179.10528564453125,51.21305274963379],[-179.14199829101562,51.26859474182129],[-179.08724975585938,51.29083442687988],[-179.10528564453125,51.21305274963379]]],[[[-178.96249389648438,51.311662673950195],[-178.94998168945312,51.39693641662598],[-178.90032958984375,51.354997634887695],[-178.96249389648438,51.311662673950195]]],[[[178.993013381958,51.57499885559082],[179.47134590148926,51.36749458312988],[178.63638496398926,51.637773513793945],[178.993013381958,51.57499885559082]]],[[[-178.7769775390625,51.74553871154785],[-178.842529296875,51.81915473937988],[-178.7427978515625,51.80777168273926],[-178.7769775390625,51.74553871154785]]],[[[178.39221382141113,51.7630558013916],[178.22302436828613,51.830827713012695],[178.32995796203613,51.81499671936035],[178.39221382141113,51.7630558013916]]],[[[-176.0128173828125,51.830270767211914],[-176.14334106445312,51.77443885803223],[-176.21945190429688,51.83138465881348],[-176.0128173828125,51.830270767211914]]],[[[-176.33642578125,51.72165870666504],[-176.41448974609375,51.854997634887695],[-176.2769775390625,51.86026954650879],[-176.33642578125,51.72165870666504]]],[[[-177.81390380859375,51.71970558166504],[-177.94998168945312,51.60637855529785],[-178.21807861328125,51.87193489074707],[-177.81390380859375,51.71970558166504]]],[[[-176.55059814453125,51.90582466125488],[-176.42974853515625,51.73026466369629],[-176.97503662109375,51.5958194732666],[-176.55059814453125,51.90582466125488]]],[[[-175.95111083984375,51.86887550354004],[-176.09307861328125,51.885263442993164],[-176.001953125,51.90887641906738],[-175.95111083984375,51.86887550354004]]],[[[-177.12222290039062,51.784433364868164],[-177.7044677734375,51.70083045959473],[-177.15725708007812,51.93832588195801],[-177.12222290039062,51.784433364868164]]],[[[-175.72503662109375,51.930551528930664],[-175.72918701171875,51.96610450744629],[-175.65750122070312,51.95694160461426],[-175.72503662109375,51.930551528930664]]],[[[-175.864990234375,51.96360969543457],[-175.94668579101562,51.97886848449707],[-175.80194091796875,51.98220252990723],[-175.864990234375,51.96360969543457]]],[[[178.53692817687988,51.89361000061035],[178.46829414367676,51.98472023010254],[178.60608100891113,51.947771072387695],[178.53692817687988,51.89361000061035]]],[[[179.73745918273926,51.90304756164551],[179.48608589172363,51.97221565246582],[179.65860176086426,52.02471351623535],[179.73745918273926,51.90304756164551]]],[[[177.68469429016113,52.07999610900879],[177.6049518585205,51.92027473449707],[177.241060256958,51.87693977355957],[177.68469429016113,52.07999610900879]]],[[[-176.0372314453125,51.964433670043945],[-176.19085693359375,52.05999183654785],[-176.04611206054688,52.10222053527832],[-176.0372314453125,51.964433670043945]]],[[[-173.515869140625,52.10693550109863],[-172.95559692382812,52.08554267883301],[-174.05697631835938,52.12027168273926],[-173.515869140625,52.10693550109863]]],[[[175.96109199523926,52.33555030822754],[175.88189888000488,52.37249183654785],[175.98773384094238,52.35360908508301],[175.96109199523926,52.33555030822754]]],[[[-172.38836669921875,52.28972053527832],[-172.6280517578125,52.25832557678223],[-172.43832397460938,52.39193153381348],[-172.38836669921875,52.28972053527832]]],[[[-173.99530029296875,52.29110145568848],[-175.33584594726562,52.0141544342041],[-174.18447875976562,52.416940689086914],[-173.99530029296875,52.29110145568848]]],[[[173.78775215148926,52.501108169555664],[173.73550605773926,52.35332679748535],[173.37524604797363,52.39943885803223],[173.78775215148926,52.501108169555664]]],[[[-171.23526000976562,52.45083045959473],[-171.30804443359375,52.49942970275879],[-171.21722412109375,52.51054573059082],[-171.23526000976562,52.45083045959473]]],[[[-170.60556030273438,52.590829849243164],[-170.8416748046875,52.554155349731445],[-170.6761474609375,52.69415473937988],[-170.60556030273438,52.590829849243164]]],[[[174.17776679992676,52.70555305480957],[174.07412910461426,52.711381912231445],[174.10217475891113,52.741106033325195],[174.17776679992676,52.70555305480957]]],[[[-170.11474609375,52.71832466125488],[-170.17999267578125,52.78387641906738],[-170.05499267578125,52.765268325805664],[-170.11474609375,52.71832466125488]]],[[[-169.675048828125,52.81777381896973],[-170.0130615234375,52.81833076477051],[-169.78115844726562,52.885263442993164],[-169.675048828125,52.81777381896973]]],[[[-170.04083251953125,52.853044509887695],[-170.12747192382812,52.88859748840332],[-169.99389457702637,52.901933670043945],[-170.04083251953125,52.853044509887695]]],[[[173.29998970031738,52.882211685180664],[172.92859077453613,52.74388313293457],[172.47635078430176,52.92444038391113],[173.29998970031738,52.882211685180664]]],[[[-169.72445678710938,52.943315505981445],[-169.75250244140625,53.026376724243164],[-169.67669677734375,53.03166389465332],[-169.72445678710938,52.943315505981445]]],[[[-168.24359130859375,53.25110054016113],[-169.08670043945312,52.82805061340332],[-168.35195922851562,53.47554969787598],[-167.79531860351562,53.49553871154785],[-168.24359130859375,53.25110054016113]]],[[[-166.20999145507812,53.705270767211914],[-166.2933349609375,53.79305458068848],[-166.09002685546875,53.839433670043945],[-166.20999145507812,53.705270767211914]]],[[[-166.60748291015625,53.829721450805664],[-166.21502685546875,53.92832374572754],[-166.75283813476562,53.44638252258301],[-167.84637451171875,53.30859565734863],[-166.80389404296875,53.648874282836914],[-167.02420043945312,53.95554542541504],[-166.60748291015625,53.829721450805664]]],[[[-165.251708984375,54.07609748840332],[-165.29779052734375,54.037492752075195],[-165.48193359375,54.07443428039551],[-165.251708984375,54.07609748840332]]],[[[-164.939208984375,54.12693977355957],[-164.965576171875,54.075273513793945],[-165.221923828125,54.08999061584473],[-164.939208984375,54.12693977355957]]],[[[-165.69696044921875,54.08471870422363],[-166.12307739257812,54.11638069152832],[-165.93832397460938,54.22054481506348],[-165.69696044921875,54.08471870422363]]],[[[-165.56057739257812,54.11026954650879],[-165.68197631835938,54.238046646118164],[-165.48641967773438,54.28804969787598],[-165.56057739257812,54.11026954650879]]],[[[-162.40057373046875,54.36944007873535],[-162.48971557617188,54.40971565246582],[-162.36831665039062,54.38833045959473],[-162.40057373046875,54.36944007873535]]],[[[-162.54388427734375,54.38138008117676],[-162.78640747070312,54.41471290588379],[-162.83111572265625,54.494157791137695],[-162.54388427734375,54.38138008117676]]],[[[-132.61944580078125,54.75444221496582],[-132.7811279296875,54.92527198791504],[-132.61886596679688,54.89610481262207],[-132.61944580078125,54.75444221496582]]],[[[-159.29501342773438,54.8669376373291],[-159.33612060546875,54.92721748352051],[-159.20693969726562,54.92444038391113],[-159.29501342773438,54.8669376373291]]],[[[-163.41363525390625,54.8911075592041],[-163.3699951171875,54.78499794006348],[-163.14501953125,54.7661075592041],[-163.04861450195312,54.6683292388916],[-164.95220947265625,54.57583045959473],[-164.43276977539062,54.930551528930664],[-163.41363525390625,54.8911075592041]]],[[[-162.29306030273438,54.83416175842285],[-162.4344482421875,54.931108474731445],[-162.23275756835938,54.96527290344238],[-162.29306030273438,54.83416175842285]]],[[[-131.32583618164062,54.856943130493164],[-131.48275756835938,54.93082618713379],[-131.23638916015625,54.99527168273926],[-131.32583618164062,54.856943130493164]]],[[[-159.43417358398438,54.9405460357666],[-159.479154586792,55.01416206359863],[-159.34942626953125,55.04916572570801],[-159.43417358398438,54.9405460357666]]],[[[-161.73971557617188,55.056100845336914],[-161.90695190429688,55.151384353637695],[-161.64138793945312,55.11332893371582],[-161.73971557617188,55.056100845336914]]],[[[-132.67471313476562,55.03305244445801],[-132.86471557617188,55.02999305725098],[-132.85333251953125,55.159433364868164],[-132.67471313476562,55.03305244445801]]],[[[-131.42584228515625,55.21110725402832],[-131.37222290039062,55.01361274719238],[-131.61749267578125,55.01111030578613],[-131.42584228515625,55.21110725402832]]],[[[-132.8358154296875,54.88916206359863],[-132.67999267578125,54.66610145568848],[-133.195556640625,55.23027229309082],[-132.8358154296875,54.88916206359863]]],[[[-159.51947021484375,55.064157485961914],[-159.65557861328125,55.05499458312988],[-159.5352783203125,55.24749183654785],[-159.51947021484375,55.064157485961914]]],[[[-161.56195068359375,55.21805000305176],[-161.70611572265625,55.20471382141113],[-161.53363037109375,55.25277900695801],[-161.56195068359375,55.21805000305176]]],[[[-159.84332275390625,55.13249397277832],[-160.24472045898438,54.901384353637695],[-159.8822021484375,55.29083442687988],[-159.84332275390625,55.13249397277832]]],[[[-133.24972534179688,55.20916175842285],[-133.439453125,55.30193519592285],[-133.29666137695312,55.33055305480957],[-133.24972534179688,55.20916175842285]]],[[[-160.33306884765625,55.24804878234863],[-160.528076171875,55.3205509185791],[-160.34695434570312,55.368600845336914],[-160.33306884765625,55.24804878234863]]],[[[-160.695556640625,55.39999580383301],[-160.461669921875,55.187211990356445],[-160.81640625,55.11832618713379],[-160.695556640625,55.39999580383301]]],[[[-133.59832763671875,55.2338809967041],[-133.65362358093262,55.36944007873535],[-133.44696044921875,55.4102725982666],[-133.59832763671875,55.2338809967041]]],[[[-131.72500610351562,55.134721755981445],[-131.84609985351562,55.419992446899414],[-131.61663818359375,55.28360939025879],[-131.72500610351562,55.134721755981445]]],[[[-163.14639282226562,55.393327713012695],[-163.19473266601562,55.42193794250488],[-163.136962890625,55.436105728149414],[-163.14639282226562,55.393327713012695]]],[[[-160.17889404296875,55.39610481262207],[-160.34194946289062,55.416940689086914],[-160.24972534179688,55.46305274963379],[-160.17889404296875,55.39610481262207]]],[[[-133.5050048828125,55.42721748352051],[-133.60165405273438,55.44748878479004],[-133.42138671875,55.48360633850098],[-133.5050048828125,55.42721748352051]]],[[[-133.57806396484375,55.49777412414551],[-133.758056640625,55.48721504211426],[-133.70248413085938,55.5513858795166],[-133.57806396484375,55.49777412414551]]],[[[-133.28945922851562,55.4758243560791],[-133.43667602539062,55.52749061584473],[-133.308349609375,55.55471229553223],[-133.28945922851562,55.4758243560791]]],[[[-133.50558471679688,55.69332313537598],[-133.67779541015625,55.78416633605957],[-133.29974365234375,55.79361152648926],[-133.50558471679688,55.69332313537598]]],[[[-133.24221801757812,55.77665901184082],[-133.32916259765625,55.87748908996582],[-133.21554565429688,55.86194038391113],[-133.24221801757812,55.77665901184082]]],[[[-158.86416625976562,55.80388069152832],[-158.832763671875,55.89388465881348],[-158.709716796875,55.83138465881348],[-158.86416625976562,55.80388069152832]]],[[[-134.24972534179688,55.81944465637207],[-134.33889770507812,55.91805458068848],[-134.09664916992188,55.9183292388916],[-134.24972534179688,55.81944465637207]]],[[[-155.58029174804688,55.77443885803223],[-155.739990234375,55.8286075592041],[-155.56390380859375,55.91860389709473],[-155.58029174804688,55.77443885803223]]],[[[-133.8477783203125,55.847490310668945],[-133.92721557617188,55.911935806274414],[-133.8477783203125,55.93526649475098],[-133.8477783203125,55.847490310668945]]],[[[-131.05056762695312,55.79972267150879],[-131.14279174804688,55.19693946838379],[-131.461669921875,55.28611183166504],[-131.348876953125,55.64499855041504],[-131.52194213867188,55.29305458068848],[-131.82223510742188,55.450273513793945],[-131.68389892578125,55.833330154418945],[-131.2650146484375,55.960824966430664],[-131.05056762695312,55.79972267150879]]],[[[-131.51947021484375,55.915544509887695],[-131.57693481445312,55.93194007873535],[-131.39944458007812,55.963884353637695],[-131.51947021484375,55.915544509887695]]],[[[-133.69528198242188,55.89638710021973],[-133.67971801757812,56.06638526916504],[-133.278076171875,56.139719009399414],[-133.69528198242188,55.89638710021973]]],[[[-133.93112182617188,56.28833198547363],[-133.94805908203125,56.30193519592285],[-133.92556762695312,56.298051834106445],[-133.93112182617188,56.28833198547363]]],[[[-133.48858642578125,56.33693885803223],[-132.1441650390625,55.480546951293945],[-132.5625,55.56777381896973],[-131.98858642578125,55.26416206359863],[-132.21859741210938,54.99249458312988],[-131.96304321289062,55.025827407836914],[-132.00390625,54.6905460357666],[-132.64138793945312,55.25027656555176],[-133.22250366210938,55.28305244445801],[-132.86749267578125,55.35388374328613],[-133.12860107421875,55.49471473693848],[-132.90835571289062,55.6280460357666],[-133.37222290039062,55.62054634094238],[-133.135009765625,55.88110542297363],[-133.25836181640625,56.15249061584473],[-133.61721801757812,56.20749855041504],[-133.48858642578125,56.33693885803223]]],[[[-132.09445190429688,56.09332466125488],[-132.31887817382812,55.91221046447754],[-132.71694946289062,56.151384353637695],[-132.41778564453125,56.35083198547363],[-132.09445190429688,56.09332466125488]]],[[[-132.81723022460938,56.2338809967041],[-133.05776977539062,56.347490310668945],[-132.63555908203125,56.434160232543945],[-132.81723022460938,56.2338809967041]]],[[[-132.50085258483887,56.35332679748535],[-132.49386596679688,56.43582344055176],[-132.38668823242188,56.39860725402832],[-132.50085258483887,56.35332679748535]]],[[[-132.13247680664062,56.34527015686035],[-132.05612182617188,56.11138343811035],[-132.37387084960938,56.48443794250488],[-132.13247680664062,56.34527015686035]]],[[[-153.95889282226562,56.50277900695801],[-154.13446044921875,56.50555610656738],[-153.87387084960938,56.55332374572754],[-153.95889282226562,56.50277900695801]]],[[[-156.99664306640625,56.555551528930664],[-157.3297119140625,56.53582954406738],[-157.25167846679688,56.58166694641113],[-156.99664306640625,56.555551528930664]]],[[[-132.3980712890625,56.58360481262207],[-132.43499755859375,56.5897159576416],[-132.37942504882812,56.60054969787598],[-132.3980712890625,56.58360481262207]]],[[[-154.48138427734375,56.60169792175293],[-154.40280151367188,56.54666328430176],[-154.7874755859375,56.414968490600586],[-154.48138427734375,56.60169792175293]]],[[[-154.21194458007812,56.49888038635254],[-154.35247802734375,56.54166603088379],[-154.08499145507812,56.608049392700195],[-154.21194458007812,56.49888038635254]]],[[[-169.67337036132812,56.608598709106445],[-169.47137451171875,56.59221076965332],[-169.7861328125,56.6138858795166],[-169.67337036132812,56.608598709106445]]],[[[-132.7730712890625,56.49471473693848],[-132.87359619140625,56.79610633850098],[-132.52890014648438,56.59527015686035],[-132.7730712890625,56.49471473693848]]],[[[-133.98748779296875,56.87082862854004],[-133.90280151367188,56.75305366516113],[-134.02471923828125,56.64721870422363],[-133.83056640625,56.79610633850098],[-133.69137573242188,56.59971809387207],[-133.92056274414062,56.61416053771973],[-133.84609985351562,56.29083442687988],[-133.97320556640625,56.35610389709473],[-133.97332763671875,56.08166694641113],[-134.0655517578125,56.30582618713379],[-134.123046875,55.99582862854004],[-134.06527709960938,56.550546646118164],[-134.40890502929688,56.82943916320801],[-133.98748779296875,56.87082862854004]]],[[[-133.31777954101562,56.99388313293457],[-132.92501831054688,56.643327713012695],[-133.3519287109375,56.83860206604004],[-133.08193969726562,56.523881912231445],[-133.5755615234375,56.433603286743164],[-133.69696044921875,56.83194160461426],[-133.89056396484375,56.89694404602051],[-133.73611450195312,56.89305305480957],[-134.01806640625,57.014719009399414],[-133.31777954101562,56.99388313293457]]],[[[-153.25335693359375,56.99833106994629],[-153.40750122070312,57.072771072387695],[-153.23416137695312,57.205827713012695],[-152.883056640625,57.15027046203613],[-153.25335693359375,56.99833106994629]]],[[[-170.1661376953125,57.16331672668457],[-170.4139404296875,57.17416572570801],[-170.15057373046875,57.22832679748535],[-170.1661376953125,57.16331672668457]]],[[[-135.79583740234375,56.98638343811035],[-135.71054077148438,57.32361030578613],[-135.54611206054688,57.12943458557129],[-135.79583740234375,56.98638343811035]]],[[[-134.9375,57.35888862609863],[-134.65362358093262,56.16304969787598],[-135.67279052734375,57.351938247680664],[-134.9375,57.35888862609863]]],[[[-134.79251098632812,57.30027198791504],[-134.97470092773438,57.41526985168457],[-134.81362915039062,57.416940689086914],[-134.79251098632812,57.30027198791504]]],[[[-153.20889282226562,57.8124942779541],[-153.53640747070312,57.93471717834473],[-153.35333251953125,57.93638038635254],[-153.26974487304688,57.8991641998291],[-153.20889282226562,57.8124942779541]]],[[[-152.35443115234375,57.890275955200195],[-152.50335693359375,57.933053970336914],[-152.417236328125,57.97638130187988],[-152.35443115234375,57.890275955200195]]],[[[-153.116943359375,57.94999885559082],[-152.15139770507812,57.604440689086914],[-153.02279663085938,57.47360420227051],[-152.5958251953125,57.3699893951416],[-153.16946411132812,57.34554481506348],[-152.95611572265625,57.25388526916504],[-153.26028442382812,57.22776985168457],[-153.5,57.06388282775879],[-153.73165893554688,57.05971717834473],[-153.54998779296875,56.983049392700195],[-153.97970581054688,56.738603591918945],[-153.73776245117188,57.13082313537598],[-154.47943115234375,57.12027168273926],[-154.10110473632812,57.11638832092285],[-154.29779052734375,56.84887886047363],[-154.80111694335938,57.28611183166504],[-154.20721435546875,57.66666603088379],[-153.6280517578125,57.26944160461426],[-153.88027954101562,57.64305305480957],[-153.58111572265625,57.612497329711914],[-153.9283447265625,57.811105728149414],[-153.4969482421875,57.627214431762695],[-153.31527709960938,57.7258243560791],[-153.479154586792,57.839433670043945],[-153.21304321289062,57.78833198547363],[-153.15057373046875,57.8638858795166],[-153.04806518554688,57.82749366760254],[-153.292236328125,58.001665115356445],[-153.116943359375,57.94999885559082]]],[[[-153.18527221679688,58.09249305725098],[-152.88778686523438,57.991106033325195],[-153.41806030273438,58.05888557434082],[-153.18527221679688,58.09249305725098]]],[[[-136.43722534179688,57.846384048461914],[-136.48443603515625,58.09332466125488],[-136.33056640625,58.01027870178223],[-136.43722534179688,57.846384048461914]]],[[[-135.74276733398438,58.25610542297363],[-135.48248291015625,58.15555000305176],[-135.707763671875,57.97832679748535],[-134.9302978515625,58.02804756164551],[-135.2047119140625,57.942216873168945],[-135.01055908203125,57.77694129943848],[-135.88751220703125,57.988603591918945],[-135.29696655273438,57.73166084289551],[-134.92166137695312,57.75694465637207],[-134.84332275390625,57.46277046203613],[-135.80416870117188,57.76333045959473],[-135.54278564453125,57.47221565246582],[-135.83084106445312,57.38582801818848],[-136.4122314453125,57.81582832336426],[-136.02972412109375,57.84916114807129],[-136.35220336914062,58.219438552856445],[-135.74276733398438,58.25610542297363]]],[[[-151.84722900390625,58.16971778869629],[-151.89666557312012,58.19415473937988],[-151.83554077148438,58.26860237121582],[-151.84722900390625,58.16971778869629]]],[[[-134.45443725585938,58.31332588195801],[-134.25973510742188,58.19499397277832],[-134.68389892578125,58.2983341217041],[-134.56695556640625,58.340829849243164],[-134.45443725585938,58.31332588195801]]],[[[-152.4091796875,58.365549087524414],[-151.9727783203125,58.233049392700195],[-153.23138427734375,58.16916084289551],[-152.4091796875,58.365549087524414]]],[[[-134.67471313476562,58.16054725646973],[-134.16915893554688,58.15971565246582],[-133.87582397460938,57.67276954650879],[-134.28860473632812,58.077219009399414],[-133.86026000976562,57.360551834106445],[-134.48666381835938,57.02555274963379],[-134.61331176757812,57.224992752075195],[-134.31027221679688,57.33610725402832],[-134.572509765625,57.48971748352051],[-134.3497314453125,57.54277229309082],[-134.65444946289062,57.59832954406738],[-134.9566650390625,58.40777015686035],[-134.67471313476562,58.16054725646973]]],[[[-152.49386596679688,58.47221565246582],[-152.66055297851562,58.5433292388916],[-152.3458251953125,58.627214431762695],[-152.49386596679688,58.47221565246582]]],[[[-160.95693969726562,58.55694007873535],[-161.11309814453125,58.65527534484863],[-160.68722534179688,58.81833076477051],[-160.95693969726562,58.55694007873535]]],[[[-152.31332397460938,58.90832710266113],[-152.36026000976562,58.91638374328613],[-152.16140747070312,58.942216873168945],[-152.31332397460938,58.90832710266113]]],[[[-150.69168090820312,59.306657791137695],[-150.77667236328125,59.32888221740723],[-150.61663818359375,59.389719009399414],[-150.69168090820312,59.306657791137695]]],[[[-153.41140747070312,59.330278396606445],[-153.55221557617188,59.36471748352051],[-153.403076171875,59.406938552856445],[-153.41140747070312,59.330278396606445]]],[[[-150.3114013671875,59.420549392700195],[-150.44027709960938,59.40110206604004],[-150.29278564453125,59.46305274963379],[-150.3114013671875,59.420549392700195]]],[[[-144.58499145507812,59.81027412414551],[-144.50390625,59.89444160461426],[-144.20889282226562,60.00555610656738],[-144.58499145507812,59.81027412414551]]],[[[-148.1611328125,59.94110298156738],[-148.24581909179688,59.94249153137207],[-147.99221801757812,60.0402774810791],[-148.1611328125,59.94110298156738]]],[[[-148.02780151367188,59.94665718078613],[-147.88333129882812,60.067216873168945],[-147.81723022460938,60.06888771057129],[-148.02780151367188,59.94665718078613]]],[[[-148.11553955078125,59.99638557434082],[-147.96722412109375,60.15304756164551],[-147.87664794921875,60.10388374328613],[-148.11553955078125,59.99638557434082]]],[[[-148.03390502929688,60.18943214416504],[-148.15139770507812,60.041940689086914],[-148.30972290039062,60.02971839904785],[-148.03390502929688,60.18943214416504]]],[[[-147.8499755859375,59.77694129943848],[-147.193603515625,60.35332679748535],[-146.92333984375,60.309160232543945],[-147.8499755859375,59.77694129943848]]],[[[-147.71194458007812,60.37610054016113],[-147.75973510742188,60.165544509887695],[-147.90972900390625,60.23472023010254],[-147.71194458007812,60.37610054016113]]],[[[-148.07943725585938,60.28277015686035],[-148.14251708984375,60.3205509185791],[-147.98330688476562,60.38388252258301],[-148.07943725585938,60.28277015686035]]],[[[-166.10971069335938,60.39915657043457],[-165.68142700195312,60.29471778869629],[-165.55972290039062,59.92360877990723],[-166.19305419921875,59.75443458557129],[-167.41806030273438,60.18942451477051],[-166.10971069335938,60.39915657043457]]],[[[-146.3538818359375,60.40749549865723],[-146.07888793945312,60.4052677154541],[-146.72415161132812,60.374711990356445],[-146.3538818359375,60.40749549865723]]],[[[-145.12277221679688,60.30721473693848],[-145.28195190429688,60.32999610900879],[-145.08694458007812,60.41666603088379],[-145.12277221679688,60.30721473693848]]],[[[-172.52029418945312,60.38833045959473],[-172.20697021484375,60.31304359436035],[-173.05364990234375,60.497209548950195],[-172.52029418945312,60.38833045959473]]],[[[-151.95556640625,60.42276954650879],[-151.95111083984375,60.512216567993164],[-151.85638427734375,60.48971748352051],[-151.95556640625,60.42276954650879]]],[[[-146.2469482421875,60.45499610900879],[-146.320556640625,60.494157791137695],[-145.74972534179688,60.59471321105957],[-146.2469482421875,60.45499610900879]]],[[[-147.37277221679688,60.66166114807129],[-147.47555541992188,60.68888282775879],[-147.31390380859375,60.67749214172363],[-147.37277221679688,60.66166114807129]]],[[[-147.92556762695312,60.66221046447754],[-148.00418090820312,60.726938247680664],[-147.84609985351562,60.69999885559082],[-147.92556762695312,60.66221046447754]]],[[[-148.14083862304688,60.642221450805664],[-148.21417236328125,60.75444221496582],[-148.10861206054688,60.73638343811035],[-148.14083862304688,60.642221450805664]]],[[[-164.98831176757812,60.82249641418457],[-165.01751708984375,60.87443733215332],[-164.90362358093262,60.85360908508301],[-164.98831176757812,60.82249641418457]]],[[[-146.75335693359375,60.80721473693848],[-146.83193969726562,60.836381912231445],[-146.744140625,60.88138008117676],[-146.75335693359375,60.80721473693848]]],[[[-147.15084838867188,60.86027717590332],[-147.31777954101562,60.884164810180664],[-147.07528686523438,60.8991641998291],[-147.15084838867188,60.86027717590332]]],[[[-147.92889404296875,60.80694007873535],[-148.133056640625,60.79972267150879],[-148.10665893554688,60.912492752075195],[-147.92889404296875,60.80694007873535]]],[[[-170.31890869140625,63.254716873168945],[-170.31585693359375,63.25387763977051],[-170.29611206054688,63.238046646118164],[-170.31890869140625,63.254716873168945]]],[[[-170.31890869140625,63.254716873168945],[-170.36221313476562,63.28249549865723],[-170.34188842773438,63.271127700805664],[-170.31890869140625,63.254716873168945]]],[[[-170.46676635742188,63.334184646606445],[-170.40390014648438,63.3044376373291],[-170.48583984375,63.34110450744629],[-170.46676635742188,63.334184646606445]]],[[[-170.54364013671875,63.35971260070801],[-170.49026489257812,63.341928482055664],[-170.5511474609375,63.360551834106445],[-170.54364013671875,63.35971260070801]]],[[[-170.59500122070312,63.37193489074707],[-170.58197021484375,63.368051528930664],[-170.86325073242188,63.41851234436035],[-170.59500122070312,63.37193489074707]]],[[[-162.37747192382812,63.544443130493164],[-162.70361328125,63.571664810180664],[-162.4202880859375,63.63749885559082],[-162.37747192382812,63.544443130493164]]],[[[-171.465576171875,63.60666084289551],[-170.30001831054688,63.69415473937988],[-168.70086669921875,63.290544509887695],[-169.6661376953125,62.943315505981445],[-170.51889038085938,63.37803840637207],[-170.856689453125,63.46193885803223],[-171.46112060546875,63.314714431762695],[-171.850830078125,63.50860786437988],[-171.72695922851562,63.79221534729004],[-171.465576171875,63.60666084289551]]],[[[-166.6591796875,66.10331916809082],[-166.443603515625,66.18081855773926],[-166.16946411132812,66.22137641906738],[-166.6591796875,66.10331916809082]]],[[[-165.36444091796875,66.42637825012207],[-165.4708251953125,66.41415596008301],[-164.76223754882812,66.53831672668457],[-165.36444091796875,66.42637825012207]]],[[[-156.44696044921875,71.26361274719238],[-155.58694458007812,71.16276741027832],[-156.1824951171875,70.91832160949707],[-155.97360229492188,70.75583076477051],[-155.08749389648438,71.1513843536377],[-154.24386596679688,70.7794361114502],[-152.25250244140625,70.83526802062988],[-152.49859619140625,70.6494312286377],[-152.07611083984375,70.57499885559082],[-152.62942504882812,70.55748176574707],[-151.73248291015625,70.55720710754395],[-151.96609497070312,70.44359016418457],[-149.17471313476562,70.49081611633301],[-144.95220947265625,69.96832466125488],[-143.28057861328125,70.11831855773926],[-141.00299072265625,69.64236640930176],[-140.99554443359375,60.30721473693848],[-139.06805419921875,60.35222053527832],[-139.18890380859375,60.088884353637695],[-137.5908203125,59.238603591918945],[-137.47805786132812,58.90721321105957],[-135.47360229492188,59.80193519592285],[-133.42999267578125,58.45916175842285],[-131.82415771484375,56.596940994262695],[-130.01507568359375,55.90918159484863],[-130.17471313476562,55.75444221496582],[-129.99053955078125,55.28166389465332],[-130.68612670898438,54.76194190979004],[-131.00863647460938,55.004167556762695],[-130.461669921875,55.327775955200195],[-131.05612182617188,55.12276649475098],[-130.6138916015625,55.29610633850098],[-130.86416625976562,55.308603286743164],[-131.01028442382812,56.10638618469238],[-131.90057373046875,55.85527229309082],[-131.75250244140625,55.80777168273926],[-131.95498657226562,55.501108169555664],[-132.1602783203125,55.5786075592041],[-131.76974487304688,56.19693946838379],[-132.7913818359375,57.08804512023926],[-133.50836181640625,57.19360542297363],[-133.06304931640625,57.34887886047363],[-133.64056396484375,57.69638252258301],[-133.00057983398438,57.51500129699707],[-133.55694580078125,57.90249061584473],[-133.12136840820312,57.857500076293945],[-134.05499267578125,58.07193946838379],[-133.7691650390625,58.518327713012695],[-134.1541748046875,58.197771072387695],[-134.510009765625,58.35388374328613],[-134.76141357421875,58.382211685180664],[-135.33526611328125,59.46832466125488],[-135.30471801757812,59.08360481262207],[-135.55056762695312,59.2288761138916],[-135.08554077148438,58.233049392700195],[-135.91555786132812,58.3830509185791],[-136.06832885742188,58.81777381896973],[-135.76947021484375,58.90027046203613],[-136.1622314453125,59.03360939025879],[-136.23471069335938,58.75083351135254],[-137.05667114257812,59.06860542297363],[-137.12554931640625,58.82193946838379],[-136.5736083984375,58.83860206604004],[-136.02749633789062,58.387216567993164],[-136.6541748046875,58.21527290344238],[-138.443603515625,59.191659927368164],[-139.71054077148438,59.49582862854004],[-139.49386596679688,59.98221015930176],[-139.28555297851562,59.57138252258301],[-138.89279174804688,59.806657791137695],[-139.5,60.03305244445801],[-140.40335083007812,59.69804573059082],[-141.37664794921875,59.86638832092285],[-141.39083862304688,60.13860511779785],[-143.92333984375,59.994157791137695],[-144.9364013671875,60.30166053771973],[-144.61138916015625,60.71554756164551],[-145.29415893554688,60.35027503967285],[-145.85943603515625,60.49166297912598],[-145.62582397460938,60.67193794250488],[-146.26113891601562,60.64805030822754],[-146.04083251953125,60.79860877990723],[-146.65335083007812,60.699716567993164],[-146.1241455078125,60.84332466125488],[-146.75668334960938,60.955270767211914],[-146.30084228515625,61.13082313537598],[-147.366943359375,60.887773513793945],[-147.54666137695312,61.154436111450195],[-147.86526489257812,60.83249855041504],[-148.05221557617188,60.949716567993164],[-147.7197265625,61.27804756164551],[-148.69973754882812,60.78972053527832],[-148.197509765625,60.62610054016113],[-148.68417358398438,60.44832801818848],[-147.93695068359375,60.46221351623535],[-148.43112182617188,60.192766189575195],[-148.0977783203125,60.20749855041504],[-148.31777954101562,60.16888618469238],[-148.43582153320312,59.94887733459473],[-149.2861328125,59.86888313293457],[-149.41696166992188,60.11832618713379],[-149.52584838867188,59.71666145324707],[-149.73193359375,59.96055030822754],[-149.74359130859375,59.65860176086426],[-150.0341796875,59.79638862609863],[-149.91583251953125,59.7147159576416],[-150.01364135742188,59.62748908996582],[-150.34942626953125,59.46554756164551],[-150.213623046875,59.71666145324707],[-150.47360229492188,59.46444129943848],[-150.54168701171875,59.59166145324707],[-150.90750122070312,59.24332618713379],[-151.98056030273438,59.28055000305176],[-150.99276733398438,59.7772159576416],[-151.87664794921875,59.75388526916504],[-151.30389404296875,60.38555335998535],[-151.40890502929688,60.727487564086914],[-150.399169921875,61.03721809387207],[-149.028076171875,60.8477725982666],[-150.06417846679688,61.154436111450195],[-149.41696166992188,61.50860786437988],[-151.5836181640625,60.976938247680664],[-152.4302978515625,60.288888931274414],[-153.10305786132812,60.289438247680664],[-152.57720947265625,60.064714431762695],[-154.26083374023438,59.142221450805664],[-153.26779174804688,58.84860420227051],[-154.10333251953125,58.48193550109863],[-154.23361206054688,58.13110542297363],[-156.489990234375,57.33111000061035],[-156.54861450195312,56.977487564086914],[-158.42306518554688,56.44388008117676],[-158.64999389648438,56.26444435119629],[-158.12054443359375,56.23360633850098],[-158.50527954101562,55.9888858795166],[-158.60110473632812,56.18804359436035],[-159.667236328125,55.577219009399414],[-159.84109497070312,55.85110664367676],[-161.25418090820312,55.346940994262695],[-161.48553466796875,55.48110389709473],[-161.14169311523438,55.538888931274414],[-161.5625,55.62276649475098],[-161.9677734375,55.101938247680664],[-162.45416259765625,55.03833198547363],[-162.62664794921875,55.29944038391113],[-162.5625,54.955270767211914],[-163.1844482421875,55.139719009399414],[-163.04446411132812,54.9374942779541],[-163.36026000976562,54.81193733215332],[-163.25863647460938,54.97332191467285],[-163.32305908203125,55.121660232543945],[-161.79998779296875,55.88665962219238],[-160.24972534179688,55.77054786682129],[-160.57470703125,55.98665809631348],[-160.34695434570312,56.28555488586426],[-158.64056396484375,56.76111030578613],[-158.64889526367188,57.05332374572754],[-157.93804931640625,57.4919376373291],[-157.39666557312012,57.490549087524414],[-157.7066650390625,57.643327713012695],[-157.6099853515625,58.0897159576416],[-157.13861083984375,58.162492752075195],[-157.55361938476562,58.38249397277832],[-156.7791748046875,59.151384353637695],[-158.18832397460938,58.60638618469238],[-158.49249267578125,58.99943733215332],[-157.99276733398438,58.90499305725098],[-158.53695678710938,59.17527198791504],[-158.89752197265625,58.39554786682129],[-160.32666015625,59.05971717834473],[-162.17138671875,58.64972114562988],[-161.56582641601562,59.10360908508301],[-161.99221801757812,59.1441593170166],[-161.70526123046875,59.496660232543945],[-162.15139770507812,60.24554634094238],[-162.37222290039062,60.176103591918945],[-161.87942504882812,60.702219009399414],[-162.5694580078125,60.31638526916504],[-162.52166557312012,59.99276924133301],[-164.06527709960938,59.824167251586914],[-165.42529296875,60.55526924133301],[-164.66500854492188,60.91166114807129],[-164.26446533203125,60.778879165649414],[-164.42916870117188,60.55332374572754],[-163.957763671875,60.78027534484863],[-163.66946411132812,60.58721351623535],[-163.40972900390625,60.756662368774414],[-163.89561462402344,60.85688591003418],[-163.5513916015625,60.903879165649414],[-165.15029907226562,60.928049087524414],[-164.82223510742188,61.11110877990723],[-165.12054443359375,61.083879470825195],[-165.13861083984375,61.256662368774414],[-165.16372680664062,61.17004585266113],[-165.3699951171875,61.20083045959473],[-165.15057373046875,61.416940689086914],[-165.05967712402344,61.41684150695801],[-164.99842834472656,61.469770431518555],[-164.84527587890625,61.49444007873535],[-164.71609497070312,61.62555122375488],[-165.01724243164062,61.50000190734863],[-165.0755615234375,61.43221473693848],[-165.1611328125,61.43249702453613],[-165.28750610351562,61.333879470825195],[-165.40750122070312,61.208330154418945],[-165.34136962890625,61.15721321105957],[-165.38668823242188,61.06860542297363],[-166.19778442382812,61.59471321105957],[-165.24722290039062,62.44610023498535],[-164.63641357421875,62.417497634887695],[-164.852783203125,62.57027626037598],[-164.479154586792,62.74582862854004],[-164.87777709960938,62.83555030822754],[-164.31832885742188,63.00694465637207],[-164.41055297851562,63.21193885803223],[-163.11166381835938,63.05193519592285],[-162.31195068359375,63.54110908508301],[-161.15167236328125,63.51249885559082],[-160.77749633789062,63.868600845336914],[-161.5291748046875,64.41887092590332],[-160.78390502929688,64.72192573547363],[-161.1824951171875,64.93748664855957],[-162.790283203125,64.33610725402832],[-163.17001342773438,64.65526008605957],[-163.17584228515625,64.4074878692627],[-166.12136840820312,64.57470893859863],[-166.96194458007812,65.18887519836426],[-166.05889892578125,65.25610542297363],[-168.131103515625,65.6655445098877],[-164.35360717773438,66.59471321105957],[-163.625,66.56721687316895],[-164.18832397460938,66.19609260559082],[-163.65640258789062,66.07054328918457],[-161.00335693359375,66.20416450500488],[-161.91000366210938,66.2744312286377],[-161.9061279296875,66.53526496887207],[-162.63613891601562,66.86886787414551],[-162.33694458007812,66.95833015441895],[-161.60055541992188,66.44775581359863],[-160.23056030273438,66.39972114562988],[-160.26419067382812,66.64749336242676],[-161.50668334960938,66.53387641906738],[-161.89779663085938,66.72831916809082],[-161.50112915039062,66.97915840148926],[-162.46112060546875,66.99247932434082],[-162.35055541992188,67.16137886047363],[-163.73248291015625,67.11360359191895],[-164.1241455078125,67.60998725891113],[-166.82778930664062,68.35081672668457],[-166.3726043701172,68.4167652130127],[-166.2158203125,68.88304328918457],[-163.64529418945312,69.10693550109863],[-161.94223022460938,70.30720710754395],[-162.11886596679688,70.15165901184082],[-159.9375,70.59332466125488],[-160.1986083984375,70.47165107727051],[-159.83612060546875,70.2683277130127],[-159.28555297851562,70.53055000305176],[-160.12442016601562,70.61526679992676],[-159.66806030273438,70.79803657531738],[-157.97943115234375,70.83749580383301],[-156.44696044921875,71.26361274719238]],[[-135.55416870117188,58.32999610900879],[-135.62527465820312,58.3830509185791],[-135.72610473632812,58.35943794250488],[-135.55416870117188,58.32999610900879]]]]}},{"type":"Feature","properties":{"name":"Burkina Faso","iso2":"BF","iso3":"BFA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-2.834048,11.002007],[-2.685561,9.481817],[-3.633611,9.954443000000111],[-4.704445,9.698055],[-5.51985,10.436272],[-5.273056,11.843887],[-4.4175,12.300831],[-4.337223,13.121666],[-3.964253,13.50383],[-3.437675,13.166498],[-3.2575,13.696665],[-2.879167,13.655554],[-2.474722,14.287498],[-2.006945,14.187777],[-1.980834,14.474722],[-0.725278,15.082777],[0.235048,14.915068],[0.602222,13.703888],[1.285306,13.349957],[0.991667,13.371666],[0.989167,13.047222],[1.578333,12.629999],[2.1425,12.694443],[2.397925,11.896152],[2.014722,11.422499],[1.435278,11.458887],[0.91797,10.996399],[-0.149762,11.13854],[-0.618333,10.911665],[-2.834048,11.002007]]]]}},{"type":"Feature","properties":{"name":"Uruguay","iso2":"UY","iso3":"URY"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-57.806396,-30.748219],[-57.608002,-30.184925],[-56.811394,-30.105278],[-56.008923,-31.079794],[-55.581947,-30.845837],[-53.879723,-31.967781],[-53.093056,-32.729729],[-53.522781,-33.147781],[-53.374298,-33.740669],[-54.145004,-34.671394],[-56.320282,-34.910561],[-57.117783,-34.462227],[-57.840279,-34.494728],[-58.402779,-33.929726],[-58.361946,-33.133339],[-58.146393,-33.101952],[-58.045563,-32.934723],[-58.199242,-32.45031],[-57.806396,-30.748219]]]]}},{"type":"Feature","properties":{"name":"Uzbekistan","iso2":"UZ","iso3":"UZB"},"geometry":{"type":"MultiPolygon","coordinates":[[[[64.383026,38.953125],[62.551102,39.934158],[61.874161,41.125549],[60.14027400000012,41.381104],[60.014442,42.217491],[58.780548,42.658043],[58.16443600000011,42.651932],[58.51554900000011,42.304436],[58.02660400000016,42.504639],[56.986938,41.893051],[57.044716,41.260277],[56.000961,41.32845300000015],[55.99749,45.001106],[58.569717,45.571106],[62.025108,43.484787],[64.931366,43.73777],[65.82193,42.877213],[66.123871,42.99694100000012],[66.02916,42.003052],[66.526382,42.003052],[66.7199860000002,41.174995],[67.935532,41.183327],[68.455261,40.59777100000012],[69.05636600000011,41.379433000000105],[70.97081,42.254669],[71.276382,42.195511],[70.187195,41.52829],[71.418045,41.118553],[71.69136,41.556335],[72.19548,41.006592],[73.173035,40.822998],[71.710541,40.145767],[70.98204,40.244843],[70.375534,40.376404],[70.796799,40.725594],[70.423874,41.049118],[69.732483,40.638603],[69.356094,40.772491],[69.308029,40.201385],[68.600815,40.178329],[69.009995,40.089714],[68.540268,39.55471],[67.441956,39.483582],[67.376373,39.212494],[68.123871,38.98555],[68.384155,38.195541],[67.779877,37.185822],[66.537735,37.366379],[66.64387500000012,38.003052000000125],[64.383026,38.953125]]]]}},{"type":"Feature","properties":{"name":"Saint Vincent and the Grenadines","iso2":"VC","iso3":"VCT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-61.416946,12.590277],[-61.45417,12.593887],[-61.425835,12.612499],[-61.416946,12.590277]]],[[[-61.32805599999989,12.687777],[-61.347778,12.701666],[-61.31056199999989,12.734999],[-61.32805599999989,12.687777]]],[[[-61.216667,12.998055],[-61.252228,12.988609],[-61.199722,13.044722],[-61.216667,12.998055]]],[[[-61.173058,13.1325],[-61.28139499999989,13.207777000000164],[-61.177223,13.384165],[-61.173058,13.1325]]]]}},{"type":"Feature","properties":{"name":"Venezuela","iso2":"VE","iso3":"VEN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-61.00361633300781,8.548887252807617],[-61.266395568847656,8.509164810180664],[-61.080833435058594,8.61027717590332],[-61.00361633300781,8.548887252807617]]],[[[-61.04778289794922,8.629446029663086],[-61.1844482421875,8.598611831665039],[-61.16722869873047,8.651945114135742],[-61.04778289794922,8.629446029663086]]],[[[-61.04194641113281,8.640275955200195],[-61.146949768066406,8.654443740844727],[-61.17778015136719,8.679445266723633],[-60.9344482421875,8.718332290649414],[-61.04194641113281,8.640275955200195]]],[[[-60.82722473144531,8.649442672729492],[-60.988616943359375,8.635557174682617],[-60.84083557128906,8.728055953979492],[-60.82722473144531,8.649442672729492]]],[[[-60.976112365722656,8.725831985473633],[-61.17028045654297,8.693334579467773],[-61.042503356933594,8.821111679077148],[-60.860557556152344,8.853334426879883],[-60.976112365722656,8.725831985473633]]],[[[-61.070556640625,8.892499923706055],[-61.09972381591797,8.891111373901367],[-61.065834045410156,8.976945877075195],[-60.84861755371094,9.093610763549805],[-61.070556640625,8.892499923706055]]],[[[-60.87028503417969,9.108331680297852],[-60.9586181640625,9.066946029663086],[-60.863616943359375,9.193334579467773],[-60.87028503417969,9.108331680297852]]],[[[-60.730003356933594,9.18638801574707],[-60.841392517089844,9.116666793823242],[-60.822784423828125,9.201665878295898],[-60.730003356933594,9.18638801574707]]],[[[-62.288612365722656,9.755556106567383],[-62.28639221191406,9.934167861938477],[-62.249168395996094,9.856943130493164],[-62.288612365722656,9.755556106567383]]],[[[-62.64750671386719,10.302499771118164],[-62.788063049316406,10.414999008178711],[-62.78722381591797,10.478612899780273],[-62.64750671386719,10.302499771118164]]],[[[-63.9072265625,10.72944450378418],[-63.996673583984375,10.802221298217773],[-63.90666961669922,10.777498245239258],[-63.9072265625,10.72944450378418]]],[[[-65.26861572265625,10.881109237670898],[-65.417236328125,10.924722671508789],[-65.21194458007812,10.956110000610352],[-65.26861572265625,10.881109237670898]]],[[[-63.804725646972656,11.021387100219727],[-64.40583801269531,10.967500686645508],[-63.88111114501953,11.176942825317383],[-63.804725646972656,11.021387100219727]]],[[[-66.64834594726562,11.758611679077148],[-66.61056518554688,11.821111679077148],[-66.58639526367188,11.771665573120117],[-66.64834594726562,11.758611679077148]]],[[[-66.1158447265625,11.773611068725586],[-66.19306945800781,11.817220687866211],[-66.10861206054688,11.825555801391602],[-66.1158447265625,11.773611068725586]]],[[[-64.57223510742188,11.80555534362793],[-64.64389038085938,11.82472038269043],[-64.61500358581543,11.89555549621582],[-64.57223510742188,11.80555534362793]]],[[[-69.77084350585938,11.696111679077148],[-68.4183349609375,11.179998397827148],[-68.16000366210938,10.496946334838867],[-66.23529052734375,10.642221450805664],[-65.08139038085938,10.060556411743164],[-63.69750213623047,10.485555648803711],[-64.25889587402344,10.661664962768555],[-61.882781982421875,10.733331680297852],[-62.91667175292969,10.528055191040039],[-63.000282287597656,10.271665573120117],[-62.78212356567383,10.399694442749023],[-62.62805938720703,10.107778549194336],[-63.01722717285156,10.097776412963867],[-62.80528259277344,10.008611679077148],[-62.61750030517578,10.089723587036133],[-62.61333465576172,10.222776412963867],[-62.5352783203125,10.20222282409668],[-62.31806182861328,9.704999923706055],[-62.2005615234375,9.905553817749023],[-62.210838317871094,9.634443283081055],[-62.18861389160156,10.015832901000977],[-61.738616943359375,9.595556259155273],[-61.62250518798828,9.906110763549805],[-60.85028076171875,9.440832138061523],[-60.78361511230469,9.304998397827148],[-61.08222961425781,9.10222053527832],[-60.94972229003906,9.179445266723633],[-61.0977783203125,8.963335037231445],[-61.208892822265625,8.595556259155273],[-61.59889221191406,8.554998397827148],[-61.073890686035156,8.400835037231445],[-60.90222930908203,8.582223892211914],[-59.99028015136719,8.535276412963867],[-59.8255615234375,8.236112594604492],[-60.71916961669922,7.535554885864258],[-60.288612365722656,7.057222366333008],[-61.13402557373047,6.711042404174805],[-61.38972473144531,5.940000534057617],[-60.730369567871094,5.204801559448242],[-60.57972717285156,4.94666862487793],[-60.98500061035156,4.52055549621582],[-62.74583435058594,4.032499313354492],[-62.875,3.560277938842773],[-63.343055725097656,3.961111068725586],[-64.01779174804688,3.886110305786133],[-64.7952880859375,4.281389236450195],[-64.19111633300781,3.594446182250977],[-64.04501342773438,2.482500076293945],[-63.361114501953125,2.419168472290039],[-63.39305877685547,2.151388168334961],[-65.51889038085938,0.649721145629883],[-65.58973693847656,0.989168167114258],[-66.31195068359375,0.750558853149414],[-66.87188720703125,1.221643447875977],[-67.1925048828125,2.392499923706055],[-67.82833862304688,2.825002670288086],[-67.29055786132812,3.397500991821289],[-67.85972595214844,4.558610916137695],[-67.45445251464844,6.193056106567383],[-69.24528503417969,6.081388473510742],[-70.11917114257812,6.975835800170898],[-72,7.018888473510742],[-72.4716796875,7.491945266723633],[-72.32528686523438,8.095556259155273],[-72.77972412109375,9.080278396606445],[-73.37806701660156,9.171388626098633],[-72.49305725097656,11.121110916137695],[-72.2093505859375,11.250001907348633],[-71.97723388671875,11.664999008178711],[-71.32472229003906,11.853055953979492],[-71.96833801269531,11.55583381652832],[-71.57695007324219,10.714445114135742],[-72.12750244140625,9.813055038452148],[-71.61805725097656,9.04194450378418],[-71.05528259277344,9.341390609741211],[-71.49751281738281,10.960000991821289],[-69.79861450195312,11.427778244018555],[-69.814453125,11.690832138061523],[-70.23834228515625,11.63166618347168],[-70.02694702148438,12.195276260375977],[-69.77084350585938,11.696111679077148]],[[-61.20667266845703,9.585832595825195],[-61.41166687011719,9.72972297668457],[-61.32695007324219,9.646665573120117],[-61.20667266845703,9.585832595825195]]]]}},{"type":"Feature","properties":{"name":"British Virgin Islands","iso2":"VG","iso3":"VGB"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-64.660843,18.383888],[-64.65251199999989,18.441109],[-64.558334,18.451942],[-64.660843,18.383888]]],[[[-64.422501,18.43861],[-64.412231,18.506107],[-64.322235,18.506107],[-64.422501,18.43861]]],[[[-64.31140099999988,18.746109],[-64.270004,18.696388],[-64.408066,18.735832],[-64.31140099999988,18.746109]]]]}},{"type":"Feature","properties":{"name":"Viet Nam","iso2":"VN","iso3":"VNM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[106.600273,8.647778],[106.555817,8.688887],[106.659378,8.764740000000103],[106.600273,8.647778]]],[[[103.4985960000001,9.31361],[103.469437,9.279444],[103.467209,9.304443],[103.4985960000001,9.31361]]],[[[106.26275600000011,9.528887],[106.088058,9.754438],[106.2855220000001,9.586943],[106.26275600000011,9.528887]]],[[[106.54357900000011,9.82583],[106.41857900000016,9.934443],[106.48578600000016,9.902222000000137],[106.54357900000011,9.82583]]],[[[106.59662600000016,10.257221000000115],[106.664413,10.243053],[106.586906,10.256943],[106.59662600000016,10.257221000000115]]],[[[106.63719200000017,10.269999],[106.75247200000015,10.234442],[106.511642,10.29361],[106.63719200000017,10.269999]]],[[[104.083862,10.361942],[104.02638200000015,10.080276],[103.837196,10.36944200000012],[104.083862,10.361942]]],[[[107.092468,10.32222],[107.063858,10.383333],[107.20636000000016,10.432775],[107.092468,10.32222]]],[[[106.89524800000018,10.372219],[106.88748200000012,10.510555],[106.97914100000011,10.408888],[106.89524800000018,10.372219]]],[[[108.958588,10.504166],[108.930252,10.510277],[108.930252,10.550276],[108.958588,10.504166]]],[[[106.904694,10.520832],[106.875793,10.530277],[106.851357,10.561943],[106.871384,10.595519],[106.852188,10.625553000000153],[106.87941000000015,10.63722],[106.92746,10.592775],[106.930252,10.544722],[106.904694,10.520832]]],[[[106.852188,10.403610000000128],[106.755539,10.481386],[106.749977,10.562498000000119],[106.786301,10.578066],[106.7532120000001,10.660968000000125],[106.856476,10.60388200000014],[106.835747,10.569703000000118],[106.87413,10.502499],[106.852188,10.403610000000128]]],[[[109.332764,12.187777],[109.245247,12.227497],[109.33148200000014,12.221088],[109.332764,12.187777]]],[[[109.3936,12.350275000000124],[109.387207,12.34972],[109.385269,12.366941],[109.3936,12.350275000000124]]],[[[107.919434,16.349442],[107.86692800000012,16.35944],[107.661217,16.572613],[107.919434,16.349442]]],[[[107.73027,20.127773],[107.711647,20.131939000000116],[107.7383120000002,20.144440000000102],[107.73027,20.127773]]],[[[107.378311,20.799164],[107.334991,20.846664],[107.382477,20.824165],[107.378311,20.799164]]],[[[107.068047,20.727493],[106.9080430000001,20.832218],[107.033867,20.856106],[107.068047,20.727493]]],[[[106.75277700000018,20.854164000000125],[106.719147,20.870831],[106.74108900000013,20.871109],[106.75277700000018,20.854164000000125]]],[[[106.873306,20.78722],[106.770828,20.852497],[106.78137200000012,20.922497],[106.873306,20.78722]]],[[[106.9480290000001,20.936382],[106.93221300000013,20.936939],[106.927467,20.944717],[106.9480290000001,20.936382]]],[[[107.4885860000002,20.839165],[107.464706,20.821384],[107.554153,20.966106000000124],[107.4885860000002,20.839165]]],[[[106.89388300000022,20.965549],[106.916656,20.954441],[106.888046,20.965549],[106.89388300000022,20.965549]]],[[[107.460823,20.942219],[107.454712,20.943886],[107.45498700000022,20.950272],[107.46219600000015,20.967495],[107.476089,20.972218000000126],[107.47831700000015,20.966106000000124],[107.4733120000001,20.954441],[107.460823,20.942219]]],[[[106.75360100000015,20.950829],[106.688873,20.956661],[106.67942800000017,20.97749300000011],[106.75360100000015,20.950829]]],[[[107.746933,20.937218],[107.747757,21.019165],[107.790817,20.981937000000116],[107.746933,20.937218]]],[[[107.462769,20.90304900000011],[107.39498900000015,20.896664000000115],[107.476723,20.946983],[107.502403,21.012671],[107.554428,21.038052],[107.462769,20.90304900000011]]],[[[107.859421,21.037777],[107.80693100000016,20.986938],[107.8311,21.034996],[107.859421,21.037777]]],[[[107.578323,20.977219],[107.567207,21.020554],[107.6207430000002,21.11783600000011],[107.578323,20.977219]]],[[[107.513321,21.128330000000105],[107.509163,21.133331],[107.53221100000016,21.145828],[107.513321,21.128330000000105]]],[[[107.383881,21.04638700000011],[107.47194700000014,21.27142],[107.604431,21.218884],[107.383881,21.04638700000011]]],[[[107.742752,21.308887000000126],[107.7083280000002,21.305275],[107.81804700000012,21.356384],[107.742752,21.308887000000126]]],[[[107.996643,21.39471800000011],[107.933319,21.364162],[107.828598,21.371384],[107.996643,21.39471800000011]]],[[[105.577477,23.059162000000143],[106.70720700000018,22.864998000000142],[106.693314,22.03083],[107.990021,21.542412],[107.414703,21.326107],[107.36998000000014,21.022221],[107.154427,20.924995000000152],[106.6438830000001,21.021385],[106.776932,20.69916200000013],[105.954163,19.92083000000015],[105.61387600000015,18.977219],[106.698868,17.399719],[108.830276,15.42083200000016],[109.466377,12.8933320000001],[109.145538,12.435555],[109.269989,11.892498],[109.17330900000016,12.120552],[109.021103,11.353331],[107.997742,10.699165],[107.26619000000014,10.376129],[106.999748,10.657166000000132],[106.961189,10.466075],[106.93219,10.567221000000103],[106.94329800000011,10.593609000000129],[106.904137,10.631386000000134],[106.744133,10.669998000000135],[106.770813,10.591108000000148],[106.73830400000011,10.560613000000117],[106.736359,10.513054],[106.591553,10.429691],[106.738571,10.469442],[106.79274,10.386944],[106.784698,10.277498],[106.424316,10.311384],[106.776367,10.079998],[106.290527,10.25083200000013],[106.618027,9.811388],[106.11718800000014,10.238331],[106.54303,9.583609],[105.820534,10.002499],[106.19412200000014,9.366941],[105.02110300000012,8.592775],[104.742752,8.604998000000151],[105.107468,9.945276],[104.445328,10.422739],[105.101913,10.955553],[106.203308,10.770554],[105.851067,11.659998],[106.458214,11.665863000000101],[106.420242,11.973608],[107.54749300000012,12.35360900000012],[107.489151,14.448608],[107.5466,14.708618],[107.695251,15.270832],[107.1755370000001,15.784164],[107.464706,16.078609000000128],[106.685532,16.45805],[106.561096,16.996941],[105.183319,18.334442],[105.193863,18.642494],[103.87943300000015,19.29361],[104.03724700000012,19.69294400000011],[104.640266,19.611942],[104.979156,20.004997],[104.3819270000001,20.444717],[104.6436,20.660275000000112],[104.109154,20.977219],[103.693588,20.657219],[103.170532,20.846664],[102.976089,21.739437],[102.676651,21.65583],[102.14074700000012,22.396286],[102.479713,22.773888],[103.030548,22.435551],[103.33638000000016,22.79638700000011],[103.964432,22.499111],[105.35386700000018,23.3347210000001],[105.577477,23.059162000000143]]]]}},{"type":"Feature","properties":{"name":"United States Virgin Islands","iso2":"VI","iso3":"VIR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-64.761948,17.774166],[-64.560287,17.748333],[-64.896118,17.67666600000014],[-64.761948,17.774166]]],[[[-64.665283,18.332222],[-64.79028299999987,18.33083],[-64.731949,18.371944],[-64.665283,18.332222]]],[[[-64.841675,18.312496],[-65.026947,18.36277800000012],[-64.9039,18.364719],[-64.841675,18.312496]]]]}},{"type":"Feature","properties":{"name":"Namibia","iso2":"NA","iso3":"NAM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[23.284721,-17.662502],[23.476109,-17.625835],[24.969997,-17.559723],[25.264431,-17.80225],[24.362499,-17.948612],[23.615578,-18.485069],[23.297108,-17.995949],[20.993286,-18.318417],[20.991943,-21.996948],[19.996666,-22.005001],[20.000942,-24.765408],[19.99612,-28.421448],[19.123055000000107,-28.962223],[18.175831,-28.908611],[17.40472,-28.713612],[17.06361,-28.028614],[16.48959,-28.578178],[15.294167,-27.322502],[14.463333,-24.109169],[14.511389,-22.55278],[11.804722,-18.081947],[11.752783000000107,-17.254833],[13.16055500000013,-16.952778],[13.993219,-17.423946],[18.451538,-17.389835],[18.915833000000134,-17.815556],[20.854164,-18.016392],[23.284721,-17.662502]]]]}},{"type":"Feature","properties":{"name":"Wallis and Futuna Islands","iso2":"WF","iso3":"WLF"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-178.042511,-14.319447],[-178.140564,-14.316389],[-178.189453,-14.236113],[-178.042511,-14.319447]]],[[[-176.161438,-13.352777],[-176.156158,-13.213614],[-176.121094,-13.263334],[-176.161438,-13.352777]]]]}},{"type":"Feature","properties":{"name":"Samoa","iso2":"WS","iso3":"WSM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-171.429749,-14.019724],[-172.064758,-13.874443],[-171.822266,-13.807503],[-171.429749,-14.019724]]],[[[-172.285858,-13.486387],[-172.214172,-13.807777],[-172.780609,-13.533335],[-172.285858,-13.486387]]]]}},{"type":"Feature","properties":{"name":"Swaziland","iso2":"SZ","iso3":"SWZ"},"geometry":{"type":"MultiPolygon","coordinates":[[[[30.902048,-26.305254],[31.33083,-25.751392],[31.96851,-25.95784],[32.1334,-26.839626],[31.987499,-27.316113],[31.161663,-27.203056],[30.818886000000106,-26.810558],[30.902048,-26.305254]]]]}},{"type":"Feature","properties":{"name":"Yemen","iso2":"YE","iso3":"YEM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[53.340828,12.108889],[53.25666,12.124998000000119],[53.291664,12.134443],[53.340828,12.108889]]],[[[53.085831,12.13361],[53.011383,12.158609],[53.09610700000016,12.175554],[53.085831,12.13361]]],[[[52.234161,12.201111],[52.395828,12.155277],[52.083054,12.222776],[52.234161,12.201111]]],[[[43.438606,12.631109],[43.396111000000104,12.666388],[43.443886000000106,12.659443],[43.438606,12.631109]]],[[[53.774719,12.616388000000114],[54.476944000000145,12.557777],[53.753609,12.308054000000126],[53.325829,12.545832000000104],[53.774719,12.616388000000114]]],[[[42.755829000000205,13.69861],[42.677216,13.666111],[42.793884,13.781111],[42.755829000000205,13.69861]]],[[[42.78749800000011,13.91],[42.689163,14.01361100000014],[42.766388,14.066944000000106],[42.78749800000011,13.91]]],[[[42.594719,15.271944000000147],[42.568886,15.3925],[42.642494,15.458332],[42.594719,15.271944000000147]]],[[[52.23194100000015,15.674166],[49.098885,14.519165],[48.69805100000022,14.039999],[45.666664,13.341665],[45.055443,12.751296],[43.957222,12.592777],[43.46721600000015,12.677776],[43.247498000000206,13.210278000000145],[42.681107,15.208332],[42.78968,16.377502],[43.206108,16.672222],[43.309441,17.4572220000001],[44.46749900000012,17.41194200000014],[46.333328,16.666664],[46.333054,15.616943],[48.766388,18.266388000000106],[51.99929,18.999344000000136],[53.114441,16.642778],[52.29888200000019,16.27222100000013],[52.23194100000015,15.674166]]]]}},{"type":"Feature","properties":{"name":"Zambia","iso2":"ZM","iso3":"ZMB"},"geometry":{"type":"MultiPolygon","coordinates":[[[[24.969997,-17.559723],[23.476109,-17.625835],[22.000149000000135,-16.171661],[21.998333,-13.004168],[24.020554,-13.00639],[23.986206,-10.870461],[24.44833,-11.463612],[25.332222000000115,-11.193335],[25.35972200000012,-11.641668],[26.004719,-11.9025],[26.86861,-11.973612],[27.199249,-11.567905],[27.66000000000011,-12.296667],[28.441944,-12.519724],[29.015831,-13.397779],[29.589443,-13.221945],[29.801388,-13.454168],[29.80505,-12.155247],[29.49361,-12.458057],[29.031387,-12.383057],[28.363331,-11.550835],[28.699718000000104,-10.653334],[28.372219,-9.260834],[28.901665,-8.478613],[30.77124000000012,-8.192247],[31.041111,-8.590279],[32.940399,-9.405077],[33.702278,-10.561857],[33.250549,-10.886667],[33.273331,-12.144445],[33.54583,-12.359446],[33.046387,-12.603889],[32.678886,-13.60639],[33.222229,-14.012566],[30.21301700000018,-14.981716],[30.415756,-15.631872],[28.927219,-15.972223],[28.759441,-16.552223],[27.825275,-16.959167],[27.038055,-17.959446],[25.264431,-17.80225],[24.969997,-17.559723]]]]}},{"type":"Feature","properties":{"name":"Zimbabwe","iso2":"ZW","iso3":"ZWE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[32.987808,-17.265003],[33.073051000000106,-18.348892],[32.699165,-18.944447],[33.0188830000001,-19.943336],[32.50222000000011,-20.598614],[32.488876,-21.344448],[31.297504000000146,-22.414764],[29.893887,-22.194447],[29.373623,-22.19241],[29.060555,-21.798058],[28.015831,-21.566113],[27.713165,-20.506432],[27.287453,-20.494965],[27.219997,-20.091667],[26.166111,-19.527779],[25.264431,-17.80225],[27.038055,-17.959446],[27.825275,-16.959167],[28.759441,-16.552223],[28.927219,-15.972223],[30.415756,-15.631872],[30.422775,-16.009167],[31.276665,-16.018612],[32.98114,-16.709053],[32.987808,-17.265003]]]]}},{"type":"Feature","properties":{"name":"Indonesia","iso2":"ID","iso3":"IDN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[121.85999488830566,-10.61027717590332],[121.6908130645752,-10.566389083862305],[121.99693489074707,-10.441110610961914],[121.85999488830566,-10.61027717590332]]],[[[123.21470832824707,-10.81222152709961],[122.80774879455566,-10.794723510742188],[123.39026832580566,-10.436944961547852],[123.21470832824707,-10.81222152709961]]],[[[123.40054512023926,-10.342777252197266],[123.30859565734863,-10.276666641235352],[123.45332527160645,-10.13972282409668],[123.40054512023926,-10.342777252197266]]],[[[120.02916145324707,-9.383333206176758],[120.81025886535645,-9.979166030883789],[120.72442817687988,-10.199722290039062],[120.16470527648926,-10.231388092041016],[118.93109321594238,-9.561111450195312],[120.02916145324707,-9.383333206176758]]],[[[125.16404914855957,-9.066141128540039],[125.12798881530762,-9.435955047607422],[124.43525886535645,-10.162778854370117],[123.48831367492676,-10.316389083862305],[124.04616355895996,-9.33997917175293],[124.34309577941895,-9.46337890625],[124.44572639465332,-9.18480110168457],[124.94544792175293,-8.954038619995117],[125.16404914855957,-9.066141128540039]]],[[[115.59471321105957,-8.804166793823242],[115.46999549865723,-8.734443664550781],[115.51249885559082,-8.670000076293945],[115.59471321105957,-8.804166793823242]]],[[[119.69053840637207,-8.802778244018555],[119.60748481750488,-8.773611068725586],[119.63305854797363,-8.60079574584961],[119.69053840637207,-8.802778244018555]]],[[[122.96943855285645,-8.572500228881836],[122.98803901672363,-8.456666946411133],[123.17775917053223,-8.442222595214844],[122.96943855285645,-8.572500228881836]]],[[[119.46164894104004,-8.440277099609375],[119.58554267883301,-8.563055038452148],[119.44719886779785,-8.754167556762695],[119.46164894104004,-8.440277099609375]]],[[[113.38889503479004,-8.497220993041992],[113.29553413391113,-8.500556945800781],[113.28581428527832,-8.440000534057617],[113.38889503479004,-8.497220993041992]]],[[[124.2905445098877,-8.329166412353516],[124.11525917053223,-8.55555534362793],[123.90693855285645,-8.452499389648438],[124.2905445098877,-8.329166412353516]]],[[[123.76442909240723,-8.32722282409668],[123.21748542785645,-8.536666870117188],[123.93914985656738,-8.242498397827148],[123.76442909240723,-8.32722282409668]]],[[[123.28109931945801,-8.405834197998047],[123.01609992980957,-8.378055572509766],[123.22083473205566,-8.233610153198242],[123.28109931945801,-8.405834197998047]]],[[[128.21997261047363,-8.210556030273438],[128.20831489562988,-8.287221908569336],[128.07995796203613,-8.259445190429688],[128.21997261047363,-8.210556030273438]]],[[[116.54915046691895,-8.775001525878906],[115.84414863586426,-8.755279541015625],[116.38749885559082,-8.204999923706055],[116.73581123352051,-8.363054275512695],[116.54915046691895,-8.775001525878906]]],[[[127.66832160949707,-8.244443893432617],[127.60582160949707,-8.20694351196289],[127.77110481262207,-8.188888549804688],[127.66832160949707,-8.244443893432617]]],[[[129.0080280303955,-8.269445419311523],[128.82831001281738,-8.198888778686523],[128.9696979522705,-8.183889389038086],[129.0080280303955,-8.269445419311523]]],[[[117.54081916809082,-8.390277862548828],[117.48137092590332,-8.191389083862305],[117.67581367492676,-8.156110763549805],[117.54081916809082,-8.390277862548828]]],[[[138.87356758117676,-8.414722442626953],[138.54471015930176,-8.333053588867188],[138.81414985656738,-8.154722213745117],[138.87356758117676,-8.414722442626953]]],[[[118.31192207336426,-8.37472152709961],[118.6483325958252,-8.294445037841797],[118.66609382629395,-8.552223205566406],[118.99693489074707,-8.31361198425293],[119.17804145812988,-8.720277786254883],[118.45720863342285,-8.871944427490234],[118.40637397766113,-8.584722518920898],[118.15498542785645,-8.871944427490234],[116.75139045715332,-9.009445190429688],[117.12275886535645,-8.378610610961914],[117.96637916564941,-8.74860954284668],[118.2844181060791,-8.594165802001953],[117.73552894592285,-8.152223587036133],[118.31192207336426,-8.37472152709961]]],[[[122.98108863830566,-8.149444580078125],[122.83249092102051,-8.601663589477539],[121.76555061340332,-8.892223358154297],[119.79623603820801,-8.720342636108398],[120.52249336242676,-8.257223129272461],[122.28830909729004,-8.644445419311523],[122.98108863830566,-8.149444580078125]]],[[[124.57776832580566,-8.135833740234375],[125.13971138000488,-8.329166412353516],[124.35080909729004,-8.454444885253906],[124.57776832580566,-8.135833740234375]]],[[[125.58167457580566,-8.317499160766602],[125.49609565734863,-8.269445419311523],[125.6413745880127,-8.135833740234375],[125.58167457580566,-8.317499160766602]]],[[[119.07248878479004,-8.267499923706055],[119.07859992980957,-8.133890151977539],[119.13693428039551,-8.195554733276367],[119.07248878479004,-8.267499923706055]]],[[[115.5022144317627,-8.178611755371094],[115.70776557922363,-8.40916633605957],[115.12608528137207,-8.854166030883789],[114.44553565979004,-8.104721069335938],[115.5022144317627,-8.178611755371094]]],[[[127.84359931945801,-8.101110458374023],[128.12744331359863,-8.171667098999023],[128.02527046203613,-8.267499923706055],[127.84359931945801,-8.101110458374023]]],[[[130.80414009094238,-8.352222442626953],[131.013032913208,-8.0897216796875],[131.180269241333,-8.129720687866211],[130.80414009094238,-8.352222442626953]]],[[[127.2138843536377,-8.113332748413086],[127.15305519104004,-8.099166870117188],[127.18166542053223,-8.02194595336914],[127.2138843536377,-8.113332748413086]]],[[[129.76443672180176,-8.061111450195312],[129.6069049835205,-7.803888320922852],[129.84329414367676,-7.840555191040039],[129.76443672180176,-8.061111450195312]]],[[[126.72136878967285,-7.673055648803711],[125.77221870422363,-8.008890151977539],[125.97221565246582,-7.658611297607422],[126.72136878967285,-7.673055648803711]]],[[[130.98913764953613,-7.723333358764648],[130.98413276672363,-7.664165496826172],[131.12884712219238,-7.626665115356445],[130.98913764953613,-7.723333358764648]]],[[[127.38109016418457,-7.658611297607422],[127.36804389953613,-7.513889312744141],[127.48193550109863,-7.528888702392578],[127.38109016418457,-7.658611297607422]]],[[[138.96829414367676,-7.556110382080078],[138.44470405578613,-8.383333206176758],[137.63525581359863,-8.430000305175781],[138.15469551086426,-7.513889312744141],[138.96829414367676,-7.556110382080078]]],[[[130.8649616241455,-7.494165420532227],[130.98358345031738,-7.520833969116211],[130.84442329406738,-7.547222137451172],[130.8649616241455,-7.494165420532227]]],[[[131.07275581359863,-7.511388778686523],[131.00332832336426,-7.424999237060547],[131.1774616241455,-7.408611297607422],[131.07275581359863,-7.511388778686523]]],[[[121.77858924865723,-7.424444198608398],[121.76193428039551,-7.359165191650391],[121.83055305480957,-7.342777252197266],[121.77858924865723,-7.424444198608398]]],[[[121.10832405090332,-7.394443511962891],[121.09332466125488,-7.304721832275391],[121.16858863830566,-7.352222442626953],[121.10832405090332,-7.394443511962891]]],[[[131.27276802062988,-7.372776031494141],[131.216646194458,-7.359165191650391],[131.263032913208,-7.300554275512695],[131.27276802062988,-7.372776031494141]]],[[[120.93137550354004,-7.283611297607422],[121.06360054016113,-7.304721832275391],[120.78970527648926,-7.277500152587891],[120.93137550354004,-7.283611297607422]]],[[[131.73608589172363,-7.214166641235352],[131.10968208312988,-8.000833511352539],[131.24328804016113,-7.479999542236328],[131.73608589172363,-7.214166641235352]]],[[[131.92718696594238,-7.106943130493164],[131.968843460083,-7.254444122314453],[131.72857856750488,-7.158611297607422],[131.92718696594238,-7.106943130493164]]],[[[114.4024829864502,-7.181110382080078],[114.29332160949707,-7.082500457763672],[114.37024879455566,-7.066110610961914],[114.4024829864502,-7.181110382080078]]],[[[128.639986038208,-7.219165802001953],[128.5260944366455,-7.143611907958984],[128.61523628234863,-7.064722061157227],[128.639986038208,-7.219165802001953]]],[[[120.74165534973145,-7.075555801391602],[120.66914558410645,-7.145553588867188],[120.63054084777832,-7.016387939453125],[120.74165534973145,-7.075555801391602]]],[[[113.99136543273926,-6.880277633666992],[113.50388526916504,-7.225276947021484],[112.6877613067627,-7.051111221313477],[113.99136543273926,-6.880277633666992]]],[[[115.2933292388916,-6.83879280090332],[115.57083320617676,-6.925832748413086],[115.29109382629395,-7.008333206176758],[115.2933292388916,-6.83879280090332]]],[[[138.690523147583,-6.761388778686523],[138.78665351867676,-6.84083366394043],[138.61108589172363,-6.736110687255859],[138.690523147583,-6.761388778686523]]],[[[131.59219551086426,-6.678888320922852],[131.62634468078613,-6.707500457763672],[131.53579902648926,-6.801387786865234],[131.59219551086426,-6.678888320922852]]],[[[134.66885566711426,-6.774166107177734],[134.62634468078613,-6.715555191040039],[134.69775581359863,-6.586387634277344],[134.66885566711426,-6.774166107177734]]],[[[105.19304084777832,-6.684444427490234],[105.11303901672363,-6.611665725708008],[105.25360298156738,-6.5272216796875],[105.19304084777832,-6.684444427490234]]],[[[134.68387031555176,-6.56110954284668],[134.6833209991455,-6.451665878295898],[134.746919631958,-6.523056030273438],[134.68387031555176,-6.56110954284668]]],[[[134.58609199523926,-6.391666412353516],[134.5422077178955,-6.535833358764648],[134.34552192687988,-6.356943130493164],[134.58609199523926,-6.391666412353516]]],[[[134.83191108703613,-6.471944808959961],[134.78802680969238,-6.393054962158203],[134.858003616333,-6.289443969726563],[134.83191108703613,-6.471944808959961]]],[[[134.34411811828613,-6.804166793823242],[134.06720161437988,-6.826665878295898],[134.1027545928955,-6.173055648803711],[134.51471138000488,-6.584999084472656],[134.34411811828613,-6.804166793823242]]],[[[134.15637397766113,-6.04749870300293],[134.40359687805176,-6.286109924316406],[134.133882522583,-6.154722213745117],[134.15637397766113,-6.04749870300293]]],[[[134.73135566711426,-6.036666870117188],[134.60302925109863,-6.370553970336914],[134.2680377960205,-6.117221832275391],[134.73135566711426,-6.036666870117188]]],[[[106.16330909729004,-6.014165878295898],[108.31109809875488,-6.260278701782227],[108.73442268371582,-6.814998626708984],[110.39082527160645,-6.979721069335938],[110.91998481750488,-6.409999847412109],[111.15277290344238,-6.69999885559082],[112.56025886535645,-6.912221908569336],[112.84554481506348,-7.599721908569336],[114.44832038879395,-7.800554275512695],[114.37164497375488,-8.521112442016602],[114.62109565734863,-8.746665954589844],[113.23275947570801,-8.281112670898438],[111.65109443664551,-8.362499237060547],[109.28970527648926,-7.699443817138672],[108.16304206848145,-7.783054351806641],[106.42331123352051,-7.371387481689453],[106.50943183898926,-6.979166030883789],[105.24331855773926,-6.810277938842773],[106.16330909729004,-6.014165878295898]]],[[[124.05832099914551,-6.0272216796875],[123.96582221984863,-5.948055267333984],[123.97664833068848,-5.875831604003906],[124.05832099914551,-6.0272216796875]]],[[[120.48193550109863,-6.483610153198242],[120.47998237609863,-5.766666412353516],[120.56137275695801,-6.024444580078125],[120.48193550109863,-6.483610153198242]]],[[[104.83611488342285,-5.828056335449219],[104.76888465881348,-5.747777938842773],[104.84832954406738,-5.774999618530273],[104.83611488342285,-5.828056335449219]]],[[[112.69275093078613,-5.852775573730469],[112.58777046203613,-5.843889236450195],[112.63498878479004,-5.739442825317383],[112.69275093078613,-5.852775573730469]]],[[[132.74133491516113,-5.950277328491211],[132.69330024719238,-5.59638786315918],[132.8083209991455,-5.806943893432617],[132.74133491516113,-5.950277328491211]]],[[[132.79553413391113,-5.68638801574707],[132.73855781555176,-5.639165878295898],[132.781099319458,-5.532777786254883],[132.79553413391113,-5.68638801574707]]],[[[132.34051704406738,-5.57722282409668],[132.30191230773926,-5.517221450805664],[132.37661933898926,-5.538331985473633],[132.34051704406738,-5.57722282409668]]],[[[123.8108081817627,-5.599166870117188],[123.68831062316895,-5.472221374511719],[123.80275917053223,-5.533611297607422],[123.8108081817627,-5.599166870117188]]],[[[134.57718086242676,-5.430000305175781],[134.73135566711426,-5.974721908569336],[134.30218696594238,-6.025833129882813],[134.20633125305176,-5.708053588867188],[134.57718086242676,-5.430000305175781]]],[[[102.38498878479004,-5.485832214355469],[102.10054206848145,-5.332500457763672],[102.38081550598145,-5.372499465942383],[102.38498878479004,-5.485832214355469]]],[[[132.84939765930176,-6.003334045410156],[133.16885566711426,-5.295555114746094],[133.111909866333,-5.591667175292969],[132.84939765930176,-6.003334045410156]]],[[[123.62581062316895,-5.376665115356445],[123.52110481262207,-5.251943588256836],[123.62719917297363,-5.282499313354492],[123.62581062316895,-5.376665115356445]]],[[[122.01693916320801,-5.474166870117188],[121.80859565734863,-5.272222518920898],[121.91330909729004,-5.058610916137695],[122.01693916320801,-5.474166870117188]]],[[[115.78249549865723,-4.831943511962891],[115.8530445098877,-4.747220993041992],[115.85247993469238,-4.785554885864258],[115.78249549865723,-4.831943511962891]]],[[[131.74218940734863,-4.768610000610352],[131.72162055969238,-4.691944122314453],[131.75442695617676,-4.723333358764648],[131.74218940734863,-4.768610000610352]]],[[[122.73776435852051,-4.651111602783203],[122.60555458068848,-5.420276641845703],[122.28499031066895,-5.385000228881836],[122.37109565734863,-4.759721755981445],[122.73776435852051,-4.651111602783203]]],[[[129.934419631958,-4.566387176513672],[129.85913276672363,-4.556665420532227],[129.938570022583,-4.507499694824219],[129.934419631958,-4.566387176513672]]],[[[129.87466621398926,-4.530832290649414],[129.86108589172363,-4.521389007568359],[129.87967109680176,-4.505556106567383],[129.87466621398926,-4.530832290649414]]],[[[123.21277046203613,-4.697498321533203],[122.97971534729004,-5.107221603393555],[123.21555519104004,-5.29749870300293],[122.6513843536377,-5.68638801574707],[122.90358924865723,-4.48499870300293],[123.21277046203613,-4.697498321533203]]],[[[131.670259475708,-4.536943435668945],[131.61050605773926,-4.428333282470703],[131.672212600708,-4.487220764160156],[131.670259475708,-4.536943435668945]]],[[[133.57525825500488,-4.251943588256836],[133.61551094055176,-4.300554275512695],[133.31414985656738,-4.10444450378418],[133.57525825500488,-4.251943588256836]]],[[[131.3427448272705,-4.117498397827148],[131.3044147491455,-4.124164581298828],[131.27276802062988,-4.073610305786133],[131.3427448272705,-4.117498397827148]]],[[[123.08859443664551,-4.008888244628906],[123.15387153625488,-4.241666793823242],[122.95776557922363,-4.100276947021484],[123.08859443664551,-4.008888244628906]]],[[[101.0344181060791,-4.025833129882813],[101.0274829864502,-4.005277633666992],[101.0486011505127,-3.994998931884766],[101.0344181060791,-4.025833129882813]]],[[[131.24469184875488,-4.045555114746094],[131.2096881866455,-3.983331680297852],[131.24469184875488,-4.001943588256836],[131.24469184875488,-4.045555114746094]]],[[[131.43579292297363,-4.076389312744141],[131.37884712219238,-3.960832595825195],[131.41943550109863,-3.960277557373047],[131.43579292297363,-4.076389312744141]]],[[[134.15970039367676,-3.934999465942383],[134.19940376281738,-3.991109848022461],[134.07275581359863,-3.934165954589844],[134.15970039367676,-3.934999465942383]]],[[[127.22831916809082,-3.904167175292969],[127.14888191223145,-3.830278396606445],[127.23387336730957,-3.827499389648438],[127.22831916809082,-3.904167175292969]]],[[[128.779146194458,-3.703887939453125],[128.74829292297363,-3.643054962158203],[128.79080390930176,-3.638889312744141],[128.779146194458,-3.703887939453125]]],[[[123.12552833557129,-3.626667022705078],[123.05774879455566,-3.578056335449219],[123.14777565002441,-3.543054580688477],[123.12552833557129,-3.626667022705078]]],[[[128.40277290344238,-3.640832901000977],[128.43109321594238,-3.522499084472656],[128.56329536437988,-3.576665878295898],[128.40277290344238,-3.640832901000977]]],[[[122.35193061828613,-3.560832977294922],[122.27998542785645,-3.572500228881836],[122.32053565979004,-3.514919281005859],[122.35193061828613,-3.560832977294922]]],[[[128.33496284484863,-3.625831604003906],[127.91832160949707,-3.740833282470703],[128.27331733703613,-3.512222290039063],[128.33496284484863,-3.625831604003906]]],[[[128.66470527648926,-3.538331985473633],[128.720796585083,-3.619165420532227],[128.55496406555176,-3.509721755981445],[128.66470527648926,-3.538331985473633]]],[[[132.7035846710205,-3.5191650390625],[132.62329292297363,-3.421388626098633],[132.67413520812988,-3.418609619140625],[132.7035846710205,-3.5191650390625]]],[[[122.44525337219238,-3.490554809570313],[122.41304206848145,-3.384445190429688],[122.4719181060791,-3.456943511962891],[122.44525337219238,-3.490554809570313]]],[[[116.38275337219238,-3.645553588867188],[116.31694221496582,-3.537500381469727],[116.41693305969238,-3.377498626708984],[116.38275337219238,-3.645553588867188]]],[[[127.63275337219238,-3.365278244018555],[127.48108863830566,-3.293333053588867],[127.5697193145752,-3.263889312744141],[127.63275337219238,-3.365278244018555]]],[[[116.11831855773926,-4.036109924316406],[116.00861549377441,-3.649166107177734],[116.26776313781738,-3.223054885864258],[116.11831855773926,-4.036109924316406]]],[[[127.77026557922363,-3.254444122314453],[127.63611030578613,-3.225831985473633],[127.75943183898926,-3.153055191040039],[127.77026557922363,-3.254444122314453]]],[[[100.5244312286377,-3.186166763305664],[100.49080848693848,-3.162776947021484],[100.50055122375488,-3.127222061157227],[100.5244312286377,-3.186166763305664]]],[[[126.99387550354004,-3.145000457763672],[127.23665046691895,-3.617500305175781],[126.7008228302002,-3.834444046020508],[126.01748847961426,-3.35444450378418],[126.1030445098877,-3.100555419921875],[126.99387550354004,-3.145000457763672]]],[[[127.88472175598145,-3.038331985473633],[127.82054328918457,-3.021665573120117],[127.99165534973145,-2.930000305175781],[127.88472175598145,-3.038331985473633]]],[[[106.88916206359863,-3.024444580078125],[106.72136878967285,-2.966388702392578],[106.81247901916504,-2.893054962158203],[106.88916206359863,-3.024444580078125]]],[[[129.8124713897705,-2.919721603393555],[130.58413887023926,-3.133333206176758],[130.82995796203613,-3.872776031494141],[129.89749336242676,-3.335832595825195],[128.87829780578613,-3.20777702331543],[128.46246528625488,-3.458332061767578],[128.17386054992676,-3.068887710571289],[127.90609931945801,-3.537500381469727],[128.17386054992676,-2.855554580688477],[129.8124713897705,-2.919721603393555]]],[[[107.42720222473145,-2.938888549804688],[107.36136817932129,-2.871110916137695],[107.48137092590332,-2.823333740234375],[107.42720222473145,-2.938888549804688]]],[[[107.07971382141113,-2.911664962768555],[107.03720283508301,-2.864999771118164],[107.0727710723877,-2.819999694824219],[107.07971382141113,-2.911664962768555]]],[[[100.46277046203613,-3.133333206176758],[100.45942878723145,-3.333889007568359],[100.17637825012207,-2.799999237060547],[100.46277046203613,-3.133333206176758]]],[[[131.579683303833,-2.656389236450195],[131.56524848937988,-2.651666641235352],[131.65442085266113,-2.621389389038086],[131.579683303833,-2.656389236450195]]],[[[107.83276557922363,-2.534999847412109],[108.26582527160645,-2.755556106567383],[108.07332038879395,-3.23527717590332],[107.60942268371582,-3.211387634277344],[107.83276557922363,-2.534999847412109]]],[[[100.03109931945801,-2.841943740844727],[99.9871997833252,-2.489166259765625],[100.21415901184082,-2.718610763549805],[100.03109931945801,-2.841943740844727]]],[[[133.59497261047363,-2.525554656982422],[133.499116897583,-2.425556182861328],[133.61441230773926,-2.477499008178711],[133.59497261047363,-2.525554656982422]]],[[[99.74109077453613,-2.376388549804688],[99.70359992980957,-2.342777252197266],[99.7371997833252,-2.350276947021484],[99.74109077453613,-2.376388549804688]]],[[[134.567476272583,-2.453054428100586],[134.51666450500488,-2.396944046020508],[134.56884956359863,-2.292778015136719],[134.567476272583,-2.453054428100586]]],[[[123.16693305969238,-2.19416618347168],[123.15165901184082,-2.19416618347168],[123.16805458068848,-2.176387786865234],[123.16693305969238,-2.19416618347168]]],[[[123.44978523254395,-2.125568389892578],[123.43802833557129,-2.11138916015625],[123.45610237121582,-2.115554809570313],[123.44978523254395,-2.125568389892578]]],[[[99.85971260070801,-2.370832443237305],[99.56999397277832,-2.222221374511719],[99.56860542297363,-2.029167175292969],[99.85971260070801,-2.370832443237305]]],[[[123.88553810119629,-2.075555801391602],[123.84443855285645,-2.053888320922852],[123.86499214172363,-2.008609771728516],[123.88553810119629,-2.075555801391602]]],[[[134.36883735656738,-2.158054351806641],[134.325532913208,-2.08860969543457],[134.38580513000488,-2.003889083862305],[134.36883735656738,-2.158054351806641]]],[[[123.76776313781738,-2.04749870300293],[123.75833320617676,-2.02027702331543],[123.7774829864502,-1.998332977294922],[123.76776313781738,-2.04749870300293]]],[[[126.05664253234863,-2.482500076293945],[125.89470863342285,-2.213333129882813],[125.91805458068848,-1.972221374511719],[126.05664253234863,-2.482500076293945]]],[[[124.36665534973145,-2.011388778686523],[124.30081367492676,-1.976943969726563],[124.35721015930176,-1.966110229492188],[124.36665534973145,-2.011388778686523]]],[[[123.4780445098877,-1.946109771728516],[123.46692848205566,-1.943611145019531],[123.48471260070801,-1.935277938842773],[123.4780445098877,-1.946109771728516]]],[[[123.54498481750488,-1.927778244018555],[123.5355396270752,-1.924999237060547],[123.54305458068848,-1.913331985473633],[123.54498481750488,-1.927778244018555]]],[[[123.6594181060791,-1.963333129882813],[123.6513843536377,-1.953887939453125],[123.65416145324707,-1.901666641235352],[123.6594181060791,-1.963333129882813]]],[[[123.71692848205566,-1.955833435058594],[123.70054817199707,-1.936666488647461],[123.73221015930176,-1.899721145629883],[123.71692848205566,-1.955833435058594]]],[[[123.69109535217285,-1.914167404174805],[123.67249488830566,-1.899721145629883],[123.67249488830566,-1.884721755981445],[123.69109535217285,-1.914167404174805]]],[[[123.8288745880127,-2.010555267333984],[123.78276252746582,-1.878610610961914],[123.85550880432129,-1.954446792602539],[123.8288745880127,-2.010555267333984]]],[[[123.76500129699707,-1.877222061157227],[123.75749397277832,-1.873611450195313],[123.76721382141113,-1.862777709960938],[123.76500129699707,-1.877222061157227]]],[[[123.38690376281738,-1.883857727050781],[123.36693000793457,-1.875831604003906],[123.36831855773926,-1.856388092041016],[123.38690376281738,-1.883857727050781]]],[[[125.43831062316895,-1.806667327880859],[126.34915351867676,-1.823055267333984],[125.46666145324707,-1.939998626708984],[125.43831062316895,-1.806667327880859]]],[[[99.28610420227051,-1.826389312744141],[99.25193977355957,-1.820833206176758],[99.26915168762207,-1.789999008178711],[99.28610420227051,-1.826389312744141]]],[[[123.07916450500488,-1.906389236450195],[123.12082099914551,-1.754444122314453],[123.15416145324707,-1.832500457763672],[123.07916450500488,-1.906389236450195]]],[[[134.17608833312988,-1.944999694824219],[134.16052436828613,-1.845556259155273],[134.2338581085205,-1.740833282470703],[134.17608833312988,-1.944999694824219]]],[[[125.00665473937988,-1.718889236450195],[125.32332038879395,-1.887222290039063],[124.32747840881348,-1.879720687866211],[125.00665473937988,-1.718889236450195]]],[[[108.69693183898926,-1.723054885864258],[108.68193244934082,-1.699722290039063],[108.77971076965332,-1.704442977905273],[108.69693183898926,-1.723054885864258]]],[[[130.188570022583,-2.064167022705078],[129.7157917022705,-1.885831832885742],[130.3505573272705,-1.680204391479492],[130.188570022583,-2.064167022705078]]],[[[123.29776191711426,-1.791389465332031],[123.26748847961426,-1.766944885253906],[123.36971473693848,-1.673053741455078],[123.29776191711426,-1.791389465332031]]],[[[136.29358100891113,-1.688610076904297],[136.902193069458,-1.799165725708008],[135.41803169250488,-1.60999870300293],[136.29358100891113,-1.688610076904297]]],[[[108.84915351867676,-1.670831680297852],[108.79971504211426,-1.568056106567383],[108.93054389953613,-1.544166564941406],[108.84915351867676,-1.670831680297852]]],[[[106.09082221984863,-1.771665573120117],[106.31833076477051,-2.435832977294922],[106.78166389465332,-2.591943740844727],[106.60193061828613,-2.913055419921875],[106.71776008605957,-3.098333358764648],[105.97831916809082,-2.822776794433594],[105.74471473693848,-2.129165649414063],[105.13220405578613,-2.067499160766602],[105.57361030578613,-1.529167175292969],[106.09082221984863,-1.771665573120117]]],[[[135.13830757141113,-1.48527717590332],[135.33081245422363,-1.492776870727539],[135.09442329406738,-1.512777328491211],[135.13830757141113,-1.48527717590332]]],[[[127.87943458557129,-1.426942825317383],[128.14526557922363,-1.68055534362793],[127.3783130645752,-1.633888244628906],[127.87943458557129,-1.426942825317383]]],[[[127.32832527160645,-1.439998626708984],[127.27277565002441,-1.413331985473633],[127.36665534973145,-1.366109848022461],[127.32832527160645,-1.439998626708984]]],[[[109.14499092102051,-1.316665649414063],[109.10471534729004,-1.289999008178711],[109.1718921661377,-1.257776260375977],[109.14499092102051,-1.316665649414063]]],[[[123.19497871398926,-1.29749870300293],[123.53137397766113,-1.434720993041992],[122.8611011505127,-1.581110000610352],[122.89749336242676,-1.186666488647461],[123.19497871398926,-1.29749870300293]]],[[[127.61470222473145,-1.257778167724609],[127.45583534240723,-1.234443664550781],[127.55053901672363,-1.171667098999023],[127.61470222473145,-1.257778167724609]]],[[[109.22859382629395,-1.233331680297852],[109.21971321105957,-1.192777633666992],[109.25804328918457,-1.169443130493164],[109.22859382629395,-1.233331680297852]]],[[[129.92886543273926,-1.211387634277344],[129.74051094055176,-1.208610534667969],[129.86664009094238,-1.142778396606445],[129.92886543273926,-1.211387634277344]]],[[[109.62378883361816,-0.984834671020508],[109.77887153625488,-1.13861083984375],[109.41858863830566,-1.263334274291992],[109.49247932434082,-0.979721069335938],[109.62378883361816,-0.984834671020508]]],[[[98.92915534973145,-0.950277328491211],[99.23887825012207,-1.78388786315918],[98.6030445098877,-1.223054885864258],[98.92915534973145,-0.950277328491211]]],[[[134.92248725891113,-1.138055801391602],[134.84301948547363,-0.941944122314453],[134.993013381958,-1.023611068725586],[134.92248725891113,-1.138055801391602]]],[[[130.9313678741455,-0.93638801574707],[130.96441841125488,-1.357221603393555],[130.6388874053955,-0.983888626098633],[130.9313678741455,-0.93638801574707]]],[[[130.91638374328613,-0.794721603393555],[130.3969440460205,-0.926387786865234],[130.48663520812988,-0.835277557373047],[130.91638374328613,-0.794721603393555]]],[[[135.48773384094238,-0.675556182861328],[136.38611030578613,-1.120832443237305],[135.89221382141113,-1.191389083862305],[135.48773384094238,-0.675556182861328]]],[[[127.28109931945801,-0.808332443237305],[127.15358924865723,-0.770000457763672],[127.20443916320801,-0.619167327880859],[127.28109931945801,-0.808332443237305]]],[[[98.5152759552002,-0.632221221923828],[98.4891529083252,-0.599443435668945],[98.50972175598145,-0.600831985473633],[98.5152759552002,-0.632221221923828]]],[[[130.60608100891113,-0.541110992431641],[130.45581245422363,-0.468610763549805],[130.660249710083,-0.426666259765625],[130.60608100891113,-0.541110992431641]]],[[[121.91330909729004,-0.475276947021484],[121.64333534240723,-0.548055648803711],[121.74136543273926,-0.418609619140625],[121.91330909729004,-0.475276947021484]]],[[[104.22831916809082,-0.417221069335938],[104.19748115539551,-0.395832061767578],[104.23166084289551,-0.391666412353516],[104.22831916809082,-0.417221069335938]]],[[[133.111909866333,-0.536388397216797],[134.11108589172363,-0.835277557373047],[134.15970039367676,-2.31944465637207],[134.466646194458,-2.864444732666016],[134.63611030578613,-2.513889312744141],[135.00415229797363,-3.341388702392578],[135.4919147491455,-3.358333587646484],[136.35663032531738,-2.253889083862305],[137.190523147583,-2.103054046630859],[137.1310749053955,-1.792778015136719],[137.85663032531738,-1.47166633605957],[141.00247383117676,-2.607084274291992],[141.00702095031738,-9.128467559814453],[139.98523139953613,-8.193611145019531],[140.146089553833,-7.884721755981445],[138.90860176086426,-8.296667098999023],[139.09552192687988,-7.564165115356445],[138.6611042022705,-7.203332901000977],[139.22247505187988,-7.162500381469727],[138.56192207336426,-6.90888786315918],[139.1894245147705,-6.969444274902344],[138.68191719055176,-6.720554351806641],[138.0644245147705,-5.406110763549805],[134.64358711242676,-4.121387481689453],[134.96551704406738,-3.939722061157227],[134.2157917022705,-3.963054656982422],[133.63748359680176,-3.491666793823242],[133.82885932922363,-2.961666107177734],[133.44970893859863,-3.871389389038086],[132.90164375305176,-4.091388702392578],[132.81802558898926,-3.303054809570313],[131.95581245422363,-2.783611297607422],[132.722749710083,-2.817222595214844],[133.238862991333,-2.416110992431641],[133.68414497375488,-2.716388702392578],[133.936372756958,-2.103054046630859],[132.301362991333,-2.269443511962891],[131.88244819641113,-1.642221450805664],[130.9635944366455,-1.403055191040039],[131.25555610656738,-0.822776794433594],[132.26971626281738,-0.384166717529297],[133.111909866333,-0.536388397216797]],[[133.61969184875488,-3.449443817138672],[133.62329292297363,-3.429473876953125],[133.61023139953613,-3.435832977294922],[133.61969184875488,-3.449443817138672]]],[[[104.49609565734863,-0.626943588256836],[104.28804206848145,-0.393888473510742],[104.53109931945801,-0.37388801574707],[104.49609565734863,-0.626943588256836]]],[[[122.01138496398926,-0.414443969726563],[121.85443305969238,-0.365833282470703],[122.04443550109863,-0.33277702331543],[122.01138496398926,-0.414443969726563]]],[[[127.57499885559082,-0.323331832885742],[127.81775856018066,-0.870832443237305],[127.30359077453613,-0.519166946411133],[127.57499885559082,-0.323331832885742]]],[[[104.44413948059082,-0.32611083984375],[104.4024829864502,-0.285554885864258],[104.48803901672363,-0.278055191040039],[104.44413948059082,-0.32611083984375]]],[[[122.08333015441895,-0.4102783203125],[122.0869312286377,-0.265556335449219],[122.14026832580566,-0.382221221923828],[122.08333015441895,-0.4102783203125]]],[[[127.18303871154785,-0.528888702392578],[127.10498237609863,-0.297222137451172],[127.23387336730957,-0.256111145019531],[127.18303871154785,-0.528888702392578]]],[[[98.50166511535645,-0.539722442626953],[98.32609748840332,-0.539722442626953],[98.43026924133301,-0.246389389038086],[98.50166511535645,-0.539722442626953]]],[[[103.61914253234863,-0.389720916748047],[103.45471382141113,-0.362220764160156],[103.53333473205566,-0.234167098999023],[103.75972175598145,-0.312221527099609],[103.61914253234863,-0.389720916748047]]],[[[122.36360359191895,-0.28416633605957],[122.22387886047363,-0.200555801391602],[122.32805061340332,-0.230833053588867],[122.36360359191895,-0.28416633605957]]],[[[122.22580909729004,-0.278055191040039],[122.14026832580566,-0.229442596435547],[122.18887519836426,-0.197221755981445],[122.22580909729004,-0.278055191040039]]],[[[103.55330848693848,-0.196388244628906],[103.50139045715332,-0.194999694824219],[103.53465461730957,-0.184232711791992],[103.55330848693848,-0.196388244628906]]],[[[104.7402515411377,-0.136943817138672],[104.92943000793457,-0.334165573120117],[104.43248176574707,-0.201944351196289],[104.7402515411377,-0.136943817138672]]],[[[121.61387825012207,-0.206666946411133],[121.56247901916504,-0.156665802001953],[121.63192939758301,-0.123056411743164],[121.61387825012207,-0.206666946411133]]],[[[97.87664985656738,-0.105278015136719],[97.82388496398926,-0.067777633666992],[97.86693000793457,-0.064167022705078],[97.87664985656738,-0.105278015136719]]],[[[104.87663459777832,-0.065555572509766],[104.83191871643066,-0.060832977294922],[104.84219551086426,-0.024442672729492],[104.87663459777832,-0.065555572509766]]],[[[130.87744331359863,-0.019166946411133],[131.25555610656738,-0.387777328491211],[130.68829536437988,-0.079442977905273],[130.91580390930176,-0.40888786315918],[130.21328926086426,-0.206666946411133],[130.87744331359863,-0.019166946411133]],[[130.66971015930176,-0.328887939453125],[130.66638374328613,-0.315832138061523],[130.662202835083,-0.325277328491211],[130.66971015930176,-0.328887939453125]]],[[[98.54748725891113,-0.370555877685547],[98.29193305969238,-0.012222290039063],[98.44413948059082,-0.06138801574707],[98.54748725891113,-0.370555877685547]]],[[[129.55468940734863,-0.21360969543457],[129.2883014678955,0.041391372680664],[129.54052925109863,-0.138889312744141],[129.55468940734863,-0.21360969543457]]],[[[127.45720863342285,-0.012222290039063],[127.39276313781738,0.00694465637207],[127.4105396270752,0.144166946411133],[127.45720863342285,-0.012222290039063]]],[[[98.83474922180176,0.107778549194336],[98.51335334777832,0.133058547973633],[98.76280403137207,0.171667098999023],[98.83474922180176,0.107778549194336]]],[[[104.48193550109863,0.023611068725586],[104.40721321105957,0.090002059936523],[104.40915107727051,0.171667098999023],[104.48193550109863,0.023611068725586]]],[[[104.70192909240723,0.023611068725586],[104.4913501739502,0.237222671508789],[104.54496955871582,0.22166633605957],[104.70192909240723,0.023611068725586]]],[[[104.41191291809082,0.29222297668457],[104.34276008605957,0.370832443237305],[104.42637825012207,0.323610305786133],[104.41191291809082,0.29222297668457]]],[[[127.3852710723877,0.270833969116211],[127.32776832580566,0.336668014526367],[127.38860511779785,0.378610610961914],[127.3852710723877,0.270833969116211]]],[[[103.07359504699707,0.57166862487793],[103.03801918029785,0.654722213745117],[103.06607246398926,0.646390914916992],[103.07359504699707,0.57166862487793]]],[[[104.28164863586426,0.623056411743164],[104.2371997833252,0.689443588256836],[104.28164863586426,0.665555953979492],[104.28164863586426,0.623056411743164]]],[[[103.48359870910645,0.616945266723633],[103.46555519104004,0.630556106567383],[103.51360511779785,0.699167251586914],[103.48359870910645,0.616945266723633]]],[[[103.18524360656738,0.508054733276367],[103.22302436828613,0.703332901000977],[103.29692268371582,0.553888320922852],[103.18524360656738,0.508054733276367]]],[[[127.40387153625488,0.619722366333008],[127.38388252258301,0.751943588256836],[127.44637489318848,0.712778091430664],[127.40387153625488,0.619722366333008]]],[[[104.29414558410645,0.706666946411133],[104.18997383117676,0.775278091430664],[104.27361488342285,0.791669845581055],[104.29414558410645,0.706666946411133]]],[[[104.59831428527832,0.758054733276367],[104.50859260559082,0.756113052368164],[104.55164527893066,0.795000076293945],[104.59831428527832,0.758054733276367]]],[[[103.0941333770752,0.72389030456543],[103.07718849182129,0.750555038452148],[103.1052417755127,0.79777717590332],[103.0941333770752,0.72389030456543]]],[[[103.7158145904541,0.792501449584961],[103.70414924621582,0.759443283081055],[103.66219520568848,0.832223892211914],[103.7158145904541,0.792501449584961]]],[[[127.32222175598145,0.750001907348633],[127.32415962219238,0.864168167114258],[127.37497901916504,0.812223434448242],[127.32222175598145,0.750001907348633]]],[[[103.52580451965332,0.80000114440918],[103.41913032531738,0.871110916137695],[103.48969459533691,0.845834732055664],[103.52580451965332,0.80000114440918]]],[[[103.93636512756348,0.766389846801758],[103.81997871398926,0.886110305786133],[103.88913917541504,0.859445571899414],[103.93636512756348,0.766389846801758]]],[[[103.83220100402832,0.756113052368164],[103.73413276672363,0.886945724487305],[103.81997871398926,0.825834274291992],[103.83220100402832,0.756113052368164]]],[[[103.43692207336426,0.647222518920898],[103.37996101379395,0.891668319702148],[103.50747871398926,0.746389389038086],[103.43692207336426,0.647222518920898]]],[[[103.47857856750488,0.86833381652832],[103.40524482727051,0.908891677856445],[103.46135902404785,0.915834426879883],[103.47857856750488,0.86833381652832]]],[[[104.24273872375488,0.819723129272461],[104.17553901672363,0.790834426879883],[104.09471321105957,0.947221755981445],[104.24273872375488,0.819723129272461]]],[[[102.62423133850098,0.994138717651367],[103.04135322570801,0.714166641235352],[102.40608406066895,0.878057479858398],[102.62423133850098,0.994138717651367]]],[[[103.93496894836426,0.926111221313477],[103.8369083404541,1.010278701782227],[103.93857002258301,0.999166488647461],[103.93496894836426,0.926111221313477]]],[[[104.84305000305176,0.957502365112305],[104.79358863830566,1.024721145629883],[104.83943367004395,1.018613815307617],[104.84305000305176,0.957502365112305]]],[[[107.55664253234863,0.96583366394043],[107.55053901672363,1.037778854370117],[107.59636878967285,1.008054733276367],[107.55664253234863,0.96583366394043]]],[[[103.03719520568848,1.037778854370117],[103.14692878723145,0.837499618530273],[102.65775489807129,1.054166793823242],[103.03719520568848,1.037778854370117]]],[[[120.67720222473145,1.035554885864258],[120.61638069152832,1.071943283081055],[120.63889503479004,1.076112747192383],[120.67720222473145,1.035554885864258]]],[[[120.38804817199707,1.020002365112305],[120.36609077453613,1.032224655151367],[120.38611030578613,1.080835342407227],[120.38804817199707,1.020002365112305]]],[[[104.66689491271973,1.023828506469727],[104.58331489562988,0.81916618347168],[104.23026466369629,1.084169387817383],[104.66689491271973,1.023828506469727]]],[[[103.43968391418457,0.98750114440918],[103.31970405578613,1.040277481079102],[103.34163856506348,1.119722366333008],[103.43968391418457,0.98750114440918]]],[[[104.03360176086426,0.982221603393555],[103.90136909484863,1.093889236450195],[104.11942481994629,1.183610916137695],[104.03360176086426,0.982221603393555]]],[[[102.39525032043457,0.923891067504883],[102.2130298614502,1.405000686645508],[102.4760684967041,1.226667404174805],[102.39525032043457,0.923891067504883]]],[[[97.52636909484863,1.41722297668457],[97.93635749816895,0.978055953979492],[97.81079292297363,0.549722671508789],[97.11468696594238,1.393335342407227],[97.52636909484863,1.41722297668457]]],[[[125.21499824523926,1.389165878295898],[125.16638374328613,1.395280838012695],[125.2994556427002,1.526079177856445],[125.21499824523926,1.389165878295898]]],[[[102.49608039855957,1.444723129272461],[102.49191474914551,1.259721755981445],[101.99442481994629,1.611112594604492],[102.49608039855957,1.444723129272461]]],[[[98.5997486114502,1.625555038452148],[98.42746162414551,1.678888320922852],[98.55505561828613,1.681665420532227],[98.5997486114502,1.625555038452148]]],[[[125.14166450500488,1.421388626098633],[124.24609565734863,0.375001907348633],[120.2422046661377,0.344999313354492],[120.06609535217285,-0.613054275512695],[120.66638374328613,-1.395553588867188],[121.08305549621582,-1.423610687255859],[121.6222095489502,-0.805000305175781],[121.92775917053223,-0.963333129882813],[123.07083320617676,-0.559720993041992],[123.4477481842041,-0.835277557373047],[123.33138465881348,-1.057222366333008],[122.81999397277832,-0.913331985473633],[121.67165565490723,-1.922222137451172],[121.29802894592285,-1.803054809570313],[122.47747993469238,-3.158054351806641],[122.19497871398926,-3.571109771728516],[122.89554023742676,-4.396389007568359],[122.10471534729004,-4.526111602783203],[122.0888843536377,-4.84083366394043],[121.55304145812988,-4.746665954589844],[121.61470222473145,-4.064722061157227],[120.8813648223877,-3.536945343017578],[121.07610511779785,-2.758888244628906],[120.77192878723145,-2.612499237060547],[120.20027351379395,-2.965000152587891],[120.46277046203613,-5.624164581298828],[119.46499824523926,-5.563610076904297],[119.50610542297363,-3.5272216796875],[118.92221260070801,-3.569721221923828],[118.75916481018066,-2.774166107177734],[119.35331916809082,-1.938888549804688],[119.51721382141113,-0.876388549804688],[119.71859931945801,-0.653610229492188],[119.86303901672363,-0.843889236450195],[119.62275886535645,-0.005277633666992],[119.83305549621582,-0.0897216796875],[120.03249549865723,0.712778091430664],[120.28720283508301,0.989721298217773],[120.57303810119629,0.775278091430664],[120.95054817199707,1.342500686645508],[123.83915901184082,0.829446792602539],[124.97110176086426,1.694723129272461],[125.14166450500488,1.421388626098633]]],[[[97.11718940734863,2.011110305786133],[97.09274482727051,2.11250114440918],[97.14831733703613,2.065832138061523],[97.11718940734863,2.011110305786133]]],[[[101.60164070129395,1.709165573120117],[101.39803504943848,1.989168167114258],[101.6455249786377,2.120000839233398],[101.60164070129395,1.709165573120117]]],[[[96.64108467102051,2.065832138061523],[96.61079597473145,2.121946334838867],[96.66913032531738,2.108888626098633],[96.64108467102051,2.065832138061523]]],[[[96.64053535461426,2.152776718139648],[96.59802436828613,2.191110610961914],[96.64859199523926,2.178888320922852],[96.64053535461426,2.152776718139648]]],[[[127.89499092102051,1.796667098999023],[127.79358863830566,0.795000076293945],[128.18829536437988,1.378057479858398],[128.72635078430176,1.556943893432617],[128.6974811553955,1.101945877075195],[128.21023750305176,0.784723281860352],[128.9052448272705,0.200277328491211],[127.87664985656738,0.310556411743164],[128.39526557922363,-0.894721984863281],[127.66609382629395,-0.225831985473633],[127.39499092102051,1.054723739624023],[128.05468940734863,2.195276260375977],[127.89499092102051,1.796667098999023]]],[[[97.32776069641113,2.032224655151367],[97.10357856750488,2.219999313354492],[97.28802680969238,2.22416877746582],[97.32776069641113,2.032224655151367]]],[[[127.79498481750488,2.205556869506836],[127.75665473937988,2.27055549621582],[127.81360054016113,2.261667251586914],[127.79498481750488,2.205556869506836]]],[[[118.57138252258301,2.316389083862305],[118.64972114562988,2.176668167114258],[118.56053352355957,2.264444351196289],[118.57138252258301,2.316389083862305]]],[[[125.43081855773926,2.313055038452148],[125.36775398254395,2.369165420532227],[125.4508228302002,2.379446029663086],[125.43081855773926,2.313055038452148]]],[[[128.1611042022705,2.282224655151367],[128.1191120147705,2.338335037231445],[128.16302680969238,2.404165267944336],[128.1611042022705,2.282224655151367]]],[[[109.06749153137207,2.485002517700195],[108.97318458557129,2.540163040161133],[109.10748481750488,2.530000686645508],[109.06749153137207,2.485002517700195]]],[[[128.4980182647705,2.05000114440918],[128.23217964172363,2.306112289428711],[128.56469917297363,2.632776260375977],[128.4980182647705,2.05000114440918]]],[[[125.40637397766113,2.626665115356445],[125.35471534729004,2.724443435668945],[125.41443061828613,2.807222366333008],[125.40637397766113,2.626665115356445]]],[[[106.24498176574707,2.736665725708008],[106.1977481842041,2.812223434448242],[106.24304389953613,2.78666877746582],[106.24498176574707,2.736665725708008]]],[[[96.43219184875488,2.343057632446289],[95.6969165802002,2.818891525268555],[95.8833179473877,2.918889999389648],[96.43219184875488,2.343057632446289]]],[[[108.83249092102051,2.844999313354492],[108.77361488342285,2.891389846801758],[108.88333320617676,3.001668930053711],[108.83249092102051,2.844999313354492]]],[[[107.75943183898926,2.97416877746582],[107.76555061340332,3.021665573120117],[107.81218910217285,3.00111198425293],[107.75943183898926,2.97416877746582]]],[[[105.7249927520752,2.833890914916992],[105.69832038879395,3.060556411743164],[105.84887886047363,2.979166030883789],[105.7249927520752,2.833890914916992]]],[[[106.28943061828613,3.159723281860352],[106.21277046203613,3.121389389038086],[106.20332527160645,3.226667404174805],[106.28943061828613,3.159723281860352]]],[[[117.52304267883301,3.285554885864258],[117.41137886047363,3.302778244018555],[117.4619312286377,3.343889236450195],[117.52304267883301,3.285554885864258]]],[[[106.28055000305176,3.230833053588867],[106.23471260070801,3.256113052368164],[106.2874927520752,3.373334884643555],[106.28055000305176,3.230833053588867]]],[[[117.66414833068848,3.28416633605957],[117.53943061828613,3.426668167114258],[117.67249488830566,3.419721603393555],[117.66414833068848,3.28416633605957]]],[[[117.60748481750488,3.47722053527832],[117.43332099914551,3.559167861938477],[117.58748817443848,3.524446487426758],[117.60748481750488,3.47722053527832]]],[[[117.39082527160645,3.561944961547852],[117.51748847961426,3.474443435668945],[117.21666145324707,3.545557022094727],[117.39082527160645,3.561944961547852]]],[[[117.88553810119629,3.456666946411133],[117.78970527648926,3.577779769897461],[117.86580848693848,3.548891067504883],[117.88553810119629,3.456666946411133]]],[[[125.88388252258301,3.362222671508789],[125.66359901428223,3.718332290649414],[125.91137886047363,3.491666793823242],[125.88388252258301,3.362222671508789]]],[[[117.82527351379395,3.740556716918945],[117.78830909729004,3.750001907348633],[117.81553840637207,3.755556106567383],[117.82527351379395,3.740556716918945]]],[[[126.84414863586426,3.738054275512695],[126.79221534729004,3.733335494995117],[126.73887825012207,3.842222213745117],[126.84414863586426,3.738054275512695]]],[[[117.84776496887207,3.797224044799805],[117.73082160949707,3.863611221313477],[117.80193519592285,3.855279922485352],[117.84776496887207,3.797224044799805]]],[[[126.71138191223145,3.798055648803711],[126.60803413391113,4.041109085083008],[126.72360420227051,3.91166877746582],[126.71138191223145,3.798055648803711]]],[[[117.68969917297363,3.97416877746582],[117.6463794708252,4.140279769897461],[117.75000190734863,4.068609237670898],[117.68969917297363,3.97416877746582]]],[[[117.88693428039551,4.026945114135742],[117.68692207336426,4.168336868286133],[117.72664833068848,4.169721603393555],[117.9035587310791,4.174043655395508],[117.88693428039551,4.026945114135742]]],[[[108.18166542053223,3.647500991821289],[108.18166542053223,4.196386337280273],[108.40693855285645,3.875833511352539],[108.18166542053223,3.647500991821289]]],[[[116.04942512512207,4.279443740844727],[117.5920581817627,4.169820785522461],[117.39276313781738,4.107500076293945],[117.82805061340332,3.70222282409668],[117.03027534484863,3.594167709350586],[117.44413948059082,3.43055534362793],[117.27304267883301,3.222776412963867],[118.09665107727051,2.30555534362793],[117.87191963195801,1.876668930053711],[119.00861549377441,0.980833053588867],[118.34387397766113,0.843057632446289],[117.89444160461426,1.119722366333008],[118.03499031066895,0.810277938842773],[117.46748542785645,0.103612899780273],[117.62248420715332,-0.779722213745117],[116.9236011505127,-1.254444122314453],[116.74331855773926,-1.024166107177734],[116.75554847717285,-1.367500305175781],[116.22249031066895,-1.779167175292969],[116.60415840148926,-2.229721069335938],[115.98387336730957,-3.588888168334961],[114.70665168762207,-4.176944732666016],[114.48108863830566,-3.498611450195313],[113.67109870910645,-3.476110458374023],[113.06469917297363,-2.993888854980469],[111.88942909240723,-3.573888778686523],[111.74971199035645,-2.741943359375],[111.55026435852051,-3.024444580078125],[110.23748970031738,-2.979442596435547],[109.90358924865723,-1.828332901000977],[110.05774879455566,-1.333889007568359],[109.72971534729004,-0.953611373901367],[109.27249336242676,-0.854999542236328],[109.51442909240723,-0.726943969726563],[109.12024879455566,-0.502222061157227],[108.84549140930176,0.810564041137695],[109.26500129699707,1.393335342407227],[108.98193550109863,1.211668014526367],[109.06694221496582,1.532224655151367],[109.64856910705566,2.073408126831055],[109.66998481750488,1.613054275512695],[110.55525398254395,0.853891372680664],[111.82721138000488,0.998613357543945],[112.47276496887207,1.568056106567383],[113.65833473205566,1.224721908569336],[114.5627613067627,1.433610916137695],[114.8047046661377,2.24888801574707],[115.2371997833252,2.522500991821289],[115.13971138000488,2.906110763549805],[115.49553108215332,3.040002822875977],[115.68525886535645,4.171945571899414],[116.04942512512207,4.279443740844727]],[[117.29553413391113,-0.878332138061523],[117.2885913848877,-0.831666946411133],[117.27221870422363,-0.876943588256836],[117.29553413391113,-0.878332138061523]]],[[[126.75972175598145,3.985834121704102],[126.74054145812988,4.54194450378418],[126.91609382629395,4.273611068725586],[126.75972175598145,3.985834121704102]]],[[[125.49136543273926,4.732778549194336],[125.47886848449707,4.734445571899414],[125.49193000793457,4.745553970336914],[125.49136543273926,4.732778549194336]]],[[[107.96443367004395,4.674722671508789],[107.93831062316895,4.701944351196289],[108.00470924377441,4.772222518920898],[107.96443367004395,4.674722671508789]]],[[[95.73857307434082,5.58527946472168],[96.34774971008301,5.222776412963867],[97.51886177062988,5.246667861938477],[98.2705249786377,4.142499923706055],[99.97775459289551,2.947500228881836],[100.00164985656738,2.601945877075195],[100.20913887023926,2.703332901000977],[100.94246101379395,1.820554733276367],[100.79720497131348,2.214445114135742],[101.05552864074707,2.28639030456543],[102.42191505432129,0.800554275512695],[102.93245887756348,0.695001602172852],[103.08191871643066,0.445554733276367],[102.53996467590332,0.166669845581055],[103.3510913848877,0.536111831665039],[103.73969459533691,0.281110763549805],[103.81419563293457,-0.001028060913086],[103.26970863342285,-0.258888244628906],[103.49080848693848,-0.216943740844727],[103.34236335754395,-0.364095687866211],[103.5999927520752,-0.441110610961914],[103.36081123352051,-0.702220916748047],[104.37915229797363,-1.041389465332031],[104.48943519592285,-1.924999237060547],[104.87943458557129,-2.146944046020508],[104.53249549865723,-2.772777557373047],[104.8621997833252,-2.289443969726563],[105.61248970031738,-2.394166946411133],[106.05525398254395,-3.031389236450195],[105.73248481750488,-5.89777946472168],[105.26860237121582,-5.44416618347168],[105.13971138000488,-5.796110153198242],[104.54498481750488,-5.506389617919922],[104.56077766418457,-5.929746627807617],[101.62692451477051,-3.246110916137695],[100.29358863830566,-0.806388854980469],[99.63582038879395,0.076944351196289],[99.1361255645752,0.261388778686523],[98.77086067199707,1.748613357543945],[97.75192451477051,2.269166946411133],[96.88025093078613,3.677499771118164],[95.53108406066895,4.682775497436523],[95.23080635070801,5.570833206176758],[95.73857307434082,5.58527946472168]],[[104.2138843536377,-1.039443969726563],[104.24331855773926,-1.023611068725586],[104.2008228302002,-1.037221908569336],[104.2138843536377,-1.039443969726563]],[[102.85970497131348,0.274446487426758],[102.92691230773926,0.322221755981445],[102.83386421203613,0.281110763549805],[102.85970497131348,0.274446487426758]]],[[[95.15802192687988,5.594724655151367],[95.10885810852051,5.61250114440918],[95.1424732208252,5.660833358764648],[95.15802192687988,5.594724655151367]]],[[[95.11969184875488,5.670278549194336],[95.00802803039551,5.73527717590332],[95.06358528137207,5.749444961547852],[95.11969184875488,5.670278549194336]]],[[[95.34247016906738,5.774168014526367],[95.21774482727051,5.913053512573242],[95.38163948059082,5.849721908569336],[95.34247016906738,5.774168014526367]]]]}},{"type":"Feature","properties":{"name":"Guadeloupe","iso2":"GP","iso3":"GLP"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-61.24556,15.871666],[-61.329445,15.92861],[-61.266945,16.014999],[-61.24556,15.871666]]],[[[-61.037224,16.311108],[-61.08667,16.29583],[-60.988617,16.346107000000146],[-61.037224,16.311108]]],[[[-61.346115,16.334164],[-61.695007,15.949165],[-61.783615,16.333054],[-61.346115,16.334164]]],[[[-62.811394,17.888332],[-62.869171,17.929722000000154],[-62.79084,17.912498],[-62.811394,17.888332]]]]}},{"type":"Feature","properties":{"name":"Netherlands Antilles","iso2":"AN","iso3":"ANT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-68.19528198242188,12.221109390258789],[-68.25111389160156,12.02055549621582],[-68.41612243652344,12.25694465637207],[-68.19528198242188,12.221109390258789]]],[[[-68.96556091308594,12.198888778686523],[-69.16361999511719,12.366388320922852],[-68.7469482421875,12.040277481079102],[-68.96556091308594,12.198888778686523]]],[[[-62.96111297607422,17.460832595825195],[-62.996673583984375,17.52055549621582],[-62.93861389160156,17.490278244018555],[-62.96111297607422,17.460832595825195]]]]}},{"type":"Feature","properties":{"name":"United Arab Emirates","iso2":"AE","iso3":"ARE"},"geometry":{"type":"MultiPolygon","coordinates":[[[[53.965271000000115,24.176666],[53.62388600000011,24.162777],[53.85110500000022,24.269165],[53.965271000000115,24.176666]]],[[[53.324165,24.267776],[53.243607,24.276665],[53.341110000000214,24.328888],[53.324165,24.267776]]],[[[53.10971800000013,24.311386],[53.079437,24.32555400000011],[53.085831,24.352776],[53.10971800000013,24.311386]]],[[[54.264717000000104,24.288887],[54.174438,24.324997],[54.231384,24.35083],[54.264717000000104,24.288887]]],[[[52.616104,24.268608],[52.572777,24.339722],[52.639717,24.3722190000001],[52.616104,24.268608]]],[[[53.3980480000001,24.324718],[53.387497,24.368889],[53.428329000000105,24.366943],[53.3980480000001,24.324718]]],[[[54.472496,24.418888],[54.328331,24.45972100000013],[54.380272,24.502499],[54.472496,24.418888]]],[[[54.515549,24.504719],[54.48555,24.509163],[54.469719,24.536942],[54.515549,24.504719]]],[[[54.440826,24.50111],[54.400833,24.514721],[54.465553,24.589996],[54.440826,24.50111]]],[[[55.61749300000011,25.57],[55.609718000000186,25.569443],[55.620552,25.583611],[55.61749300000011,25.57]]],[[[56.183331,25.654989],[56.269722,25.636015],[56.373528,24.979382],[56.104164,24.734722000000104],[56.037498,24.938889],[55.7794420000001,24.563889000000145],[56.024719,24.076111],[55.510277000000116,23.97277500000014],[55.199165000000136,22.699718],[52.583328,22.938890000000114],[51.583611000000104,24.25972],[52.080551,23.955555],[54.118607,24.139442],[54.424164,24.281666],[54.650276000000105,24.746944],[55.863609,25.72333100000013],[56.079941,26.065559],[56.183331,25.654989]]]]}},{"type":"Feature","properties":{"name":"Timor-Leste","iso2":"TL","iso3":"TLS"},"geometry":{"type":"MultiPolygon","coordinates":[[[[124.44572729730143,-9.184801455158606],[124.34309325995272,-9.463379556533425],[124.04616116616907,-9.339979205869994],[124.44572729730143,-9.184801455158606]]],[[[127.25305200000011,-8.477499],[125.1279887712715,-9.435955217796248],[125.16404989666458,-9.066142474253581],[124.94544874451074,-8.95403931930285],[125.844147,-8.481667],[127.25305200000011,-8.477499]]]]}},{"type":"Feature","properties":{"name":"Pitcairn Islands","iso2":"PN","iso3":"PCN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-130.076935,-25.079723],[-130.107483,-25.063335],[-130.065002,-25.063335],[-130.076935,-25.079723]]],[[[-124.780853,-24.675835],[-124.795853,-24.666115],[-124.77252199999987,-24.666946],[-124.780853,-24.675835]]],[[[-128.289185,-24.409721],[-128.336945,-24.329166],[-128.303894,-24.33028],[-128.289185,-24.409721]]]]}},{"type":"Feature","properties":{"name":"Palau","iso2":"PW","iso3":"PLW"},"geometry":{"type":"MultiPolygon","coordinates":[[[[132.226624,5.292777000000129],[132.20831300000012,5.31111],[132.230255,5.307221],[132.226624,5.292777000000129]]],[[[134.166077,6.885277],[134.139435,6.934721000000124],[134.174988,6.923888],[134.166077,6.885277]]],[[[134.274994,7.010278],[134.227753,6.987777],[134.27832,7.070833],[134.274994,7.010278]]],[[[134.392761,7.140277],[134.353851,7.168055000000109],[134.381897,7.192498],[134.392761,7.140277]]],[[[134.377747,7.215833],[134.344116,7.269444],[134.438873,7.278888],[134.377747,7.215833]]],[[[134.470795,7.36111],[134.5174870000001,7.308054],[134.448303,7.331944],[134.470795,7.36111]]],[[[134.561371,7.371943],[134.485229,7.438054000000108],[134.634155,7.729444],[134.561371,7.371943]]]]}},{"type":"Feature","properties":{"name":"Marshall Islands","iso2":"MH","iso3":"MHL"},"geometry":{"type":"MultiPolygon","coordinates":[[[[168.113586,5.600277],[168.094971,5.613333],[168.12439,5.641666000000114],[168.113586,5.600277]]],[[[168.09024,5.630554000000146],[168.074982,5.631943],[168.077148,5.650265],[168.09024,5.630554000000146]]],[[[171.75192300000012,6.080555],[171.727173,6.086110000000147],[171.733582,6.096388],[171.75192300000012,6.080555]]],[[[172.090515,6.219721],[172.07412700000012,6.222221000000104],[172.080261,6.229721],[172.090515,6.219721]]],[[[171.914154,7.092499000000117],[171.89413500000015,7.101665],[171.929962,7.133888],[171.914154,7.092499000000117]]],[[[168.768036,7.298332],[168.78637700000016,7.288888],[168.670258,7.328888],[168.768036,7.298332]]],[[[168.574677,7.398055000000113],[168.554962,7.423055],[168.5585940000001,7.471388],[168.574677,7.398055000000113]]],[[[168.967194,7.574166],[168.944427,7.615276],[168.974976,7.60111],[168.967194,7.574166]]],[[[168.251373,7.749443],[168.233582,7.74861],[168.220245,7.766944],[168.251373,7.749443]]],[[[167.738861,8.725275],[167.724396,8.729719],[167.740784,8.747776],[167.738861,8.725275]]],[[[170.844971,8.886944],[170.834961,8.893332],[170.846924,8.916109],[170.844971,8.886944]]],[[[165.536926,9.19722],[165.522491,9.207775],[165.5269170000001,9.218609000000143],[165.536926,9.19722]]],[[[166.829956,9.32222],[166.811646,9.336943],[166.830261,9.335831],[166.829956,9.32222]]],[[[170.248016,9.544722],[170.244965,9.533609000000112],[170.233307,9.55888700000014],[170.248016,9.544722]]],[[[170.15387,9.639442],[170.1355290000001,9.633333],[170.161652,9.645277],[170.15387,9.639442]]],[[[169.97161900000017,10.436386],[169.96386700000014,10.43333200000015],[169.944122,10.451109],[169.97161900000017,10.436386]]],[[[166.885254,11.144722],[166.841339,11.153332],[166.900543,11.168610000000115],[166.885254,11.144722]]],[[[169.866913,11.232775],[169.85553,11.231941],[169.858856,11.241386],[169.866913,11.232775]]],[[[162.33828700000012,11.351942],[162.323578,11.354164],[162.341644,11.362219],[162.33828700000012,11.351942]]],[[[167.520813,11.377775],[167.512207,11.393888],[167.5260930000002,11.386665],[167.520813,11.377775]]],[[[165.55609100000018,11.615831],[165.5130310000002,11.638611],[165.547211,11.634443000000104],[165.55609100000018,11.615831]]],[[[165.29165600000013,11.700554],[165.27191200000013,11.706387],[165.284698,11.714165],[165.29165600000013,11.700554]]],[[[168.987732,14.580832],[168.974976,14.58111],[169.003876,14.598053],[168.987732,14.580832]]]]}},{"type":"Feature","properties":{"name":"Saint Pierre and Miquelon","iso2":"PM","iso3":"SPM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-56.150833,46.758049],[-56.23722099999986,46.763885000000144],[-56.173889,46.80999],[-56.150833,46.758049]]],[[[-56.271111,46.994156],[-56.368332,46.784721],[-56.390282,47.118881],[-56.271111,46.994156]]]]}},{"type":"Feature","properties":{"name":"Saint Helena","iso2":"SH","iso3":"SHN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-9.892223,-40.390839],[-10.028611999999896,-40.309448],[-9.95222299999989,-40.306671],[-9.892223,-40.390839]]],[[[-12.206389999999885,-37.112503],[-12.331666999999868,-37.107506],[-12.259445,-37.05278],[-12.206389999999885,-37.112503]]],[[[-5.662222999999869,-15.987501],[-5.793056,-15.994167],[-5.704167,-15.903057],[-5.662222999999869,-15.987501]]],[[[-14.36389,-7.979723],[-14.381945,-7.883612],[-14.293056,-7.945278],[-14.36389,-7.979723]]]]}},{"type":"Feature","properties":{"name":"San Marino","iso2":"SM","iso3":"SMR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[12.415798,43.957954],[12.509998,43.986938],[12.459166,43.896111],[12.415798,43.957954]]]]}},{"type":"Feature","properties":{"name":"Turks and Caicos Islands","iso2":"TC","iso3":"TCA"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-71.140289,21.431942],[-71.150558,21.470833],[-71.135559,21.511108000000107],[-71.140289,21.431942]]],[[[-72.460556,21.629719],[-72.45667999999989,21.699718000000118],[-72.433624,21.713333],[-72.460556,21.629719]]],[[[-71.468903,21.654999],[-71.53334,21.734444],[-71.462784,21.720833],[-71.468903,21.654999]]],[[[-71.657791,21.82333],[-71.65888999999987,21.739719000000107],[-71.850571,21.845833],[-71.657791,21.82333]]],[[[-72.2622219999999,21.75111],[-72.327225,21.855831],[-72.247787,21.795555],[-72.2622219999999,21.75111]]],[[[-71.88417099999987,21.847221],[-72.03334,21.942776],[-71.912231,21.943333],[-71.88417099999987,21.847221]]]]}},{"type":"Feature","properties":{"name":"Western Sahara","iso2":"EH","iso3":"ESH"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-15.741997,21.338284],[-16.953056,21.338333],[-17.05233,20.764095000000125],[-16.917225,21.943054],[-16.719448,22.26083],[-16.491112,22.334164],[-16.075558,23.324444],[-15.766668,23.781666],[-15.777225,23.908882],[-16.00639,23.6675],[-15.838058,23.896938],[-14.901112,24.688053],[-14.480278,26.171108],[-13.574167,26.731667],[-13.174961,27.666958],[-8.666668,27.666664],[-8.66679,27.290459],[-8.666944999999885,26.000275000000116],[-12.000557,26],[-12.000278,23.454441000000102],[-13.105278,22.893055],[-12.999723,21.338055000000125],[-15.741997,21.338284]]]]}},{"type":"Feature","properties":{"name":"Serbia","iso2":"RS","iso3":"SRB"},"geometry":{"type":"MultiPolygon","coordinates":[[[[20.071423,42.560913],[20.348888,42.886383],[19.228809,43.513214],[19.51083,43.679718],[19.237019,44.011009],[19.620476,44.048454],[19.104443,44.355827],[19.371387,44.88916],[19.039719,44.861382],[19.423885,45.22583],[18.980324000000138,45.378624],[18.81702,45.912964],[20.261024,46.114853],[21.513611,45.151108],[21.400398,44.780823],[22.146385,44.479164],[22.479164,44.710274],[22.764893,44.559006],[22.457333,44.474358],[22.681435,44.224701],[22.367222,43.826942],[23.004997,43.192772],[22.442219,42.821663],[22.365276,42.323883],[20.589642,41.882187],[20.071423,42.560913]]]]}},{"type":"Feature","properties":{"name":"Holy See (Vatican City)","iso2":"VA","iso3":"VAT"},"geometry":{"type":"MultiPolygon","coordinates":[[[[12.445090330888661,41.90311752178489],[12.45165333958056,41.907989033391274],[12.456660170953796,41.901426024699205],[12.445090330888661,41.90311752178489]]]]}},{"type":"Feature","properties":{"name":"Svalbard","iso2":"SJ","iso3":"SJM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-8.290895462036133,70.97415351867676],[-9.120058059692383,70.85775947570801],[-7.927001953125,71.15081977844238],[-8.290895462036133,70.97415351867676]]],[[[19.18194007873535,74.35971260070801],[18.79194450378418,74.48166084289551],[19.29972267150879,74.4749927520752],[19.18194007873535,74.35971260070801]]],[[[25.016111373901367,76.46638679504395],[24.936384201049805,76.4488697052002],[25.58222007751465,76.70665168762207],[25.016111373901367,76.46638679504395]]],[[[23.285554885864258,77.26471138000488],[23.13527488708496,77.23526191711426],[23.036386489868164,77.25999641418457],[23.285554885864258,77.26471138000488]]],[[[23.336111068725586,78.19748115539551],[23.059720993041992,78.01609992980957],[24.910276412963867,77.74971199035645],[22.6411075592041,77.25305366516113],[22.407499313354492,77.42082405090332],[22.77833366394043,77.54776191711426],[20.858888626098633,77.46249580383301],[21.64499855041504,77.9124927520752],[20.903051376342773,78.11499214172363],[23.336111068725586,78.19748115539551]]],[[[21.501665115356445,78.56553840637207],[22.028886795043945,78.5808277130127],[22.271944046020508,78.26361274719238],[20.671110153198242,78.18748664855957],[20.124719619750977,78.47221565246582],[21.501665115356445,78.56553840637207]]],[[[26.847497940063477,78.70749092102051],[26.396387100219727,78.77083015441895],[27.017499923706055,78.69304084777832],[26.847497940063477,78.70749092102051]]],[[[11.271944046020508,78.60693550109863],[12.163610458374023,78.19970893859863],[10.488611221313477,78.8963794708252],[11.271944046020508,78.60693550109863]]],[[[29.030553817749023,78.91609382629395],[29.708051681518555,78.8963794708252],[28.01972007751465,78.86747932434082],[29.030553817749023,78.91609382629395]]],[[[30.209440231323242,78.97638130187988],[30.06694221496582,79.00110054016113],[30.336111068725586,78.98887825012207],[30.209440231323242,78.97638130187988]]],[[[21.226106643676758,79.0374927520752],[20.98249626159668,79.01416206359863],[20.923608779907227,79.02998542785645],[21.226106643676758,79.0374927520752]]],[[[20.83305549621582,79.05415534973145],[20.046110153198242,79.0374927520752],[20.19972038269043,79.12469673156738],[20.83305549621582,79.05415534973145]]],[[[20.00750160217285,79.2422046661377],[19.9547176361084,79.22665596008301],[20.168886184692383,79.31915473937988],[20.00750160217285,79.2422046661377]]],[[[20.10944175720215,79.36581611633301],[20.18027687072754,79.3388843536377],[19.628332138061523,79.3883228302002],[20.10944175720215,79.36581611633301]]],[[[10.92277717590332,79.65109443664551],[10.712221145629883,79.71360969543457],[11.076108932495117,79.66276741027832],[10.92277717590332,79.65109443664551]]],[[[11.000555038452148,79.74026679992676],[10.639165878295898,79.75000190734863],[10.756109237670898,79.78332710266113],[11.000555038452148,79.74026679992676]]],[[[16.81916618347168,79.8722095489502],[18.09833335876465,79.72026252746582],[17.63555335998535,79.37248420715332],[18.356943130493164,79.6283130645752],[18.92055320739746,79.16415596008301],[21.549165725708008,78.76776313781738],[18.965551376342773,78.45610237121582],[19.092222213745117,78.09553718566895],[18.410829544067383,78.02165412902832],[18.292776107788086,77.50638008117676],[17.73832893371582,77.47110176086426],[16.919164657592773,76.79971504211426],[17.198331832885742,76.69470405578613],[16.612775802612305,76.57054328918457],[15.498052597045898,76.87997627258301],[16.51972007751465,76.99859809875488],[14.467222213745117,77.1716480255127],[13.914167404174805,77.52777290344238],[16.223051071166992,77.43498420715332],[14.739164352416992,77.65860176086426],[17.0061092376709,77.93136787414551],[13.94194221496582,77.71666145324707],[13.588888168334961,78.04942512512207],[17.301664352416992,78.42025947570801],[16.328886032104492,78.45221138000488],[16.83111000061035,78.67192268371582],[15.464166641235352,78.45166206359863],[15.193330764770508,78.58804512023926],[15.379999160766602,78.84471321105957],[14.385557174682617,78.49775886535645],[14.726388931274414,78.38388252258301],[13.00666618347168,78.19748115539551],[12.360555648803711,78.48027229309082],[13.198610305786133,78.54081916809082],[11.333333969116211,78.96054267883301],[12.505556106567383,78.90803718566895],[11.755277633666992,79.0758228302002],[12.113054275512695,79.29582405090332],[11.236387252807617,79.09305000305176],[10.676942825317383,79.54498481750488],[13.82472038269043,79.8752613067627],[12.447778701782227,79.56637763977051],[13.484441757202148,79.5808277130127],[13.257223129272461,79.47137641906738],[14.058889389038086,79.2602710723877],[13.886945724487305,79.54136848449707],[14.584997177124023,79.80415534973145],[16.44999885559082,78.90387153625488],[15.638055801391602,79.82721138000488],[16.307775497436523,80.0627613067627],[16.81916618347168,79.8722095489502]]],[[[27.837778091430664,80.11026191711426],[27.674165725708008,80.12275886535645],[28.07444190979004,80.14415168762207],[27.837778091430664,80.11026191711426]]],[[[36.84916114807129,80.13998603820801],[36.59054756164551,80.15498542785645],[36.76027870178223,80.16081428527832],[36.84916114807129,80.13998603820801]]],[[[32.36638832092285,80.09443855285645],[31.44944190979004,80.08581733703613],[33.63749885559082,80.21331977844238],[32.36638832092285,80.09443855285645]]],[[[18.55333137512207,80.24553108215332],[18.119443893432617,80.28471565246582],[18.75861167907715,80.30192756652832],[18.55333137512207,80.24553108215332]]],[[[24.335832595825195,80.38415718078613],[24.128610610961914,80.39305305480957],[24.196943283081055,80.45416450500488],[24.335832595825195,80.38415718078613]]],[[[19.933332443237305,80.47747993469238],[21.86055564880371,80.26776313781738],[21.598608016967773,80.11831855773926],[22.22638511657715,79.97915840148926],[22.578611373901367,80.2986011505127],[22.361108779907227,80.41026496887207],[22.88694190979004,80.49026679992676],[23.360830307006836,80.42943000793457],[23.101388931274414,80.12082099914551],[24.83638572692871,80.35081672668457],[27.244997024536133,79.90498542785645],[23.511667251586914,79.17886543273926],[19.63555335998535,79.60386848449707],[22.312498092651367,79.79693794250488],[18.771387100219727,79.71748542785645],[18.154165267944336,79.90999031066895],[18.8094425201416,79.99470710754395],[17.783056259155273,80.12776374816895],[19.34055519104004,80.08638191223145],[19.584165573120117,80.1513843536377],[18.979997634887695,80.33665657043457],[19.837778091430664,80.2138843536377],[19.46333122253418,80.45471382141113],[19.933332443237305,80.47747993469238]]],[[[24.26500129699707,80.47110176086426],[23.97443962097168,80.49054145812988],[24.174997329711914,80.50915718078613],[24.26500129699707,80.47110176086426]]],[[[19.933332443237305,80.47747993469238],[19.8447208404541,80.50305366516113],[20.130277633666992,80.51277351379395],[19.933332443237305,80.47747993469238]]],[[[20.753610610961914,80.62137031555176],[20.499162673950195,80.65776252746582],[20.793333053588867,80.64749336242676],[20.753610610961914,80.62137031555176]]],[[[21.330278396606445,80.70027351379395],[21.364999771118164,80.67886543273926],[21.02638816833496,80.6816577911377],[21.330278396606445,80.70027351379395]]],[[[20.81916618347168,80.71914863586426],[20.51833152770996,80.75999641418457],[21.00666618347168,80.70138740539551],[20.81916618347168,80.71914863586426]]]]}},{"type":"Feature","properties":{"name":"Saint Martin","iso2":"MF","iso3":"MAF"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-63.00666799999988,18.080555],[-63.01145899999989,18.067276],[-63.139839,18.058601],[-63.00666799999988,18.080555]]]]}},{"type":"Feature","properties":{"name":"Saint Barthelemy","iso2":"BL","iso3":"BLM"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-63.028336,18.015553],[-63.139839,18.058601],[-63.01145899999989,18.067276],[-63.028336,18.015553]]]]}},{"type":"Feature","properties":{"name":"Guernsey","iso2":"GG","iso3":"GGY"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-2.590834,49.422493],[-2.670278,49.434166000000104],[-2.501667,49.507774],[-2.590834,49.422493]]]]}},{"type":"Feature","properties":{"name":"Jersey","iso2":"JE","iso3":"JEY"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-2.015,49.214165],[-2.205278,49.180832],[-2.247222,49.253052],[-2.015,49.214165]]]]}},{"type":"Feature","properties":{"name":"South Georgia South Sandwich Islands","iso2":"GS","iso3":"SGS"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-27.325836,-59.427223],[-27.298058,-59.473061],[-27.412502,-59.434448],[-27.325836,-59.427223]]],[[[-26.582779,-59.070007],[-26.665001,-59.025841],[-26.501114,-59.036949],[-26.582779,-59.070007]]],[[[-26.246391,-58.407501],[-26.24889,-58.498611],[-26.459167,-58.427223],[-26.246391,-58.407501]]],[[[-26.41278099999988,-57.80806],[-26.512222,-57.771118],[-26.443336,-57.743896],[-26.41278099999988,-57.80806]]],[[[-26.660835,-57.086395],[-26.728888999999896,-57.062782],[-26.675835,-57.056396],[-26.660835,-57.086395]]],[[[-27.10861199999988,-56.717506],[-27.209724,-56.693611],[-27.129448,-56.682228],[-27.10861199999988,-56.717506]]],[[[-27.563892,-56.320557],[-27.600002,-56.281113],[-27.549446,-56.27417],[-27.563892,-56.320557]]],[[[-37.038612,-54.511673],[-37.083618,-54.512779],[-37.105835,-54.471115],[-37.038612,-54.511673]]],[[[-37.495003,-54.010559],[-36.288063,-54.266396],[-35.782501,-54.765556],[-36.115837,-54.887222],[-37.411392,-54.268333],[-37.239448999999865,-54.147781],[-38.033058,-54.048889],[-37.495003,-54.010559]]]]}},{"type":"Feature","properties":{"name":"Taiwan","iso2":"TW","iso3":"TWN"},"geometry":{"type":"MultiPolygon","coordinates":[[[[121.576393,22.001389],[121.490257,22.078609],[121.546944,22.078053],[121.576393,22.001389]]],[[[119.66943400000011,23.549999],[119.526703,23.535461],[119.59832800000018,23.606941],[119.66943400000011,23.549999]]],[[[118.223602,24.40416300000011],[118.207489,24.412495000000106],[118.241364,24.445827],[118.223602,24.40416300000011]]],[[[118.4191440000001,24.395828],[118.275543,24.399162],[118.401657,24.521664],[118.4191440000001,24.395828]]],[[[121.734711,25.138885],[122.002213,25.006943000000106],[121.839706,24.476383000000126],[120.71637700000011,21.928051],[120.05275700000018,23.044998],[120.111366,23.620274],[121.00916300000014,25.008888000000113],[121.734711,25.138885]]],[[[119.92942800000012,26.134995],[119.909416,26.159439],[119.95247700000019,26.159996000000106],[119.92942800000012,26.134995]]],[[[119.96720900000017,26.187496000000138],[119.956383,26.215549],[120.006104,26.219162],[119.96720900000017,26.187496000000138]]]]}}]} \ No newline at end of file diff --git a/src/plugins/tile_map/public/__tests__/blues.png b/src/plugins/tile_map/public/__tests__/blues.png deleted file mode 100644 index 89d6734eb123a..0000000000000 Binary files a/src/plugins/tile_map/public/__tests__/blues.png and /dev/null differ diff --git a/src/plugins/tile_map/public/__tests__/coordinate_maps_visualization.js b/src/plugins/tile_map/public/__tests__/coordinate_maps_visualization.js deleted file mode 100644 index f2830e58e0eea..0000000000000 --- a/src/plugins/tile_map/public/__tests__/coordinate_maps_visualization.js +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; -import { ImageComparator } from 'test_utils/image_comparator'; -import dummyESResponse from './dummy_es_response.json'; -import initial from './initial.png'; -import blues from './blues.png'; -import shadedGeohashGrid from './shaded_geohash_grid.png'; -import heatmapRaw from './heatmap_raw.png'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import EMS_CATALOGUE from '../../../maps_legacy/public/__tests__/map/ems_mocks/sample_manifest.json'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import EMS_FILES from '../../../maps_legacy/public/__tests__/map/ems_mocks/sample_files.json'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import EMS_TILES from '../../../maps_legacy/public/__tests__/map/ems_mocks/sample_tiles.json'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import EMS_STYLE_ROAD_MAP_BRIGHT from '../../../maps_legacy/public/__tests__/map/ems_mocks/sample_style_bright'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import EMS_STYLE_ROAD_MAP_DESATURATED from '../../../maps_legacy/public/__tests__/map/ems_mocks/sample_style_desaturated'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import EMS_STYLE_DARK_MAP from '../../../maps_legacy/public/__tests__/map/ems_mocks/sample_style_dark'; - -import { createTileMapVisualization } from '../tile_map_visualization'; -import { createTileMapTypeDefinition } from '../tile_map_type'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { ExprVis } from '../../../visualizations/public/expressions/vis'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { BaseVisType } from '../../../visualizations/public/vis_types/base_vis_type'; -import { - getPrecision, - getZoomPrecision, - // eslint-disable-next-line @kbn/eslint/no-restricted-paths -} from '../../../maps_legacy/public/map/precision'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { ServiceSettings } from '../../../maps_legacy/public/map/service_settings'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { KibanaMap } from '../../../maps_legacy/public/map/kibana_map'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { BaseMapsVisualizationProvider } from '../../../maps_legacy/public/map/base_maps_visualization'; - -function mockRawData() { - const stack = [dummyESResponse]; - let node; - do { - node = stack.pop(); - if (typeof node === 'object') { - // eslint-disable-next-line guard-for-in - for (const key in node) { - if (node.hasOwnProperty(key)) { - if (key === 'aggConfig') { - node[key].makeLabel = () => 'foobar'; - } - } - stack.push(node[key]); - } - } - } while (stack.length); -} -mockRawData(); - -const THRESHOLD = 0.45; -const PIXEL_DIFF = 64; - -describe('CoordinateMapsVisualizationTest', function () { - let domNode; - let CoordinateMapsVisualization; - let vis; - let dependencies; - let visType; - - let imageComparator; - - let getManifestStub; - beforeEach(ngMock.module('kibana')); - beforeEach( - ngMock.inject((Private, $injector) => { - const mapConfig = { - emsFileApiUrl: '', - emsTileApiUrl: '', - emsLandingPageUrl: '', - }; - const tilemapsConfig = { - options: { - attribution: '123', - }, - }; - - const serviceSettings = new ServiceSettings(mapConfig, tilemapsConfig); - const BaseMapsVisualization = new BaseMapsVisualizationProvider( - (...args) => new KibanaMap(...args), - serviceSettings - ); - const uiSettings = $injector.get('config'); - - dependencies = { - getZoomPrecision, - getPrecision, - BaseMapsVisualization, - uiSettings, - serviceSettings, - }; - - visType = new BaseVisType(createTileMapTypeDefinition(dependencies)); - - CoordinateMapsVisualization = createTileMapVisualization(dependencies); - - getManifestStub = serviceSettings.__debugStubManifestCalls(async (url) => { - //simulate network calls - if (url.startsWith('https://foobar')) { - return EMS_CATALOGUE; - } else if (url.startsWith('https://tiles.foobar')) { - return EMS_TILES; - } else if (url.startsWith('https://files.foobar')) { - return EMS_FILES; - } else if (url.startsWith('https://raster-style.foobar')) { - if (url.includes('osm-bright-desaturated')) { - return EMS_STYLE_ROAD_MAP_DESATURATED; - } else if (url.includes('osm-bright')) { - return EMS_STYLE_ROAD_MAP_BRIGHT; - } else if (url.includes('dark-matter')) { - return EMS_STYLE_DARK_MAP; - } - } - }); - }) - ); - - afterEach(() => { - getManifestStub.removeStub(); - }); - - describe('CoordinateMapsVisualization - basics', function () { - beforeEach(async function () { - setupDOM('512px', '512px'); - - imageComparator = new ImageComparator(); - vis = new ExprVis({ - type: visType, - }); - vis.params = { - mapType: 'Scaled Circle Markers', - isDesaturated: true, - addTooltip: true, - heatClusterSize: 1.5, - legendPosition: 'bottomright', - mapZoom: 2, - mapCenter: [0, 0], - dimensions: { - metric: { - accessor: 1, - label: 'test', - format: { id: 'string' }, - }, - bucket: { - accessor: 0, - }, - }, - }; - const mockAggs = { - byType: (type) => { - return mockAggs.aggs.find((agg) => agg.type.type === type); - }, - aggs: [ - { - type: { - type: 'metrics', - }, - fieldFormatter: (x) => { - return x; - }, - makeLabel: () => { - return 'foobar'; - }, - }, - { - type: { - type: 'buckets', - }, - params: { useGeoCentroid: true }, - }, - ], - }; - vis.getAggConfig = function () { - return mockAggs; - }; - vis.aggs = mockAggs; - }); - - afterEach(function () { - teardownDOM(); - imageComparator.destroy(); - }); - - it('should initialize OK (may fail in dev env)', async function () { - const coordinateMapVisualization = new CoordinateMapsVisualization(domNode, vis); - await coordinateMapVisualization.render(dummyESResponse, vis.params, { - resize: false, - params: true, - aggs: true, - data: true, - uiState: false, - }); - - const mismatchedPixels = await compareImage(initial, 0); - coordinateMapVisualization.destroy(); - expect(mismatchedPixels).to.be.lessThan(PIXEL_DIFF); - }); - - it('should toggle to Heatmap OK', async function () { - const coordinateMapVisualization = new CoordinateMapsVisualization(domNode, vis); - await coordinateMapVisualization.render(dummyESResponse, vis.params, { - resize: false, - params: true, - aggs: true, - data: true, - uiState: false, - }); - - vis.params.mapType = 'Heatmap'; - await coordinateMapVisualization.render(dummyESResponse, vis.params, { - resize: false, - params: true, - aggs: false, - data: false, - uiState: false, - }); - - const mismatchedPixels = await compareImage(heatmapRaw, 1); - coordinateMapVisualization.destroy(); - expect(mismatchedPixels).to.be.lessThan(PIXEL_DIFF); - }); - - it('should toggle back&forth OK between mapTypes (may fail in dev env)', async function () { - const coordinateMapVisualization = new CoordinateMapsVisualization(domNode, vis); - await coordinateMapVisualization.render(dummyESResponse, vis.params, { - resize: false, - params: true, - aggs: true, - data: true, - uiState: false, - }); - - vis.params.mapType = 'Heatmap'; - await coordinateMapVisualization.render(dummyESResponse, vis.params, { - resize: false, - params: true, - aggs: false, - data: false, - uiState: false, - }); - - vis.params.mapType = 'Scaled Circle Markers'; - await coordinateMapVisualization.render(dummyESResponse, vis.params, { - resize: false, - params: true, - aggs: false, - data: false, - uiState: false, - }); - - const mismatchedPixels = await compareImage(initial, 0); - coordinateMapVisualization.destroy(); - expect(mismatchedPixels).to.be.lessThan(PIXEL_DIFF); - }); - - it('should toggle to different color schema ok (may fail in dev env)', async function () { - const coordinateMapVisualization = new CoordinateMapsVisualization(domNode, vis); - await coordinateMapVisualization.render(dummyESResponse, vis.params, { - resize: false, - params: true, - aggs: true, - data: true, - uiState: false, - }); - - vis.params.colorSchema = 'Blues'; - await coordinateMapVisualization.render(dummyESResponse, vis.params, { - resize: false, - params: true, - aggs: false, - data: false, - uiState: false, - }); - - const mismatchedPixels = await compareImage(blues, 0); - coordinateMapVisualization.destroy(); - expect(mismatchedPixels).to.be.lessThan(PIXEL_DIFF); - }); - - it('should toggle to different color schema and maptypes ok', async function () { - const coordinateMapVisualization = new CoordinateMapsVisualization(domNode, vis); - await coordinateMapVisualization.render(dummyESResponse, vis.params, { - resize: false, - params: true, - aggs: true, - data: true, - uiState: false, - }); - - vis.params.colorSchema = 'Greens'; - vis.params.mapType = 'Shaded Geohash Grid'; - await coordinateMapVisualization.render(dummyESResponse, vis.params, { - resize: false, - params: true, - aggs: false, - data: false, - uiState: false, - }); - - const mismatchedPixels = await compareImage(shadedGeohashGrid, 0); - coordinateMapVisualization.destroy(); - expect(mismatchedPixels).to.be.lessThan(PIXEL_DIFF); - }); - }); - - async function compareImage(expectedImageSource, index) { - const elementList = domNode.querySelectorAll('canvas'); - const firstCanvasOnMap = elementList[index]; - return imageComparator.compareImage(firstCanvasOnMap, expectedImageSource, THRESHOLD); - } - - function setupDOM(width, height) { - domNode = document.createElement('div'); - domNode.style.top = '0'; - domNode.style.left = '0'; - domNode.style.width = width; - domNode.style.height = height; - domNode.style.position = 'fixed'; - domNode.style.border = '1px solid blue'; - domNode.style['pointer-events'] = 'none'; - document.body.appendChild(domNode); - } - - function teardownDOM() { - domNode.innerHTML = ''; - document.body.removeChild(domNode); - } -}); diff --git a/src/plugins/tile_map/public/__tests__/dummy_es_response.json b/src/plugins/tile_map/public/__tests__/dummy_es_response.json deleted file mode 100644 index 1c54857f9d67a..0000000000000 --- a/src/plugins/tile_map/public/__tests__/dummy_es_response.json +++ /dev/null @@ -1,1810 +0,0 @@ -{ - "featureCollection": { - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -84.9070567265153, - 36.36630680412054 - ] - }, - "properties": { - "geohash": "dn", - "doc_count": 715, - "geohash_meta": { - "center": [ - 36.5625, - -84.375 - ], - "rectangle": [ - [ - 33.75, - -90 - ], - [ - 33.75, - -78.75 - ], - [ - 39.375, - -78.75 - ], - [ - 39.375, - -90 - ] - ] - }, - "value": 715 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -84.9149083904922, - 41.58417354337871 - ] - }, - "properties": { - "geohash": "dp", - "doc_count": 657, - "geohash_meta": { - "center": [ - 42.1875, - -84.375 - ], - "rectangle": [ - [ - 39.375, - -90 - ], - [ - 39.375, - -78.75 - ], - [ - 45, - -78.75 - ], - [ - 45, - -90 - ] - ] - }, - "value": 657 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -95.05993634462357, - 36.32617760449648 - ] - }, - "properties": { - "geohash": "9y", - "doc_count": 623, - "geohash_meta": { - "center": [ - 36.5625, - -95.625 - ], - "rectangle": [ - [ - 33.75, - -101.25 - ], - [ - 33.75, - -90 - ], - [ - 39.375, - -90 - ], - [ - 39.375, - -101.25 - ] - ] - }, - "value": 623 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -73.9467297680676, - 42.102721743285656 - ] - }, - "properties": { - "geohash": "dr", - "doc_count": 576, - "geohash_meta": { - "center": [ - 42.1875, - -73.125 - ], - "rectangle": [ - [ - 39.375, - -78.75 - ], - [ - 39.375, - -67.5 - ], - [ - 45, - -67.5 - ], - [ - 45, - -78.75 - ] - ] - }, - "value": 576 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -95.22280854173005, - 41.98196731042117 - ] - }, - "properties": { - "geohash": "9z", - "doc_count": 555, - "geohash_meta": { - "center": [ - 42.1875, - -95.625 - ], - "rectangle": [ - [ - 39.375, - -101.25 - ], - [ - 39.375, - -90 - ], - [ - 45, - -90 - ], - [ - 45, - -101.25 - ] - ] - }, - "value": 555 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -84.76328378543258, - 31.699854251928627 - ] - }, - "properties": { - "geohash": "dj", - "doc_count": 528, - "geohash_meta": { - "center": [ - 30.9375, - -84.375 - ], - "rectangle": [ - [ - 28.125, - -90 - ], - [ - 28.125, - -78.75 - ], - [ - 33.75, - -78.75 - ], - [ - 33.75, - -90 - ] - ] - }, - "value": 528 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -95.2651846781373, - 31.394152916036546 - ] - }, - "properties": { - "geohash": "9v", - "doc_count": 510, - "geohash_meta": { - "center": [ - 30.9375, - -95.625 - ], - "rectangle": [ - [ - 28.125, - -101.25 - ], - [ - 28.125, - -90 - ], - [ - 33.75, - -90 - ], - [ - 33.75, - -101.25 - ] - ] - }, - "value": 510 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -118.95955030806363, - 36.473086257465184 - ] - }, - "properties": { - "geohash": "9q", - "doc_count": 390, - "geohash_meta": { - "center": [ - 36.5625, - -118.125 - ], - "rectangle": [ - [ - 33.75, - -123.75 - ], - [ - 33.75, - -112.5 - ], - [ - 39.375, - -112.5 - ], - [ - 39.375, - -123.75 - ] - ] - }, - "value": 390 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -106.9422698020935, - 36.371589582413435 - ] - }, - "properties": { - "geohash": "9w", - "doc_count": 257, - "geohash_meta": { - "center": [ - 36.5625, - -106.875 - ], - "rectangle": [ - [ - 33.75, - -112.5 - ], - [ - 33.75, - -101.25 - ], - [ - 39.375, - -101.25 - ], - [ - 39.375, - -112.5 - ] - ] - }, - "value": 257 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -95.21766104735434, - 46.71993430238217 - ] - }, - "properties": { - "geohash": "cb", - "doc_count": 248, - "geohash_meta": { - "center": [ - 47.8125, - -95.625 - ], - "rectangle": [ - [ - 45, - -101.25 - ], - [ - 45, - -90 - ], - [ - 50.625, - -90 - ], - [ - 50.625, - -101.25 - ] - ] - }, - "value": 248 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -119.4527724198997, - 47.01064535882324 - ] - }, - "properties": { - "geohash": "c2", - "doc_count": 241, - "geohash_meta": { - "center": [ - 47.8125, - -118.125 - ], - "rectangle": [ - [ - 45, - -123.75 - ], - [ - 45, - -112.5 - ], - [ - 50.625, - -112.5 - ], - [ - 50.625, - -123.75 - ] - ] - }, - "value": 241 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -106.35303659364581, - 41.90058804117143 - ] - }, - "properties": { - "geohash": "9x", - "doc_count": 233, - "geohash_meta": { - "center": [ - 42.1875, - -106.875 - ], - "rectangle": [ - [ - 39.375, - -112.5 - ], - [ - 39.375, - -101.25 - ], - [ - 45, - -101.25 - ], - [ - 45, - -112.5 - ] - ] - }, - "value": 233 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -119.78077582083642, - 42.019549501128495 - ] - }, - "properties": { - "geohash": "9r", - "doc_count": 202, - "geohash_meta": { - "center": [ - 42.1875, - -118.125 - ], - "rectangle": [ - [ - 39.375, - -123.75 - ], - [ - 39.375, - -112.5 - ], - [ - 45, - -112.5 - ], - [ - 45, - -123.75 - ] - ] - }, - "value": 202 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -77.02892781235278, - 37.012665029615164 - ] - }, - "properties": { - "geohash": "dq", - "doc_count": 188, - "geohash_meta": { - "center": [ - 36.5625, - -73.125 - ], - "rectangle": [ - [ - 33.75, - -78.75 - ], - [ - 33.75, - -67.5 - ], - [ - 39.375, - -67.5 - ], - [ - 39.375, - -78.75 - ] - ] - }, - "value": 188 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -106.99090437032282, - 47.078339285217226 - ] - }, - "properties": { - "geohash": "c8", - "doc_count": 158, - "geohash_meta": { - "center": [ - 47.8125, - -106.875 - ], - "rectangle": [ - [ - 45, - -112.5 - ], - [ - 45, - -101.25 - ], - [ - 50.625, - -101.25 - ], - [ - 50.625, - -112.5 - ] - ] - }, - "value": 158 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -107.13654454797506, - 32.61927543673664 - ] - }, - "properties": { - "geohash": "9t", - "doc_count": 138, - "geohash_meta": { - "center": [ - 30.9375, - -106.875 - ], - "rectangle": [ - [ - 28.125, - -112.5 - ], - [ - 28.125, - -101.25 - ], - [ - 33.75, - -101.25 - ], - [ - 33.75, - -112.5 - ] - ] - }, - "value": 138 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -152.64550829306245, - 59.914903342723846 - ] - }, - "properties": { - "geohash": "bd", - "doc_count": 126, - "geohash_meta": { - "center": [ - 59.0625, - -151.875 - ], - "rectangle": [ - [ - 56.25, - -157.5 - ], - [ - 56.25, - -146.25 - ], - [ - 61.875, - -146.25 - ], - [ - 61.875, - -157.5 - ] - ] - }, - "value": 126 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -81.2875135615468, - 26.6619403520599 - ] - }, - "properties": { - "geohash": "dh", - "doc_count": 96, - "geohash_meta": { - "center": [ - 25.3125, - -84.375 - ], - "rectangle": [ - [ - 22.5, - -90 - ], - [ - 22.5, - -78.75 - ], - [ - 28.125, - -78.75 - ], - [ - 28.125, - -90 - ] - ] - }, - "value": 96 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -161.96613382548094, - 60.42251357808709 - ] - }, - "properties": { - "geohash": "b6", - "doc_count": 95, - "geohash_meta": { - "center": [ - 59.0625, - -163.125 - ], - "rectangle": [ - [ - 56.25, - -168.75 - ], - [ - 56.25, - -157.5 - ], - [ - 61.875, - -157.5 - ], - [ - 61.875, - -168.75 - ] - ] - }, - "value": 95 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -162.01718556694686, - 64.50348428450525 - ] - }, - "properties": { - "geohash": "b7", - "doc_count": 83, - "geohash_meta": { - "center": [ - 64.6875, - -163.125 - ], - "rectangle": [ - [ - 61.875, - -168.75 - ], - [ - 61.875, - -157.5 - ], - [ - 67.5, - -157.5 - ], - [ - 67.5, - -168.75 - ] - ] - }, - "value": 83 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -152.76569221168756, - 64.75516308099031 - ] - }, - "properties": { - "geohash": "be", - "doc_count": 77, - "geohash_meta": { - "center": [ - 64.6875, - -151.875 - ], - "rectangle": [ - [ - 61.875, - -157.5 - ], - [ - 61.875, - -146.25 - ], - [ - 67.5, - -146.25 - ], - [ - 67.5, - -157.5 - ] - ] - }, - "value": 77 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -86.92213883623481, - 45.67713766358793 - ] - }, - "properties": { - "geohash": "f0", - "doc_count": 70, - "geohash_meta": { - "center": [ - 47.8125, - -84.375 - ], - "rectangle": [ - [ - 45, - -90 - ], - [ - 45, - -78.75 - ], - [ - 50.625, - -78.75 - ], - [ - 50.625, - -90 - ] - ] - }, - "value": 70 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -115.65346693620086, - 33.081501605920494 - ] - }, - "properties": { - "geohash": "9m", - "doc_count": 61, - "geohash_meta": { - "center": [ - 30.9375, - -118.125 - ], - "rectangle": [ - [ - 28.125, - -123.75 - ], - [ - 28.125, - -112.5 - ], - [ - 33.75, - -112.5 - ], - [ - 33.75, - -123.75 - ] - ] - }, - "value": 61 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -65.73361264541745, - 18.2236089091748 - ] - }, - "properties": { - "geohash": "de", - "doc_count": 41, - "geohash_meta": { - "center": [ - 19.6875, - -61.875 - ], - "rectangle": [ - [ - 16.875, - -67.5 - ], - [ - 16.875, - -56.25 - ], - [ - 22.5, - -56.25 - ], - [ - 22.5, - -67.5 - ] - ] - }, - "value": 41 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -143.12310453504324, - 64.18042578734457 - ] - }, - "properties": { - "geohash": "bg", - "doc_count": 39, - "geohash_meta": { - "center": [ - 64.6875, - -140.625 - ], - "rectangle": [ - [ - 61.875, - -146.25 - ], - [ - 61.875, - -135 - ], - [ - 67.5, - -135 - ], - [ - 67.5, - -146.25 - ] - ] - }, - "value": 39 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -124.1186392866075, - 42.33813495375216 - ] - }, - "properties": { - "geohash": "9p", - "doc_count": 37, - "geohash_meta": { - "center": [ - 42.1875, - -129.375 - ], - "rectangle": [ - [ - 39.375, - -135 - ], - [ - 39.375, - -123.75 - ], - [ - 45, - -123.75 - ], - [ - 45, - -135 - ] - ] - }, - "value": 37 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -137.9709525872022, - 59.20598397497088 - ] - }, - "properties": { - "geohash": "bf", - "doc_count": 36, - "geohash_meta": { - "center": [ - 59.0625, - -140.625 - ], - "rectangle": [ - [ - 56.25, - -146.25 - ], - [ - 56.25, - -135 - ], - [ - 61.875, - -135 - ], - [ - 61.875, - -146.25 - ] - ] - }, - "value": 36 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -132.43937451392412, - 55.6085482891649 - ] - }, - "properties": { - "geohash": "c1", - "doc_count": 35, - "geohash_meta": { - "center": [ - 53.4375, - -129.375 - ], - "rectangle": [ - [ - 50.625, - -135 - ], - [ - 50.625, - -123.75 - ], - [ - 56.25, - -123.75 - ], - [ - 56.25, - -135 - ] - ] - }, - "value": 35 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -98.05168284103274, - 27.216137498617172 - ] - }, - "properties": { - "geohash": "9u", - "doc_count": 33, - "geohash_meta": { - "center": [ - 25.3125, - -95.625 - ], - "rectangle": [ - [ - 22.5, - -101.25 - ], - [ - 22.5, - -90 - ], - [ - 28.125, - -90 - ], - [ - 28.125, - -101.25 - ] - ] - }, - "value": 33 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -133.99208377115428, - 57.29258285835385 - ] - }, - "properties": { - "geohash": "c4", - "doc_count": 30, - "geohash_meta": { - "center": [ - 59.0625, - -129.375 - ], - "rectangle": [ - [ - 56.25, - -135 - ], - [ - 56.25, - -123.75 - ], - [ - 61.875, - -123.75 - ], - [ - 61.875, - -135 - ] - ] - }, - "value": 30 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -68.79461143165827, - 45.693174339830875 - ] - }, - "properties": { - "geohash": "f2", - "doc_count": 24, - "geohash_meta": { - "center": [ - 47.8125, - -73.125 - ], - "rectangle": [ - [ - 45, - -78.75 - ], - [ - 45, - -67.5 - ], - [ - 50.625, - -67.5 - ], - [ - 50.625, - -78.75 - ] - ] - }, - "value": 24 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -163.01397004164755, - 54.89952846430242 - ] - }, - "properties": { - "geohash": "b3", - "doc_count": 24, - "geohash_meta": { - "center": [ - 53.4375, - -163.125 - ], - "rectangle": [ - [ - 50.625, - -168.75 - ], - [ - 50.625, - -157.5 - ], - [ - 56.25, - -157.5 - ], - [ - 56.25, - -168.75 - ] - ] - }, - "value": 24 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -156.45671758800745, - 20.677654556930065 - ] - }, - "properties": { - "geohash": "8e", - "doc_count": 21, - "geohash_meta": { - "center": [ - 19.6875, - -151.875 - ], - "rectangle": [ - [ - 16.875, - -157.5 - ], - [ - 16.875, - -146.25 - ], - [ - 22.5, - -146.25 - ], - [ - 22.5, - -157.5 - ] - ] - }, - "value": 21 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -151.52415155433118, - 68.92314183991402 - ] - }, - "properties": { - "geohash": "bs", - "doc_count": 18, - "geohash_meta": { - "center": [ - 70.3125, - -151.875 - ], - "rectangle": [ - [ - 67.5, - -157.5 - ], - [ - 67.5, - -146.25 - ], - [ - 73.125, - -146.25 - ], - [ - 73.125, - -157.5 - ] - ] - }, - "value": 18 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -124.08633585087955, - 46.76067248918116 - ] - }, - "properties": { - "geohash": "c0", - "doc_count": 13, - "geohash_meta": { - "center": [ - 47.8125, - -129.375 - ], - "rectangle": [ - [ - 45, - -135 - ], - [ - 45, - -123.75 - ], - [ - 50.625, - -123.75 - ], - [ - 50.625, - -135 - ] - ] - }, - "value": 13 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -158.69247693568468, - 21.67966120876372 - ] - }, - "properties": { - "geohash": "87", - "doc_count": 12, - "geohash_meta": { - "center": [ - 19.6875, - -163.125 - ], - "rectangle": [ - [ - 16.875, - -168.75 - ], - [ - 16.875, - -157.5 - ], - [ - 22.5, - -157.5 - ], - [ - 22.5, - -168.75 - ] - ] - }, - "value": 12 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -169.91430887952447, - 14.246335001662374 - ] - }, - "properties": { - "geohash": "84", - "doc_count": 12, - "geohash_meta": { - "center": [ - 14.0625, - -174.375 - ], - "rectangle": [ - [ - 11.25, - -180 - ], - [ - 11.25, - -168.75 - ], - [ - 16.875, - -168.75 - ], - [ - 16.875, - -180 - ] - ] - }, - "value": 12 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -145.1541736163199, - 14.100071671418846 - ] - }, - "properties": { - "geohash": "8f", - "doc_count": 10, - "geohash_meta": { - "center": [ - 14.0625, - -140.625 - ], - "rectangle": [ - [ - 11.25, - -146.25 - ], - [ - 11.25, - -135 - ], - [ - 16.875, - -135 - ], - [ - 16.875, - -146.25 - ] - ] - }, - "value": 10 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -163.34791378118098, - 69.16283434722573 - ] - }, - "properties": { - "geohash": "bk", - "doc_count": 9, - "geohash_meta": { - "center": [ - 70.3125, - -163.125 - ], - "rectangle": [ - [ - 67.5, - -168.75 - ], - [ - 67.5, - -157.5 - ], - [ - 73.125, - -157.5 - ], - [ - 73.125, - -168.75 - ] - ] - }, - "value": 9 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -67.16800019145012, - 44.8411110509187 - ] - }, - "properties": { - "geohash": "dx", - "doc_count": 6, - "geohash_meta": { - "center": [ - 42.1875, - -61.875 - ], - "rectangle": [ - [ - 39.375, - -67.5 - ], - [ - 39.375, - -56.25 - ], - [ - 45, - -56.25 - ], - [ - 45, - -67.5 - ] - ] - }, - "value": 6 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -169.80291330255568, - 56.72484784852713 - ] - }, - "properties": { - "geohash": "b4", - "doc_count": 4, - "geohash_meta": { - "center": [ - 59.0625, - -174.375 - ], - "rectangle": [ - [ - 56.25, - -180 - ], - [ - 56.25, - -168.75 - ], - [ - 61.875, - -168.75 - ], - [ - 61.875, - -180 - ] - ] - }, - "value": 4 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -145.57611141353846, - 68.11608082149178 - ] - }, - "properties": { - "geohash": "bu", - "doc_count": 3, - "geohash_meta": { - "center": [ - 70.3125, - -140.625 - ], - "rectangle": [ - [ - 67.5, - -146.25 - ], - [ - 67.5, - -135 - ], - [ - 73.125, - -135 - ], - [ - 73.125, - -146.25 - ] - ] - }, - "value": 3 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -171.11272992566228, - 63.72657997068018 - ] - }, - "properties": { - "geohash": "b5", - "doc_count": 2, - "geohash_meta": { - "center": [ - 64.6875, - -174.375 - ], - "rectangle": [ - [ - 61.875, - -180 - ], - [ - 61.875, - -168.75 - ], - [ - 67.5, - -168.75 - ], - [ - 67.5, - -180 - ] - ] - }, - "value": 2 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -174.20635032467544, - 52.220348292030394 - ] - }, - "properties": { - "geohash": "b1", - "doc_count": 2, - "geohash_meta": { - "center": [ - 53.4375, - -174.375 - ], - "rectangle": [ - [ - 50.625, - -180 - ], - [ - 50.625, - -168.75 - ], - [ - 56.25, - -168.75 - ], - [ - 56.25, - -180 - ] - ] - }, - "value": 2 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -145.76861112378538, - 18.1244444148615 - ] - }, - "properties": { - "geohash": "8g", - "doc_count": 2, - "geohash_meta": { - "center": [ - 19.6875, - -140.625 - ], - "rectangle": [ - [ - 16.875, - -146.25 - ], - [ - 16.875, - -135 - ], - [ - 22.5, - -135 - ], - [ - 22.5, - -146.25 - ] - ] - }, - "value": 2 - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -123.75373472459614, - 39.26203776150942 - ] - }, - "properties": { - "geohash": "9n", - "doc_count": 1, - "geohash_meta": { - "center": [ - 36.5625, - -129.375 - ], - "rectangle": [ - [ - 33.75, - -135 - ], - [ - 33.75, - -123.75 - ], - [ - 39.375, - -123.75 - ], - [ - 39.375, - -135 - ] - ] - }, - "value": 1 - } - } - ] - }, - "meta": { - "min": 1, - "max": 715, - "geohashPrecision": 2, - "geohashGridDimensionsAtEquator": [ - 1252300, - 624100 - ] - } -} diff --git a/src/plugins/tile_map/public/__tests__/geohash_layer.js b/src/plugins/tile_map/public/__tests__/geohash_layer.js deleted file mode 100644 index 000a0e16dd16b..0000000000000 --- a/src/plugins/tile_map/public/__tests__/geohash_layer.js +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import { GeohashLayer } from '../geohash_layer'; -// import heatmapPng from './heatmap.png'; -import scaledCircleMarkersPng from './scaled_circle_markers.png'; -// import shadedCircleMarkersPng from './shadedCircleMarkers.png'; -import { ImageComparator } from 'test_utils/image_comparator'; -import GeoHashSampleData from './dummy_es_response.json'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { KibanaMap } from '../../../maps_legacy/public/map/kibana_map'; - -describe('geohash_layer', function () { - let domNode; - let expectCanvas; - let kibanaMap; - let imageComparator; - - function setupDOM() { - domNode = document.createElement('div'); - domNode.style.top = '0'; - domNode.style.left = '0'; - domNode.style.width = '512px'; - domNode.style.height = '512px'; - domNode.style.position = 'fixed'; - domNode.style['pointer-events'] = 'none'; - document.body.appendChild(domNode); - - expectCanvas = document.createElement('canvas'); - document.body.appendChild(expectCanvas); - } - - function teardownDOM() { - domNode.innerHTML = ''; - document.body.removeChild(domNode); - document.body.removeChild(expectCanvas); - } - - describe('GeohashGridLayer', function () { - beforeEach(async function () { - setupDOM(); - imageComparator = new ImageComparator(); - kibanaMap = new KibanaMap(domNode, { - minZoom: 1, - maxZoom: 10, - }); - kibanaMap.setZoomLevel(3); - kibanaMap.setCenter({ - lon: -100, - lat: 40, - }); - }); - - afterEach(function () { - // return; - kibanaMap.destroy(); - teardownDOM(); - imageComparator.destroy(); - }); - - [ - { - options: { mapType: 'Scaled Circle Markers', colorRamp: 'Yellow to Red' }, - expected: scaledCircleMarkersPng, - }, - // https://github.com/elastic/kibana/issues/19393 - // { - // options: { mapType: 'Shaded Circle Markers', colorRamp: 'Yellow to Red' }, - // expected: shadedCircleMarkersPng - // }, - // FAILING: https://github.com/elastic/kibana/issues/33323 - // { - // options: { - // mapType: 'Heatmap', - // heatmap: { - // heatClusterSize: '2' - // } - // }, - // expected: heatmapPng - // } - ].forEach(function (test) { - it(`${test.options.mapType} (may fail in dev env)`, async function () { - const geohashGridOptions = test.options; - const geohashLayer = new GeohashLayer( - GeoHashSampleData.featureCollection, - GeoHashSampleData.meta, - geohashGridOptions, - kibanaMap.getZoomLevel(), - kibanaMap - ); - kibanaMap.addLayer(geohashLayer); - - const elementList = domNode.querySelectorAll('canvas'); - expect(elementList.length).to.equal(1); - const canvas = elementList[0]; - - const mismatchedPixels = await imageComparator.compareImage(canvas, test.expected, 0.1); - expect(mismatchedPixels).to.be.lessThan(16); - }); - }); - - it('should not throw when fitting on empty-data layer', function () { - const geohashLayer = new GeohashLayer( - { - type: 'FeatureCollection', - features: [], - }, - {}, - { mapType: 'Scaled Circle Markers', colorRamp: 'Yellow to Red' }, - kibanaMap.getZoomLevel(), - kibanaMap - ); - kibanaMap.addLayer(geohashLayer); - - expect(() => { - kibanaMap.fitToData(); - }).to.not.throwException(); - }); - - it('should not throw when resizing to 0 on heatmap', function () { - const geohashGridOptions = { - mapType: 'Heatmap', - heatmap: { - heatClusterSize: '2', - }, - }; - - const geohashLayer = new GeohashLayer( - GeoHashSampleData.featureCollection, - GeoHashSampleData.meta, - geohashGridOptions, - kibanaMap.getZoomLevel(), - kibanaMap - ); - kibanaMap.addLayer(geohashLayer); - domNode.style.width = 0; - domNode.style.height = 0; - expect(() => { - kibanaMap.resize(); - }).to.not.throwException(); - }); - }); -}); diff --git a/src/plugins/tile_map/public/__tests__/heatmap.png b/src/plugins/tile_map/public/__tests__/heatmap.png deleted file mode 100644 index b355849c11766..0000000000000 Binary files a/src/plugins/tile_map/public/__tests__/heatmap.png and /dev/null differ diff --git a/src/plugins/tile_map/public/__tests__/heatmap_raw.png b/src/plugins/tile_map/public/__tests__/heatmap_raw.png deleted file mode 100644 index 6737c9d0dc807..0000000000000 Binary files a/src/plugins/tile_map/public/__tests__/heatmap_raw.png and /dev/null differ diff --git a/src/plugins/tile_map/public/__tests__/initial.png b/src/plugins/tile_map/public/__tests__/initial.png deleted file mode 100644 index d108407c58388..0000000000000 Binary files a/src/plugins/tile_map/public/__tests__/initial.png and /dev/null differ diff --git a/src/plugins/tile_map/public/__tests__/scaled_circle_markers.png b/src/plugins/tile_map/public/__tests__/scaled_circle_markers.png deleted file mode 100644 index df659d1024f75..0000000000000 Binary files a/src/plugins/tile_map/public/__tests__/scaled_circle_markers.png and /dev/null differ diff --git a/src/plugins/tile_map/public/__tests__/shaded_circle_markers.png b/src/plugins/tile_map/public/__tests__/shaded_circle_markers.png deleted file mode 100644 index 7cf3fe92f7afc..0000000000000 Binary files a/src/plugins/tile_map/public/__tests__/shaded_circle_markers.png and /dev/null differ diff --git a/src/plugins/tile_map/public/__tests__/shaded_geohash_grid.png b/src/plugins/tile_map/public/__tests__/shaded_geohash_grid.png deleted file mode 100644 index e0b19dc619323..0000000000000 Binary files a/src/plugins/tile_map/public/__tests__/shaded_geohash_grid.png and /dev/null differ diff --git a/src/plugins/timelion/public/app.js b/src/plugins/timelion/public/app.js index 0294e71084f98..614a7539de44c 100644 --- a/src/plugins/timelion/public/app.js +++ b/src/plugins/timelion/public/app.js @@ -23,7 +23,7 @@ import { i18n } from '@kbn/i18n'; import { createHashHistory } from 'history'; -import { createKbnUrlStateStorage } from '../../kibana_utils/public'; +import { createKbnUrlStateStorage, withNotifyOnErrors } from '../../kibana_utils/public'; import { syncQueryStateWithUrl } from '../../data/public'; import { getSavedSheetBreadcrumbs, getCreateBreadcrumbs } from './breadcrumbs'; @@ -63,6 +63,7 @@ export function initTimelionApp(app, deps) { createKbnUrlStateStorage({ history, useHash: deps.core.uiSettings.get('state:storeInSessionStorage'), + ...withNotifyOnErrors(deps.core.notifications.toasts), }) ); app.config(watchMultiDecorator); diff --git a/src/plugins/usage_collection/README.md b/src/plugins/usage_collection/README.md index a828096f86042..4f0f10703c5e9 100644 --- a/src/plugins/usage_collection/README.md +++ b/src/plugins/usage_collection/README.md @@ -10,8 +10,6 @@ To integrate with the telemetry services for usage collection of your feature, t All you need to provide is a `type` for organizing your fields, `schema` field to define the expected types of usage fields reported, and a `fetch` method for returning your usage data. Then you need to make the Telemetry service aware of the collector by registering it. -### New Platform - 1. Make sure `usageCollection` is in your optional Plugins: ```json @@ -205,6 +203,10 @@ There are a few ways you can test that your usage collector is working properly. # UI Metric app +The UI metrics implementation in its current state is not useful. We are working on improving the implementation to enable teams to use the data to visualize and gather information from what is being reported. Please refer to the telemetry team if you are interested in adding ui_metrics to your plugin. + +**Until a better implementation is introduced, please defer from adding any new ui metrics.** + ## Purpose The purpose of the UI Metric app is to provide a tool for gathering data on how users interact with diff --git a/src/plugins/vis_type_timelion/public/helpers/arg_value_suggestions.ts b/src/plugins/vis_type_timelion/public/helpers/arg_value_suggestions.ts index 19ec46bd7f659..85d41aab5859d 100644 --- a/src/plugins/vis_type_timelion/public/helpers/arg_value_suggestions.ts +++ b/src/plugins/vis_type_timelion/public/helpers/arg_value_suggestions.ts @@ -117,6 +117,7 @@ export function getArgValueSuggestions() { const valueSplit = partial.split(':'); return indexPattern.fields + .getAll() .filter((field) => { return ( field.aggregatable && @@ -136,6 +137,7 @@ export function getArgValueSuggestions() { } return indexPattern.fields + .getAll() .filter((field) => { return ( field.aggregatable && @@ -155,6 +157,7 @@ export function getArgValueSuggestions() { } return indexPattern.fields + .getAll() .filter((field) => { return ( 'date' === field.type && diff --git a/src/plugins/vis_type_timeseries/common/vis_schema.ts b/src/plugins/vis_type_timeseries/common/vis_schema.ts index a462e488c6732..c1730e6a15435 100644 --- a/src/plugins/vis_type_timeseries/common/vis_schema.ts +++ b/src/plugins/vis_type_timeseries/common/vis_schema.ts @@ -119,6 +119,10 @@ export const metricsItems = schema.object({ type: stringRequired, value: stringOptionalNullable, values: schema.maybe(schema.nullable(schema.arrayOf(schema.nullable(schema.string())))), + size: stringOptionalNullable, + agg_with: stringOptionalNullable, + order: stringOptionalNullable, + order_by: stringOptionalNullable, }); const splitFiltersItems = schema.object({ diff --git a/src/plugins/vis_type_vislib/public/vislib/errors.ts b/src/plugins/vis_type_vislib/public/vislib/errors.ts index c2965e8165759..b047d0900cd48 100644 --- a/src/plugins/vis_type_vislib/public/vislib/errors.ts +++ b/src/plugins/vis_type_vislib/public/vislib/errors.ts @@ -19,6 +19,7 @@ /* eslint-disable max-classes-per-file */ +import { i18n } from '@kbn/i18n'; import { KbnError } from '../../../kibana_utils/public'; export class VislibError extends KbnError { @@ -51,6 +52,10 @@ export class PieContainsAllZeros extends VislibError { export class NoResults extends VislibError { constructor() { - super('No results found'); + super( + i18n.translate('visTypeVislib.vislib.errors.noResultsFoundTitle', { + defaultMessage: 'No results found', + }) + ); } } diff --git a/src/plugins/visualizations/public/components/visualization_noresults.tsx b/src/plugins/visualizations/public/components/visualization_noresults.tsx index 1b45463f1d2ef..c77ef4490a4b3 100644 --- a/src/plugins/visualizations/public/components/visualization_noresults.tsx +++ b/src/plugins/visualizations/public/components/visualization_noresults.tsx @@ -18,6 +18,7 @@ */ import { EuiIcon, EuiSpacer, EuiText } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import React from 'react'; interface VisualizationNoResultsProps { @@ -37,7 +38,11 @@ export class VisualizationNoResults extends React.Component -

No results found

+

+ {i18n.translate('visualizations.noResultsFoundTitle', { + defaultMessage: 'No results found', + })} +

diff --git a/src/plugins/visualizations/public/legacy/__tests__/vis_update_objs/gauge_objs.js b/src/plugins/visualizations/public/legacy/vis_update_state.stub.js similarity index 100% rename from src/plugins/visualizations/public/legacy/__tests__/vis_update_objs/gauge_objs.js rename to src/plugins/visualizations/public/legacy/vis_update_state.stub.js diff --git a/src/plugins/visualizations/public/legacy/vis_update_state.test.js b/src/plugins/visualizations/public/legacy/vis_update_state.test.js index 7ddf0cc6e33e1..d0a735fbacdc2 100644 --- a/src/plugins/visualizations/public/legacy/vis_update_state.test.js +++ b/src/plugins/visualizations/public/legacy/vis_update_state.test.js @@ -21,7 +21,7 @@ import _ from 'lodash'; import { updateOldState } from './vis_update_state'; // eslint-disable-next-line camelcase -import { pre_6_1, since_6_1 } from './__tests__/vis_update_objs/gauge_objs'; +import { pre_6_1, since_6_1 } from './vis_update_state.stub'; function watchForChanges(obj) { const originalObject = _.cloneDeep(obj); diff --git a/src/plugins/visualize/public/application/utils/get_top_nav_config.tsx b/src/plugins/visualize/public/application/utils/get_top_nav_config.tsx index 392168a530087..da9ba66a914dd 100644 --- a/src/plugins/visualize/public/application/utils/get_top_nav_config.tsx +++ b/src/plugins/visualize/public/application/utils/get_top_nav_config.tsx @@ -114,7 +114,7 @@ export const getTopNavConfig = ( application.navigateToApp(originatingApp); } } else { - if (setOriginatingApp && originatingApp && savedVis.copyOnSave) { + if (setOriginatingApp && originatingApp && newlyCreated) { setOriginatingApp(undefined); } chrome.docTitle.change(savedVis.lastSavedTitle); diff --git a/src/plugins/visualize/public/plugin.ts b/src/plugins/visualize/public/plugin.ts index fd9a67599414f..3299319e613a0 100644 --- a/src/plugins/visualize/public/plugin.ts +++ b/src/plugins/visualize/public/plugin.ts @@ -31,7 +31,12 @@ import { ScopedHistory, } from 'kibana/public'; -import { Storage, createKbnUrlTracker, createKbnUrlStateStorage } from '../../kibana_utils/public'; +import { + Storage, + createKbnUrlTracker, + createKbnUrlStateStorage, + withNotifyOnErrors, +} from '../../kibana_utils/public'; import { DataPublicPluginStart, DataPublicPluginSetup, esFilters } from '../../data/public'; import { NavigationPublicPluginStart as NavigationStart } from '../../navigation/public'; import { SharePluginStart } from '../../share/public'; @@ -150,6 +155,7 @@ export class VisualizePlugin kbnUrlStateStorage: createKbnUrlStateStorage({ history, useHash: coreStart.uiSettings.get('state:storeInSessionStorage'), + ...withNotifyOnErrors(coreStart.notifications.toasts), }), kibanaLegacy: pluginsStart.kibanaLegacy, pluginInitializerContext: this.initializerContext, diff --git a/src/test_utils/public/stub_index_pattern.js b/src/test_utils/public/stub_index_pattern.js index 5a81139157cef..f7b65930b683d 100644 --- a/src/test_utils/public/stub_index_pattern.js +++ b/src/test_utils/public/stub_index_pattern.js @@ -22,12 +22,7 @@ import sinon from 'sinon'; // because it is one of the few places that we need to access the IndexPattern class itself, rather // than just the type. Doing this as a temporary measure; it will be left behind when migrating to NP. -import { - IndexPattern, - indexPatterns, - KBN_FIELD_TYPES, - getIndexPatternFieldListCreator, -} from '../../plugins/data/public'; +import { IndexPattern, indexPatterns, KBN_FIELD_TYPES, FieldList } from '../../plugins/data/public'; import { setFieldFormats } from '../../plugins/data/public/services'; @@ -42,16 +37,6 @@ import { getFieldFormatsRegistry } from './stub_field_formats'; export default function StubIndexPattern(pattern, getConfig, timeField, fields, core) { const registeredFieldFormats = getFieldFormatsRegistry(core); - const createFieldList = getIndexPatternFieldListCreator({ - fieldFormats: { - getDefaultInstance: () => ({ - convert: (val) => String(val), - }), - }, - toastNotifications: { - addDanger: () => {}, - }, - }); this.id = pattern; this.title = pattern; @@ -74,9 +59,12 @@ export default function StubIndexPattern(pattern, getConfig, timeField, fields, ); this.fieldsFetcher = { apiClient: { baseUrl: '' } }; this.formatField = this.formatHit.formatField; + this.getFormatterForField = () => ({ + convert: () => '', + }); this._reindexFields = function () { - this.fields = createFieldList(this, this.fields || fields, false); + this.fields = new FieldList(this, this.fields || fields, false); }; this.stubSetFieldFormat = function (fieldName, id, params) { diff --git a/test/api_integration/apis/telemetry/telemetry_local.js b/test/api_integration/apis/telemetry/telemetry_local.js index 88e6b3a29052e..8b10f412fae27 100644 --- a/test/api_integration/apis/telemetry/telemetry_local.js +++ b/test/api_integration/apis/telemetry/telemetry_local.js @@ -90,7 +90,7 @@ export default function ({ getService }) { expect(stats.stack_stats.data[0].index_count).to.be(1); expect(stats.stack_stats.data[0].doc_count).to.be(0); expect(stats.stack_stats.data[0].ecs_index_count).to.be(0); - expect(stats.stack_stats.data[0].size_in_bytes).to.be.greaterThan(0); + expect(stats.stack_stats.data[0].size_in_bytes).to.be.a('number'); }); it('should pull local stats and validate fields', async () => { diff --git a/test/functional/apps/dashboard/edit_embeddable_redirects.js b/test/functional/apps/dashboard/edit_embeddable_redirects.js index 6d3d43890a962..fcc504ea24f31 100644 --- a/test/functional/apps/dashboard/edit_embeddable_redirects.js +++ b/test/functional/apps/dashboard/edit_embeddable_redirects.js @@ -21,8 +21,10 @@ import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'settings', 'common']); const esArchiver = getService('esArchiver'); + const testSubjects = getService('testSubjects'); const kibanaServer = getService('kibanaServer'); const dashboardPanelActions = getService('dashboardPanelActions'); + const dashboardVisualizations = getService('dashboardVisualizations'); describe('edit embeddable redirects', () => { before(async () => { @@ -81,6 +83,23 @@ export default function ({ getService, getPageObjects }) { await PageObjects.header.waitUntilLoadingHasFinished(); await dashboardPanelActions.openContextMenu(); await dashboardPanelActions.clickEdit(); + await PageObjects.visualize.linkedToOriginatingApp(); + await PageObjects.visualize.saveVisualizationExpectSuccess(newTitle, { + saveAsNew: true, + redirectToOrigin: false, + }); + await PageObjects.visualize.notLinkedToOriginatingApp(); + await PageObjects.common.navigateToApp('dashboard'); + }); + + it('loses originatingApp connection after first save when redirectToOrigin is false', async () => { + const newTitle = 'test create panel originatingApp'; + await PageObjects.dashboard.loadSavedDashboard('few panels'); + await PageObjects.dashboard.switchToEditMode(); + await testSubjects.exists('dashboardAddNewPanelButton'); + await testSubjects.click('dashboardAddNewPanelButton'); + await dashboardVisualizations.ensureNewVisualizationDialogIsShowing(); + await PageObjects.visualize.clickMarkdownWidget(); await PageObjects.visualize.saveVisualizationExpectSuccess(newTitle, { saveAsNew: true, redirectToOrigin: false, diff --git a/test/functional/apps/discover/_shared_links.js b/test/functional/apps/discover/_shared_links.js index 5c6a70450a0aa..94409a94e9257 100644 --- a/test/functional/apps/discover/_shared_links.js +++ b/test/functional/apps/discover/_shared_links.js @@ -26,6 +26,7 @@ export default function ({ getService, getPageObjects }) { const kibanaServer = getService('kibanaServer'); const PageObjects = getPageObjects(['common', 'discover', 'share', 'timePicker']); const browser = getService('browser'); + const toasts = getService('toasts'); describe('shared links', function describeIndexTests() { let baseUrl; @@ -132,28 +133,47 @@ export default function ({ getService, getPageObjects }) { await teardown(); }); - describe('permalink', function () { - it('should allow for copying the snapshot URL as a short URL and should open it', async function () { - const re = new RegExp(baseUrl + '/goto/[0-9a-f]{32}$'); - await PageObjects.share.checkShortenUrl(); - let actualUrl; - await retry.try(async () => { - actualUrl = await PageObjects.share.getSharedUrl(); - expect(actualUrl).to.match(re); - }); + it('should allow for copying the snapshot URL as a short URL and should open it', async function () { + const re = new RegExp(baseUrl + '/goto/[0-9a-f]{32}$'); + await PageObjects.share.checkShortenUrl(); + let actualUrl; + await retry.try(async () => { + actualUrl = await PageObjects.share.getSharedUrl(); + expect(actualUrl).to.match(re); + }); - const actualTime = await PageObjects.timePicker.getTimeConfig(); - - await browser.clearSessionStorage(); - await browser.get(actualUrl, false); - await retry.waitFor('shortUrl resolves and opens', async () => { - const resolvedUrl = await browser.getCurrentUrl(); - expect(resolvedUrl).to.match(/discover/); - const resolvedTime = await PageObjects.timePicker.getTimeConfig(); - expect(resolvedTime.start).to.equal(actualTime.start); - expect(resolvedTime.end).to.equal(actualTime.end); - return true; - }); + const actualTime = await PageObjects.timePicker.getTimeConfig(); + + await browser.clearSessionStorage(); + await browser.get(actualUrl, false); + await retry.waitFor('shortUrl resolves and opens', async () => { + const resolvedUrl = await browser.getCurrentUrl(); + expect(resolvedUrl).to.match(/discover/); + const resolvedTime = await PageObjects.timePicker.getTimeConfig(); + expect(resolvedTime.start).to.equal(actualTime.start); + expect(resolvedTime.end).to.equal(actualTime.end); + return true; + }); + }); + + it("sharing hashed url shouldn't crash the app", async () => { + const currentUrl = await browser.getCurrentUrl(); + const timeBeforeReload = await PageObjects.timePicker.getTimeConfig(); + await browser.clearSessionStorage(); + await browser.get(currentUrl, false); + await retry.waitFor('discover to open', async () => { + const resolvedUrl = await browser.getCurrentUrl(); + expect(resolvedUrl).to.match(/discover/); + const { message } = await toasts.getErrorToast(); + expect(message).to.contain( + 'Unable to completely restore the URL, be sure to use the share functionality.' + ); + await toasts.dismissAllToasts(); + const timeAfterReload = await PageObjects.timePicker.getTimeConfig(); + expect(timeBeforeReload.start).not.to.be(timeAfterReload.start); + expect(timeBeforeReload.end).not.to.be(timeAfterReload.end); + await PageObjects.timePicker.setDefaultAbsoluteRange(); + return true; }); }); }); diff --git a/test/functional/apps/management/_index_pattern_popularity.js b/test/functional/apps/management/_index_pattern_popularity.js index 530b8e1111a0c..e2fcf50ef2c12 100644 --- a/test/functional/apps/management/_index_pattern_popularity.js +++ b/test/functional/apps/management/_index_pattern_popularity.js @@ -60,7 +60,7 @@ export default function ({ getService, getPageObjects }) { // check that it is 0 (previous increase was cancelled const popularity = await PageObjects.settings.getPopularity(); log.debug('popularity = ' + popularity); - expect(popularity).to.be('0'); + expect(popularity).to.be(''); }); it('can be saved', async function () { diff --git a/test/functional/apps/management/_scripted_fields.js b/test/functional/apps/management/_scripted_fields.js index 2727313ab2336..116d1eac90cea 100644 --- a/test/functional/apps/management/_scripted_fields.js +++ b/test/functional/apps/management/_scripted_fields.js @@ -36,6 +36,7 @@ import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { + const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); const log = getService('log'); const browser = getService('browser'); @@ -57,9 +58,9 @@ export default function ({ getService, getPageObjects }) { before(async function () { await browser.setWindowSize(1200, 800); + await esArchiver.load('discover'); // delete .kibana index and then wait for Kibana to re-create it await kibanaServer.uiSettings.replace({}); - await PageObjects.settings.createIndexPattern(); await kibanaServer.uiSettings.update({}); }); diff --git a/test/functional/apps/management/_scripted_fields_filter.js b/test/functional/apps/management/_scripted_fields_filter.js index 2eb53508c2846..2d59d2ba57d5b 100644 --- a/test/functional/apps/management/_scripted_fields_filter.js +++ b/test/functional/apps/management/_scripted_fields_filter.js @@ -27,7 +27,9 @@ export default function ({ getService, getPageObjects }) { const esArchiver = getService('esArchiver'); const PageObjects = getPageObjects(['settings']); - describe('filter scripted fields', function describeIndexTests() { + // this functionality is no longer functional as of 7.0 but still needs cleanup + // https://github.com/elastic/kibana/issues/74118 + describe.skip('filter scripted fields', function describeIndexTests() { before(async function () { // delete .kibana index and then wait for Kibana to re-create it await browser.setWindowSize(1200, 800); diff --git a/test/functional/services/common/browser.ts b/test/functional/services/common/browser.ts index c38ac771e4162..b0eec5e24f635 100644 --- a/test/functional/services/common/browser.ts +++ b/test/functional/services/common/browser.ts @@ -163,6 +163,14 @@ export async function BrowserProvider({ getService }: FtrProviderContext) { return currentWithoutTime; } + /** + * Gets the page/document title of the focused window/frame. + * https://www.selenium.dev/selenium/docs/api/javascript/module/selenium-webdriver/chrome_exports_Driver.html#getTitle + */ + public async getTitle() { + return await driver.getTitle(); + } + /** * Navigates the focused window/frame to a new URL. * https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/chrome_exports_Driver.html#get diff --git a/test/functional/services/toasts.ts b/test/functional/services/toasts.ts index 92f1f726fa039..a70e4ba464ae8 100644 --- a/test/functional/services/toasts.ts +++ b/test/functional/services/toasts.ts @@ -53,6 +53,16 @@ export function ToastsProvider({ getService }: FtrProviderContext) { await dismissButton.click(); } + public async dismissAllToasts() { + const list = await this.getGlobalToastList(); + const toasts = await list.findAllByCssSelector(`.euiToast`); + for (const toast of toasts) { + await toast.moveMouseTo(); + const dismissButton = await testSubjects.findDescendant('toastCloseButton', toast); + await dismissButton.click(); + } + } + private async getToastElement(index: number) { const list = await this.getGlobalToastList(); return await list.findByCssSelector(`.euiToast:nth-child(${index})`); diff --git a/x-pack/package.json b/x-pack/package.json index dcba01a771fd5..7533741391f8e 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -199,10 +199,10 @@ "yargs": "4.8.1" }, "dependencies": { - "@babel/core": "^7.10.2", - "@babel/register": "^7.10.1", - "@babel/runtime": "^7.10.2", - "@elastic/apm-rum-react": "^1.1.2", + "@babel/core": "^7.11.1", + "@babel/register": "^7.10.5", + "@babel/runtime": "^7.11.2", + "@elastic/apm-rum-react": "^1.2.2", "@elastic/datemath": "5.0.3", "@elastic/ems-client": "7.9.3", "@elastic/eui": "26.3.1", @@ -227,9 +227,9 @@ "@turf/circle": "6.0.1", "@turf/distance": "6.0.1", "@turf/helpers": "6.0.1", - "angular": "^1.7.9", - "angular-resource": "1.7.9", - "angular-sanitize": "1.7.9", + "angular": "^1.8.0", + "angular-resource": "1.8.0", + "angular-sanitize": "1.8.0", "angular-ui-ace": "0.2.3", "apollo-cache-inmemory": "1.6.2", "apollo-client": "^2.3.8", diff --git a/x-pack/plugins/canvas/public/apps/export/export/__tests__/export_app.test.tsx b/x-pack/plugins/canvas/public/apps/export/export/__tests__/export_app.test.tsx index b0a8d1e990e75..1bb58919b7fa6 100644 --- a/x-pack/plugins/canvas/public/apps/export/export/__tests__/export_app.test.tsx +++ b/x-pack/plugins/canvas/public/apps/export/export/__tests__/export_app.test.tsx @@ -6,8 +6,8 @@ import React from 'react'; import { mount } from 'enzyme'; -// @ts-expect-error untyped local -import { ExportApp } from '../export_app'; +import { ExportApp } from '../export_app.component'; +import { CanvasWorkpad } from '../../../../../types'; jest.mock('style-it', () => ({ it: (css: string, Component: any) => Component, @@ -23,7 +23,7 @@ jest.mock('../../../../components/link', () => ({ describe('', () => { test('renders as expected', () => { - const sampleWorkpad = { + const sampleWorkpad = ({ id: 'my-workpad-abcd', css: '', pages: [ @@ -34,7 +34,7 @@ describe('', () => { elements: [3, 4, 5, 6], }, ], - }; + } as any) as CanvasWorkpad; const page1 = mount( {}} /> diff --git a/x-pack/plugins/canvas/public/apps/export/export/export_app.component.tsx b/x-pack/plugins/canvas/public/apps/export/export/export_app.component.tsx new file mode 100644 index 0000000000000..03121e749d0dc --- /dev/null +++ b/x-pack/plugins/canvas/public/apps/export/export/export_app.component.tsx @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { FC, useEffect } from 'react'; +import PropTypes from 'prop-types'; +// @ts-expect-error untyped library +import Style from 'style-it'; +// @ts-expect-error untyped local +import { WorkpadPage } from '../../../components/workpad_page'; +import { Link } from '../../../components/link'; +import { CanvasWorkpad } from '../../../../types'; + +interface Props { + workpad: CanvasWorkpad; + selectedPageIndex: number; + initializeWorkpad: () => void; +} + +export const ExportApp: FC = ({ workpad, selectedPageIndex, initializeWorkpad }) => { + const { id, pages, height, width } = workpad; + const activePage = pages[selectedPageIndex]; + const pageElementCount = activePage.elements.length; + + useEffect(() => initializeWorkpad()); + + return ( +
+
+
+ + Edit Workpad + +
+ {Style.it( + workpad.css, +
+ {}} + unregisterLayout={() => {}} + /> +
+ )} +
+
+ ); +}; + +ExportApp.propTypes = { + workpad: PropTypes.shape({ + id: PropTypes.string.isRequired, + pages: PropTypes.array.isRequired, + }).isRequired, + selectedPageIndex: PropTypes.number.isRequired, + initializeWorkpad: PropTypes.func.isRequired, +}; diff --git a/x-pack/plugins/canvas/public/apps/export/export/export_app.js b/x-pack/plugins/canvas/public/apps/export/export/export_app.js deleted file mode 100644 index 1d02d85cae0b3..0000000000000 --- a/x-pack/plugins/canvas/public/apps/export/export/export_app.js +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import PropTypes from 'prop-types'; -import Style from 'style-it'; -import { WorkpadPage } from '../../../components/workpad_page'; -import { Link } from '../../../components/link'; - -export class ExportApp extends React.PureComponent { - static propTypes = { - workpad: PropTypes.shape({ - id: PropTypes.string.isRequired, - pages: PropTypes.array.isRequired, - }).isRequired, - selectedPageIndex: PropTypes.number.isRequired, - initializeWorkpad: PropTypes.func.isRequired, - }; - - componentDidMount() { - this.props.initializeWorkpad(); - } - - render() { - const { workpad, selectedPageIndex } = this.props; - const { pages, height, width } = workpad; - const activePage = pages[selectedPageIndex]; - const pageElementCount = activePage.elements.length; - - return ( -
-
-
- - Edit Workpad - -
- {Style.it( - workpad.css, -
- {}} - unregisterLayout={() => {}} - /> -
- )} -
-
- ); - } -} diff --git a/x-pack/plugins/canvas/public/apps/export/export/export_app.ts b/x-pack/plugins/canvas/public/apps/export/export/export_app.ts new file mode 100644 index 0000000000000..b47d1950ec2b7 --- /dev/null +++ b/x-pack/plugins/canvas/public/apps/export/export/export_app.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { connect } from 'react-redux'; +import { initializeWorkpad } from '../../../state/actions/workpad'; +import { getWorkpad, getSelectedPageIndex } from '../../../state/selectors/workpad'; +import { ExportApp as Component } from './export_app.component'; +import { State } from '../../../../types'; + +export const ExportApp = connect( + (state: State) => ({ + workpad: getWorkpad(state), + selectedPageIndex: getSelectedPageIndex(state), + }), + (dispatch) => ({ + initializeWorkpad: () => dispatch(initializeWorkpad()), + }) +)(Component); diff --git a/x-pack/plugins/canvas/public/apps/export/export/index.js b/x-pack/plugins/canvas/public/apps/export/export/index.js deleted file mode 100644 index 95c46d9e1c8ae..0000000000000 --- a/x-pack/plugins/canvas/public/apps/export/export/index.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { connect } from 'react-redux'; -import { compose, branch, renderComponent } from 'recompose'; -import { initializeWorkpad } from '../../../state/actions/workpad'; -import { getWorkpad, getSelectedPageIndex } from '../../../state/selectors/workpad'; -import { LoadWorkpad } from './load_workpad'; -import { ExportApp as Component } from './export_app'; - -const mapStateToProps = (state) => ({ - workpad: getWorkpad(state), - selectedPageIndex: getSelectedPageIndex(state), -}); - -const mapDispatchToProps = (dispatch) => ({ - initializeWorkpad() { - dispatch(initializeWorkpad()); - }, -}); - -const branches = [branch(({ workpad }) => workpad == null, renderComponent(LoadWorkpad))]; - -export const ExportApp = compose( - connect(mapStateToProps, mapDispatchToProps), - ...branches -)(Component); diff --git a/x-pack/plugins/canvas/public/apps/export/export/index.ts b/x-pack/plugins/canvas/public/apps/export/export/index.ts new file mode 100644 index 0000000000000..81939d550a7ab --- /dev/null +++ b/x-pack/plugins/canvas/public/apps/export/export/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { ExportApp } from './export_app'; +export { ExportApp as ExportAppComponent } from './export_app.component'; diff --git a/x-pack/plugins/canvas/public/apps/export/index.js b/x-pack/plugins/canvas/public/apps/export/index.ts similarity index 100% rename from x-pack/plugins/canvas/public/apps/export/index.js rename to x-pack/plugins/canvas/public/apps/export/index.ts diff --git a/x-pack/plugins/canvas/public/apps/export/routes.js b/x-pack/plugins/canvas/public/apps/export/routes.ts similarity index 79% rename from x-pack/plugins/canvas/public/apps/export/routes.js rename to x-pack/plugins/canvas/public/apps/export/routes.ts index 33e375115aa19..0b4f74149fb4f 100644 --- a/x-pack/plugins/canvas/public/apps/export/routes.js +++ b/x-pack/plugins/canvas/public/apps/export/routes.ts @@ -4,10 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ +import { Dispatch } from 'redux'; +// @ts-expect-error Untyped local import * as workpadService from '../../lib/workpad_service'; import { setWorkpad } from '../../state/actions/workpad'; +// @ts-expect-error Untyped local import { fetchAllRenderables } from '../../state/actions/elements'; +// @ts-expect-error Untyped local import { setPage } from '../../state/actions/pages'; +// @ts-expect-error Untyped local import { setAssets } from '../../state/actions/assets'; import { ExportApp } from './export'; @@ -18,7 +23,13 @@ export const routes = [ { name: 'exportWorkpad', path: '/pdf/:id/page/:page', - action: (dispatch) => async ({ params, router }) => { + action: (dispatch: Dispatch) => async ({ + params, + // @ts-expect-error Fix when Router is typed. + router, + }: { + params: { id: string; page: string }; + }) => { // load workpad if given a new id via url param const fetchedWorkpad = await workpadService.get(params.id); const pageNumber = parseInt(params.page, 10); diff --git a/x-pack/plugins/canvas/public/apps/home/home_app/home_app.js b/x-pack/plugins/canvas/public/apps/home/home_app/home_app.component.tsx similarity index 79% rename from x-pack/plugins/canvas/public/apps/home/home_app/home_app.js rename to x-pack/plugins/canvas/public/apps/home/home_app/home_app.component.tsx index bfa4abbf7c56d..3c2e989cc8e51 100644 --- a/x-pack/plugins/canvas/public/apps/home/home_app/home_app.js +++ b/x-pack/plugins/canvas/public/apps/home/home_app/home_app.component.tsx @@ -4,12 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import React, { FC } from 'react'; import { EuiPage, EuiPageBody, EuiPageContent } from '@elastic/eui'; +// @ts-expect-error untyped local import { WorkpadManager } from '../../../components/workpad_manager'; +// @ts-expect-error untyped local import { setDocTitle } from '../../../lib/doc_title'; -export const HomeApp = ({ onLoad = () => {} }) => { +interface Props { + onLoad: () => void; +} + +export const HomeApp: FC = ({ onLoad = () => {} }) => { onLoad(); setDocTitle('Canvas'); return ( diff --git a/x-pack/plugins/canvas/public/apps/home/home_app/index.js b/x-pack/plugins/canvas/public/apps/home/home_app/home_app.ts similarity index 69% rename from x-pack/plugins/canvas/public/apps/home/home_app/index.js rename to x-pack/plugins/canvas/public/apps/home/home_app/home_app.ts index f78ee1f8a18af..ff9d1c1cc63ac 100644 --- a/x-pack/plugins/canvas/public/apps/home/home_app/index.js +++ b/x-pack/plugins/canvas/public/apps/home/home_app/home_app.ts @@ -6,12 +6,10 @@ import { connect } from 'react-redux'; import { resetWorkpad } from '../../../state/actions/workpad'; -import { HomeApp as Component } from './home_app'; +import { HomeApp as Component } from './home_app.component'; -const mapDispatchToProps = (dispatch) => ({ +export const HomeApp = connect(null, (dispatch) => ({ onLoad() { dispatch(resetWorkpad()); }, -}); - -export const HomeApp = connect(null, mapDispatchToProps)(Component); +}))(Component); diff --git a/x-pack/plugins/canvas/public/apps/home/home_app/index.ts b/x-pack/plugins/canvas/public/apps/home/home_app/index.ts new file mode 100644 index 0000000000000..8ea92312e3e50 --- /dev/null +++ b/x-pack/plugins/canvas/public/apps/home/home_app/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { HomeApp } from './home_app'; +export { HomeApp as HomeAppComponent } from './home_app.component'; diff --git a/x-pack/plugins/canvas/public/apps/home/index.js b/x-pack/plugins/canvas/public/apps/home/index.ts similarity index 100% rename from x-pack/plugins/canvas/public/apps/home/index.js rename to x-pack/plugins/canvas/public/apps/home/index.ts diff --git a/x-pack/plugins/canvas/public/apps/home/routes.js b/x-pack/plugins/canvas/public/apps/home/routes.ts similarity index 100% rename from x-pack/plugins/canvas/public/apps/home/routes.js rename to x-pack/plugins/canvas/public/apps/home/routes.ts diff --git a/x-pack/plugins/canvas/public/apps/index.js b/x-pack/plugins/canvas/public/apps/index.ts similarity index 88% rename from x-pack/plugins/canvas/public/apps/index.js rename to x-pack/plugins/canvas/public/apps/index.ts index c014349ca18da..8b3d378e23f80 100644 --- a/x-pack/plugins/canvas/public/apps/index.js +++ b/x-pack/plugins/canvas/public/apps/index.ts @@ -8,6 +8,7 @@ import * as home from './home'; import * as workpad from './workpad'; import * as exp from './export'; +// @ts-expect-error Router and routes are not yet strongly typed export const routes = [].concat(workpad.routes, home.routes, exp.routes); export const apps = [workpad.WorkpadApp, home.HomeApp, exp.ExportApp]; diff --git a/x-pack/plugins/canvas/public/apps/workpad/index.js b/x-pack/plugins/canvas/public/apps/workpad/index.ts similarity index 100% rename from x-pack/plugins/canvas/public/apps/workpad/index.js rename to x-pack/plugins/canvas/public/apps/workpad/index.ts diff --git a/x-pack/plugins/canvas/public/apps/workpad/routes.js b/x-pack/plugins/canvas/public/apps/workpad/routes.ts similarity index 82% rename from x-pack/plugins/canvas/public/apps/workpad/routes.js rename to x-pack/plugins/canvas/public/apps/workpad/routes.ts index a330020b741ac..d83f85f717305 100644 --- a/x-pack/plugins/canvas/public/apps/workpad/routes.js +++ b/x-pack/plugins/canvas/public/apps/workpad/routes.ts @@ -4,17 +4,24 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ErrorStrings } from '../../../i18n'; +import { Dispatch } from 'redux'; +// @ts-expect-error import * as workpadService from '../../lib/workpad_service'; import { notifyService } from '../../services'; import { getBaseBreadcrumb, getWorkpadBreadcrumb, setBreadcrumb } from '../../lib/breadcrumbs'; +// @ts-expect-error import { getDefaultWorkpad } from '../../state/defaults'; import { setWorkpad } from '../../state/actions/workpad'; +// @ts-expect-error import { setAssets, resetAssets } from '../../state/actions/assets'; +// @ts-expect-error import { setPage } from '../../state/actions/pages'; import { getWorkpad } from '../../state/selectors/workpad'; +// @ts-expect-error import { setZoomScale } from '../../state/actions/transient'; +import { ErrorStrings } from '../../../i18n'; import { WorkpadApp } from './workpad_app'; +import { State } from '../../../types'; const { workpadRoutes: strings } = ErrorStrings; @@ -25,7 +32,8 @@ export const routes = [ { name: 'createWorkpad', path: '/create', - action: (dispatch) => async ({ router }) => { + // @ts-expect-error Fix when Router is typed. + action: (dispatch: Dispatch) => async ({ router }) => { const newWorkpad = getDefaultWorkpad(); try { await workpadService.create(newWorkpad); @@ -46,7 +54,13 @@ export const routes = [ { name: 'loadWorkpad', path: '/:id(/page/:page)', - action: (dispatch, getState) => async ({ params, router }) => { + action: (dispatch: Dispatch, getState: () => State) => async ({ + params, + // @ts-expect-error Fix when Router is typed. + router, + }: { + params: { id: string; page?: string }; + }) => { // load workpad if given a new id via url param const state = getState(); const currentWorkpad = getWorkpad(state); @@ -70,10 +84,10 @@ export const routes = [ // fetch the workpad again, to get changes const workpad = getWorkpad(getState()); - const pageNumber = parseInt(params.page, 10); + const pageNumber = params.page ? parseInt(params.page, 10) : null; // no page provided, append current page to url - if (isNaN(pageNumber)) { + if (!pageNumber || isNaN(pageNumber)) { return router.redirectTo('loadWorkpad', { id: workpad.id, page: workpad.page + 1 }); } diff --git a/x-pack/plugins/canvas/public/apps/workpad/workpad_app/index.js b/x-pack/plugins/canvas/public/apps/workpad/workpad_app/index.js deleted file mode 100644 index ac50cd3fb99b6..0000000000000 --- a/x-pack/plugins/canvas/public/apps/workpad/workpad_app/index.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { connect } from 'react-redux'; -import { compose, branch, renderComponent } from 'recompose'; -import { selectToplevelNodes } from '../../../state/actions/transient'; -import { canUserWrite, getAppReady } from '../../../state/selectors/app'; -import { getWorkpad, isWriteable } from '../../../state/selectors/workpad'; -import { LoadWorkpad } from './load_workpad'; -import { WorkpadApp as Component } from './workpad_app'; -import { withElementsLoadedTelemetry } from './workpad_telemetry'; - -export { WORKPAD_CONTAINER_ID } from './workpad_app'; - -const mapStateToProps = (state) => { - const appReady = getAppReady(state); - - return { - isWriteable: isWriteable(state) && canUserWrite(state), - appReady: typeof appReady === 'object' ? appReady : { ready: appReady }, - workpad: getWorkpad(state), - }; -}; - -const mapDispatchToProps = (dispatch) => ({ - deselectElement(ev) { - ev && ev.stopPropagation(); - dispatch(selectToplevelNodes([])); - }, -}); - -const branches = [branch(({ workpad }) => workpad == null, renderComponent(LoadWorkpad))]; - -export const WorkpadApp = compose( - connect(mapStateToProps, mapDispatchToProps), - ...branches, - withElementsLoadedTelemetry -)(Component); diff --git a/x-pack/plugins/canvas/public/apps/workpad/workpad_app/index.ts b/x-pack/plugins/canvas/public/apps/workpad/workpad_app/index.ts new file mode 100644 index 0000000000000..a00bf855ba376 --- /dev/null +++ b/x-pack/plugins/canvas/public/apps/workpad/workpad_app/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { WorkpadApp } from './workpad_app'; +export { WorkpadApp as WorkpadAppComponent } from './workpad_app.component'; diff --git a/x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.component.tsx b/x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.component.tsx new file mode 100644 index 0000000000000..791f40f0219cd --- /dev/null +++ b/x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.component.tsx @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { FC, MouseEventHandler, useRef } from 'react'; +import PropTypes from 'prop-types'; +import { Sidebar } from '../../../components/sidebar'; +import { Toolbar } from '../../../components/toolbar'; +// @ts-expect-error Untyped local +import { Workpad } from '../../../components/workpad'; +import { WorkpadHeader } from '../../../components/workpad_header'; +import { CANVAS_LAYOUT_STAGE_CONTENT_SELECTOR } from '../../../../common/lib/constants'; +import { CommitFn } from '../../../../types'; + +export const WORKPAD_CONTAINER_ID = 'canvasWorkpadContainer'; + +interface Props { + deselectElement?: MouseEventHandler; + isWriteable: boolean; +} + +export const WorkpadApp: FC = ({ deselectElement, isWriteable }) => { + const interactivePageLayout = useRef(null); // future versions may enable editing on multiple pages => use array then + + const registerLayout = (newLayout: CommitFn) => { + if (interactivePageLayout.current !== newLayout) { + interactivePageLayout.current = newLayout; + } + }; + + const unregisterLayout = (oldLayout: CommitFn) => { + if (interactivePageLayout.current === oldLayout) { + interactivePageLayout.current = null; + } + }; + + const commit = interactivePageLayout.current || (() => {}); + + return ( +
+
+
+
+
+ +
+ +
+ {/* NOTE: canvasWorkpadContainer is used for exporting */} +
+ +
+
+
+ + {isWriteable && ( +
+ +
+ )} +
+ +
+ +
+
+
+ ); +}; + +WorkpadApp.propTypes = { + isWriteable: PropTypes.bool.isRequired, + deselectElement: PropTypes.func, +}; diff --git a/x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.js b/x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.js deleted file mode 100644 index fc3ac9922355a..0000000000000 --- a/x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.js +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import PropTypes from 'prop-types'; -import { Sidebar } from '../../../components/sidebar'; -import { Toolbar } from '../../../components/toolbar'; -import { Workpad } from '../../../components/workpad'; -import { WorkpadHeader } from '../../../components/workpad_header'; -import { CANVAS_LAYOUT_STAGE_CONTENT_SELECTOR } from '../../../../common/lib/constants'; - -export const WORKPAD_CONTAINER_ID = 'canvasWorkpadContainer'; - -export class WorkpadApp extends React.PureComponent { - static propTypes = { - isWriteable: PropTypes.bool.isRequired, - deselectElement: PropTypes.func, - }; - - interactivePageLayout = null; // future versions may enable editing on multiple pages => use array then - - registerLayout(newLayout) { - if (this.interactivePageLayout !== newLayout) { - this.interactivePageLayout = newLayout; - } - } - - unregisterLayout(oldLayout) { - if (this.interactivePageLayout === oldLayout) { - this.interactivePageLayout = null; - } - } - - render() { - const { isWriteable, deselectElement } = this.props; - - return ( -
-
-
-
-
- {})} /> -
- -
- {/* NOTE: canvasWorkpadContainer is used for exporting */} -
- -
-
-
- - {isWriteable && ( -
- -
- )} -
- -
- -
-
-
- ); - } -} diff --git a/x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.ts b/x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.ts new file mode 100644 index 0000000000000..46f2efaf5e7d2 --- /dev/null +++ b/x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { MouseEventHandler } from 'react'; +import { Dispatch } from 'redux'; +import { connect } from 'react-redux'; +// @ts-expect-error untyped local +import { selectToplevelNodes } from '../../../state/actions/transient'; +import { canUserWrite } from '../../../state/selectors/app'; +import { getWorkpad, isWriteable } from '../../../state/selectors/workpad'; +import { WorkpadApp as Component } from './workpad_app.component'; +import { withElementsLoadedTelemetry } from './workpad_telemetry'; +import { State } from '../../../../types'; + +export { WORKPAD_CONTAINER_ID } from './workpad_app.component'; + +const mapDispatchToProps = (dispatch: Dispatch): { deselectElement: MouseEventHandler } => ({ + deselectElement: (ev) => { + ev.stopPropagation(); + dispatch(selectToplevelNodes([])); + }, +}); + +export const WorkpadApp = connect( + (state: State) => ({ + isWriteable: isWriteable(state) && canUserWrite(state), + workpad: getWorkpad(state), + }), + mapDispatchToProps +)(withElementsLoadedTelemetry(Component)); diff --git a/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.component.tsx b/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.component.tsx index eb4b451896b46..b1e87ca67f5e5 100644 --- a/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.component.tsx +++ b/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.component.tsx @@ -18,22 +18,25 @@ import { EditMenu } from './edit_menu'; import { ElementMenu } from './element_menu'; import { ShareMenu } from './share_menu'; import { ViewMenu } from './view_menu'; +import { CommitFn } from '../../../types'; const { WorkpadHeader: strings } = ComponentStrings; export interface Props { isWriteable: boolean; - toggleWriteable: () => void; canUserWrite: boolean; - commit: (type: string, payload: any) => any; + commit: CommitFn; + onSetWriteable?: (writeable: boolean) => void; } export const WorkpadHeader: FunctionComponent = ({ isWriteable, canUserWrite, - toggleWriteable, commit, + onSetWriteable = () => {}, }) => { + const toggleWriteable = () => onSetWriteable(!isWriteable); + const keyHandler = (action: string) => { if (action === 'EDITING') { toggleWriteable(); @@ -145,6 +148,7 @@ export const WorkpadHeader: FunctionComponent = ({ WorkpadHeader.propTypes = { isWriteable: PropTypes.bool, - toggleWriteable: PropTypes.func, + commit: PropTypes.func.isRequired, + onSetWriteable: PropTypes.func, canUserWrite: PropTypes.bool, }; diff --git a/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.tsx b/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.tsx index 1f630040b0c36..0661aa4be4313 100644 --- a/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.tsx +++ b/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.tsx @@ -10,37 +10,16 @@ import { canUserWrite } from '../../state/selectors/app'; import { getSelectedPage, isWriteable } from '../../state/selectors/workpad'; import { setWriteable } from '../../state/actions/workpad'; import { State } from '../../../types'; -import { WorkpadHeader as Component, Props as ComponentProps } from './workpad_header.component'; +import { WorkpadHeader as Component } from './workpad_header.component'; -interface StateProps { - isWriteable: boolean; - canUserWrite: boolean; - selectedPage: string; -} - -interface DispatchProps { - setWriteable: (isWorkpadWriteable: boolean) => void; -} - -const mapStateToProps = (state: State): StateProps => ({ +const mapStateToProps = (state: State) => ({ isWriteable: isWriteable(state) && canUserWrite(state), canUserWrite: canUserWrite(state), selectedPage: getSelectedPage(state), }); const mapDispatchToProps = (dispatch: Dispatch) => ({ - setWriteable: (isWorkpadWriteable: boolean) => dispatch(setWriteable(isWorkpadWriteable)), -}); - -const mergeProps = ( - stateProps: StateProps, - dispatchProps: DispatchProps, - ownProps: ComponentProps -): ComponentProps => ({ - ...stateProps, - ...dispatchProps, - ...ownProps, - toggleWriteable: () => dispatchProps.setWriteable(!stateProps.isWriteable), + onSetWriteable: (isWorkpadWriteable: boolean) => dispatch(setWriteable(isWorkpadWriteable)), }); -export const WorkpadHeader = connect(mapStateToProps, mapDispatchToProps, mergeProps)(Component); +export const WorkpadHeader = connect(mapStateToProps, mapDispatchToProps)(Component); diff --git a/x-pack/plugins/canvas/types/canvas.ts b/x-pack/plugins/canvas/types/canvas.ts index cc07f498f1eec..6b3f9ad3e8043 100644 --- a/x-pack/plugins/canvas/types/canvas.ts +++ b/x-pack/plugins/canvas/types/canvas.ts @@ -76,3 +76,7 @@ export interface CanvasWorkpadBoundingBox { top: number; bottom: number; } + +export type LayoutState = any; + +export type CommitFn = (type: string, payload: any) => LayoutState; diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts index 927dc91f365b7..9662b9e17248b 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts @@ -51,7 +51,7 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { if (this.longRunningToast) return; this.longRunningToast = this.deps.toasts.addInfo( { - title: 'Your query is taking awhile', + title: 'Your query is taking a while', text: getLongQueryNotification({ cancel: this.cancelPending, runBeyondTimeout: this.runBeyondTimeout, diff --git a/x-pack/plugins/discover_enhanced/server/config.ts b/x-pack/plugins/discover_enhanced/server/config.ts index becbdee1bfe40..3e5e29e8c7de7 100644 --- a/x-pack/plugins/discover_enhanced/server/config.ts +++ b/x-pack/plugins/discover_enhanced/server/config.ts @@ -10,7 +10,7 @@ import { PluginConfigDescriptor } from '../../../../src/core/server'; export const configSchema = schema.object({ actions: schema.object({ exploreDataInChart: schema.object({ - enabled: schema.boolean({ defaultValue: true }), + enabled: schema.boolean({ defaultValue: false }), }), }), }); diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_context.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_context.mock.ts index fcfa1b0a21f13..b1d7341d51a4c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_context.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_context.mock.ts @@ -13,5 +13,6 @@ import { httpServiceMock } from 'src/core/public/mocks'; export const mockKibanaContext = { http: httpServiceMock.createSetupContract(), setBreadcrumbs: jest.fn(), + setDocTitle: jest.fn(), enterpriseSearchUrl: 'http://localhost:3002', }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/empty_states/empty_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/empty_states/empty_state.tsx index 9bb5cd3bffdf5..d6c38629d8143 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/empty_states/empty_state.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/empty_states/empty_state.tsx @@ -9,7 +9,7 @@ import { EuiPage, EuiPageBody, EuiPageContent, EuiEmptyPrompt, EuiButton } from import { FormattedMessage } from '@kbn/i18n/react'; import { sendTelemetry } from '../../../shared/telemetry'; -import { SetAppSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs'; +import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { KibanaContext, IKibanaContext } from '../../../index'; import { EngineOverviewHeader } from '../engine_overview_header'; @@ -33,7 +33,7 @@ export const EmptyState: React.FC = () => { return ( - + diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/empty_states/error_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/empty_states/error_state.tsx index 346e70d32f7b1..3753ad5433e8f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/empty_states/error_state.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/empty_states/error_state.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { EuiPage, EuiPageBody, EuiPageContent } from '@elastic/eui'; import { ErrorStatePrompt } from '../../../shared/error_state'; -import { SetAppSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs'; +import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { SendAppSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; import { EngineOverviewHeader } from '../engine_overview_header'; @@ -17,7 +17,7 @@ import './empty_states.scss'; export const ErrorState: React.FC = () => { return ( - + diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/empty_states/loading_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/empty_states/loading_state.tsx index 2be917c8df096..533dca7d0ab79 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/empty_states/loading_state.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/empty_states/loading_state.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { EuiPage, EuiPageBody, EuiPageContent, EuiSpacer, EuiLoadingContent } from '@elastic/eui'; -import { SetAppSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs'; +import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { EngineOverviewHeader } from '../engine_overview_header'; import './empty_states.scss'; @@ -15,7 +15,7 @@ import './empty_states.scss'; export const LoadingState: React.FC = () => { return ( - + diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.tsx index 13d092a657d11..286c32b2a443b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.tsx @@ -16,7 +16,7 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { SetAppSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs'; +import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { SendAppSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; import { LicenseContext, ILicenseContext, hasPlatinumLicense } from '../../../shared/licensing'; import { KibanaContext, IKibanaContext } from '../../../index'; @@ -93,7 +93,7 @@ export const EngineOverview: React.FC = () => { return ( - + diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/setup_guide/setup_guide.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/setup_guide/setup_guide.test.tsx index 82cc344d49632..5936b8f2d4283 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/setup_guide/setup_guide.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/setup_guide/setup_guide.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { SetAppSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs'; +import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { SetupGuide as SetupGuideLayout } from '../../../shared/setup_guide'; import { SetupGuide } from './'; @@ -16,6 +16,6 @@ describe('SetupGuide', () => { const wrapper = shallow(); expect(wrapper.find(SetupGuideLayout)).toHaveLength(1); - expect(wrapper.find(SetBreadcrumbs)).toHaveLength(1); + expect(wrapper.find(SetPageChrome)).toHaveLength(1); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/setup_guide/setup_guide.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/setup_guide/setup_guide.tsx index f899423319afc..fa55289e73e0b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/setup_guide/setup_guide.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/setup_guide/setup_guide.tsx @@ -11,7 +11,7 @@ import { i18n } from '@kbn/i18n'; import { APP_SEARCH_PLUGIN } from '../../../../../common/constants'; import { SetupGuide as SetupGuideLayout } from '../../../shared/setup_guide'; -import { SetAppSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs'; +import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { SendAppSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; import GettingStarted from '../../assets/getting_started.png'; @@ -22,7 +22,7 @@ export const SetupGuide: React.FC = () => ( standardAuthLink="https://swiftype.com/documentation/app-search/self-managed/security#standard" elasticsearchNativeAuthLink="https://swiftype.com/documentation/app-search/self-managed/security#elasticsearch-native-realm" > - diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_breadcrumbs/index.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_breadcrumbs/index.ts deleted file mode 100644 index c4ef68704b7e0..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_breadcrumbs/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export { - enterpriseSearchBreadcrumbs, - appSearchBreadcrumbs, - workplaceSearchBreadcrumbs, -} from './generate_breadcrumbs'; -export { SetAppSearchBreadcrumbs, SetWorkplaceSearchBreadcrumbs } from './set_breadcrumbs'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_breadcrumbs/set_breadcrumbs.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_breadcrumbs/set_breadcrumbs.test.tsx deleted file mode 100644 index 974ca54277c51..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_breadcrumbs/set_breadcrumbs.test.tsx +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; - -import '../../__mocks__/react_router_history.mock'; -import { mountWithKibanaContext } from '../../__mocks__'; - -jest.mock('./generate_breadcrumbs', () => ({ appSearchBreadcrumbs: jest.fn() })); -import { appSearchBreadcrumbs, SetAppSearchBreadcrumbs } from './'; - -describe('SetAppSearchBreadcrumbs', () => { - const setBreadcrumbs = jest.fn(); - const builtBreadcrumbs = [] as any; - const appSearchBreadCrumbsInnerCall = jest.fn().mockReturnValue(builtBreadcrumbs); - const appSearchBreadCrumbsOuterCall = jest.fn().mockReturnValue(appSearchBreadCrumbsInnerCall); - (appSearchBreadcrumbs as jest.Mock).mockImplementation(appSearchBreadCrumbsOuterCall); - - afterEach(() => { - jest.clearAllMocks(); - }); - - const mountSetAppSearchBreadcrumbs = (props: any) => { - return mountWithKibanaContext(, { - http: {}, - enterpriseSearchUrl: 'http://localhost:3002', - setBreadcrumbs, - }); - }; - - describe('when isRoot is false', () => { - const subject = () => mountSetAppSearchBreadcrumbs({ text: 'Page 1', isRoot: false }); - - it('calls appSearchBreadcrumbs to build breadcrumbs, then registers them with Kibana', () => { - subject(); - - // calls appSearchBreadcrumbs to build breadcrumbs with the target page and current location - expect(appSearchBreadCrumbsInnerCall).toHaveBeenCalledWith([ - { text: 'Page 1', path: '/current-path' }, - ]); - - // then registers them with Kibana - expect(setBreadcrumbs).toHaveBeenCalledWith(builtBreadcrumbs); - }); - }); - - describe('when isRoot is true', () => { - const subject = () => mountSetAppSearchBreadcrumbs({ text: 'Page 1', isRoot: true }); - - it('calls appSearchBreadcrumbs to build breadcrumbs with an empty breadcrumb, then registers them with Kibana', () => { - subject(); - - // uses an empty bredcrumb - expect(appSearchBreadCrumbsInnerCall).toHaveBeenCalledWith([]); - - // then registers them with Kibana - expect(setBreadcrumbs).toHaveBeenCalledWith(builtBreadcrumbs); - }); - }); -}); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_breadcrumbs/generate_breadcrumbs.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.test.ts similarity index 97% rename from x-pack/plugins/enterprise_search/public/applications/shared/kibana_breadcrumbs/generate_breadcrumbs.test.ts rename to x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.test.ts index 70aa723d62601..0f34bbb6b65bc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_breadcrumbs/generate_breadcrumbs.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.test.ts @@ -4,8 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { generateBreadcrumb } from './generate_breadcrumbs'; -import { appSearchBreadcrumbs, enterpriseSearchBreadcrumbs, workplaceSearchBreadcrumbs } from './'; +import { + generateBreadcrumb, + appSearchBreadcrumbs, + enterpriseSearchBreadcrumbs, + workplaceSearchBreadcrumbs, +} from './generate_breadcrumbs'; import { mockHistory as mockHistoryUntyped } from '../../__mocks__'; const mockHistory = mockHistoryUntyped as any; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_breadcrumbs/generate_breadcrumbs.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/shared/kibana_breadcrumbs/generate_breadcrumbs.ts rename to x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_title.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_title.test.ts new file mode 100644 index 0000000000000..0c1c18b98e33e --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_title.test.ts @@ -0,0 +1,60 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + generateTitle, + enterpriseSearchTitle, + appSearchTitle, + workplaceSearchTitle, +} from './generate_title'; + +describe('generateTitle', () => { + it('creates a hyphen separated string from an array of page titles', () => { + const title = generateTitle(['Curations', 'some Engine', 'App Search']); + expect(title).toEqual('Curations - some Engine - App Search'); + }); +}); + +describe('enterpriseSearchTitle', () => { + it('automatically appends the Enterprise Search product onto the pages array', () => { + const title = enterpriseSearchTitle(['Setup Guide']); + expect(title).toEqual('Setup Guide - Enterprise Search'); + }); + + it('can be mixed and matched', () => { + const title = enterpriseSearchTitle([appSearchTitle(['Some Page'])]); + expect(title).toEqual('Some Page - App Search - Enterprise Search'); + }); + + it('falls back to product name', () => { + const title = enterpriseSearchTitle(); + expect(title).toEqual('Enterprise Search'); + }); +}); + +describe('appSearchTitle', () => { + it('automatically appends the App Search product onto the pages array', () => { + const title = appSearchTitle(['Engines']); + expect(title).toEqual('Engines - App Search'); + }); + + it('falls back to product name', () => { + const title = appSearchTitle(); + expect(title).toEqual('App Search'); + }); +}); + +describe('workplaceSearchTitle', () => { + it('automatically appends the Workplace Search product onto the pages array', () => { + const title = workplaceSearchTitle(['Sources']); + expect(title).toEqual('Sources - Workplace Search'); + }); + + it('falls back to product name', () => { + const title = workplaceSearchTitle(); + expect(title).toEqual('Workplace Search'); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_title.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_title.ts new file mode 100644 index 0000000000000..706baefc00cc2 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_title.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + ENTERPRISE_SEARCH_PLUGIN, + APP_SEARCH_PLUGIN, + WORKPLACE_SEARCH_PLUGIN, +} from '../../../../common/constants'; + +/** + * Generate a document title that generally follows our breadcrumb trails + * https://github.com/elastic/kibana/blob/master/docs/development/core/public/kibana-plugin-core-public.chromedoctitle.md + */ + +export type TTitle = string[]; + +/** + * Given an array of page titles, return a final formatted document title + * @param pages - e.g., ['Curations', 'some Engine', 'App Search'] + * @returns - e.g., 'Curations | some Engine | App Search' + */ +export const generateTitle = (pages: TTitle) => pages.join(' - '); + +/** + * Product-specific helpers + */ + +export const enterpriseSearchTitle = (page: TTitle = []) => + generateTitle([...page, ENTERPRISE_SEARCH_PLUGIN.NAME]); + +export const appSearchTitle = (page: TTitle = []) => + generateTitle([...page, APP_SEARCH_PLUGIN.NAME]); + +export const workplaceSearchTitle = (page: TTitle = []) => + generateTitle([...page, WORKPLACE_SEARCH_PLUGIN.NAME]); diff --git a/x-pack/plugins/canvas/public/apps/workpad/workpad_app/load_workpad.js b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/index.ts similarity index 72% rename from x-pack/plugins/canvas/public/apps/workpad/workpad_app/load_workpad.js rename to x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/index.ts index 388bf00723f82..4468d11ba94c9 100644 --- a/x-pack/plugins/canvas/public/apps/workpad/workpad_app/load_workpad.js +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/index.ts @@ -4,6 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; - -export const LoadWorkpad = () =>
Load a workpad...
; +export { SetAppSearchChrome, SetWorkplaceSearchChrome } from './set_chrome'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.test.tsx new file mode 100644 index 0000000000000..aba0b250e56c0 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.test.tsx @@ -0,0 +1,84 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; + +import '../../__mocks__/react_router_history.mock'; +import { mockKibanaContext, mountWithKibanaContext } from '../../__mocks__'; + +jest.mock('./generate_breadcrumbs', () => ({ + appSearchBreadcrumbs: jest.fn(() => (crumbs: any) => crumbs), + workplaceSearchBreadcrumbs: jest.fn(() => (crumbs: any) => crumbs), +})); +import { appSearchBreadcrumbs, workplaceSearchBreadcrumbs } from './generate_breadcrumbs'; + +jest.mock('./generate_title', () => ({ + appSearchTitle: jest.fn((title: any) => title), + workplaceSearchTitle: jest.fn((title: any) => title), +})); +import { appSearchTitle, workplaceSearchTitle } from './generate_title'; + +import { SetAppSearchChrome, SetWorkplaceSearchChrome } from './'; + +describe('SetAppSearchChrome', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + afterEach(() => { + expect(appSearchBreadcrumbs).toHaveBeenCalled(); + expect(appSearchTitle).toHaveBeenCalled(); + }); + + it('sets breadcrumbs and document title', () => { + mountWithKibanaContext(); + + expect(mockKibanaContext.setBreadcrumbs).toHaveBeenCalledWith([ + { + text: 'Engines', + path: '/current-path', + }, + ]); + expect(mockKibanaContext.setDocTitle).toHaveBeenCalledWith(['Engines']); + }); + + it('sets empty breadcrumbs and document title when isRoot is true', () => { + mountWithKibanaContext(); + + expect(mockKibanaContext.setBreadcrumbs).toHaveBeenCalledWith([]); + expect(mockKibanaContext.setDocTitle).toHaveBeenCalledWith([]); + }); +}); + +describe('SetWorkplaceSearchChrome', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + afterEach(() => { + expect(workplaceSearchBreadcrumbs).toHaveBeenCalled(); + expect(workplaceSearchTitle).toHaveBeenCalled(); + }); + + it('sets breadcrumbs and document title', () => { + mountWithKibanaContext(); + + expect(mockKibanaContext.setBreadcrumbs).toHaveBeenCalledWith([ + { + text: 'Sources', + path: '/current-path', + }, + ]); + expect(mockKibanaContext.setDocTitle).toHaveBeenCalledWith(['Sources']); + }); + + it('sets empty breadcrumbs and document title when isRoot is true', () => { + mountWithKibanaContext(); + + expect(mockKibanaContext.setBreadcrumbs).toHaveBeenCalledWith([]); + expect(mockKibanaContext.setDocTitle).toHaveBeenCalledWith([]); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_breadcrumbs/set_breadcrumbs.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.tsx similarity index 66% rename from x-pack/plugins/enterprise_search/public/applications/shared/kibana_breadcrumbs/set_breadcrumbs.tsx rename to x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.tsx index e54f1a12b73cb..59e83a2cb13c2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_breadcrumbs/set_breadcrumbs.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.tsx @@ -13,9 +13,10 @@ import { workplaceSearchBreadcrumbs, TBreadcrumbs, } from './generate_breadcrumbs'; +import { appSearchTitle, workplaceSearchTitle, TTitle } from './generate_title'; /** - * Small on-mount helper for setting Kibana's chrome breadcrumbs on any App Search view + * Helpers for setting Kibana chrome (breadcrumbs, doc titles) on React view mount * @see https://github.com/elastic/kibana/blob/master/src/core/public/chrome/chrome_service.tsx */ @@ -31,27 +32,31 @@ interface IRootBreadcrumbsProps { } type TBreadcrumbsProps = IBreadcrumbsProps | IRootBreadcrumbsProps; -export const SetAppSearchBreadcrumbs: React.FC = ({ text, isRoot }) => { +export const SetAppSearchChrome: React.FC = ({ text, isRoot }) => { const history = useHistory(); - const { setBreadcrumbs } = useContext(KibanaContext) as IKibanaContext; + const { setBreadcrumbs, setDocTitle } = useContext(KibanaContext) as IKibanaContext; const crumb = isRoot ? [] : [{ text, path: history.location.pathname }]; + const title = isRoot ? [] : [text]; useEffect(() => { setBreadcrumbs(appSearchBreadcrumbs(history)(crumb as TBreadcrumbs | [])); + setDocTitle(appSearchTitle(title as TTitle | [])); }, []); return null; }; -export const SetWorkplaceSearchBreadcrumbs: React.FC = ({ text, isRoot }) => { +export const SetWorkplaceSearchChrome: React.FC = ({ text, isRoot }) => { const history = useHistory(); - const { setBreadcrumbs } = useContext(KibanaContext) as IKibanaContext; + const { setBreadcrumbs, setDocTitle } = useContext(KibanaContext) as IKibanaContext; const crumb = isRoot ? [] : [{ text, path: history.location.pathname }]; + const title = isRoot ? [] : [text]; useEffect(() => { setBreadcrumbs(workplaceSearchBreadcrumbs(history)(crumb as TBreadcrumbs | [])); + setDocTitle(workplaceSearchTitle(title as TTitle | [])); }, []); return null; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/error_state/error_state.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/error_state/error_state.tsx index a1bc17e05dc05..e1114986d2244 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/error_state/error_state.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/error_state/error_state.tsx @@ -9,14 +9,14 @@ import { EuiPage, EuiPageBody, EuiPageContent } from '@elastic/eui'; import { WORKPLACE_SEARCH_PLUGIN } from '../../../../../common/constants'; import { ErrorStatePrompt } from '../../../shared/error_state'; -import { SetWorkplaceSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs'; +import { SetWorkplaceSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { SendWorkplaceSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; import { ViewContentHeader } from '../shared/view_content_header'; export const ErrorState: React.FC = () => { return ( - + diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/overview/overview.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/overview/overview.tsx index b75a2841dad9b..2c3e78b404d42 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/overview/overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/overview/overview.tsx @@ -9,7 +9,7 @@ import { EuiPage, EuiPageBody, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useActions, useValues } from 'kea'; -import { SetWorkplaceSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs'; +import { SetWorkplaceSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { SendWorkplaceSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; import { KibanaContext, IKibanaContext } from '../../../index'; @@ -72,7 +72,7 @@ export const Overview: React.FC = () => { return ( - + diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/setup_guide/setup_guide.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/setup_guide/setup_guide.test.tsx index b87c35d5a5942..73cf4b419f944 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/setup_guide/setup_guide.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/setup_guide/setup_guide.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { SetWorkplaceSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs'; +import { SetWorkplaceSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { SetupGuide as SetupGuideLayout } from '../../../shared/setup_guide'; import { SetupGuide } from './'; @@ -16,6 +16,6 @@ describe('SetupGuide', () => { const wrapper = shallow(); expect(wrapper.find(SetupGuideLayout)).toHaveLength(1); - expect(wrapper.find(SetBreadcrumbs)).toHaveLength(1); + expect(wrapper.find(SetPageChrome)).toHaveLength(1); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/setup_guide/setup_guide.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/setup_guide/setup_guide.tsx index e96d114c67c5d..f9b00bdf29642 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/setup_guide/setup_guide.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/setup_guide/setup_guide.tsx @@ -11,7 +11,7 @@ import { i18n } from '@kbn/i18n'; import { WORKPLACE_SEARCH_PLUGIN } from '../../../../../common/constants'; import { SetupGuide as SetupGuideLayout } from '../../../shared/setup_guide'; -import { SetWorkplaceSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs'; +import { SetWorkplaceSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { SendWorkplaceSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; import GettingStarted from '../../assets/getting_started.png'; @@ -26,7 +26,7 @@ export const SetupGuide: React.FC = () => { standardAuthLink="https://www.elastic.co/guide/en/workplace-search/current/workplace-search-security.html#standard" elasticsearchNativeAuthLink="https://www.elastic.co/guide/en/workplace-search/current/workplace-search-security.html#elasticsearch-native-realm" > - { const [coreStart] = await core.getStartServices(); + const { chrome } = coreStart; + chrome.docTitle.change(APP_SEARCH_PLUGIN.NAME); await this.setPublicUrl(config, coreStart.http); @@ -68,6 +70,8 @@ export class EnterpriseSearchPlugin implements Plugin { category: DEFAULT_APP_CATEGORIES.enterpriseSearch, mount: async (params: AppMountParameters) => { const [coreStart] = await core.getStartServices(); + const { chrome } = coreStart; + chrome.docTitle.change(WORKPLACE_SEARCH_PLUGIN.NAME); const { renderApp } = await import('./applications'); const { WorkplaceSearch } = await import('./applications/workplace_search'); diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.js b/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.js index 943f663a025d8..4fe3d5c66696e 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.js +++ b/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.js @@ -5,16 +5,23 @@ */ import React from 'react'; +import { act } from 'react-dom/test-utils'; import moment from 'moment-timezone'; import { Provider } from 'react-redux'; // axios has a $http like interface so using it to simulate $http import axios from 'axios'; import axiosXhrAdapter from 'axios/lib/adapters/xhr'; -import sinon from 'sinon'; import { findTestSubject } from '@elastic/eui/lib/test'; +import { init as initHttpRequests } from './helpers/http_requests'; +import { + notificationServiceMock, + fatalErrorsServiceMock, +} from '../../../../../src/core/public/mocks'; +import { usageCollectionPluginMock } from '../../../../../src/plugins/usage_collection/public/mocks'; + import { mountWithIntl } from '../../../../test_utils/enzyme_helpers'; -import { fetchedPolicies, fetchedNodes } from '../../public/application/store/actions'; +import { fetchedPolicies } from '../../public/application/store/actions'; import { indexLifecycleManagementStore } from '../../public/application/store'; import { EditPolicy } from '../../public/application/sections/edit_policy'; import { init as initHttp } from '../../public/application/services/http'; @@ -33,15 +40,17 @@ import { policyNameMustBeDifferentErrorMessage, policyNameAlreadyUsedErrorMessage, maximumDocumentsRequiredMessage, -} from '../../public/application/store/selectors/lifecycle'; +} from '../../public/application/store/selectors'; -initHttp(axios.create({ adapter: axiosXhrAdapter }), (path) => path); -initUiMetric({ reportUiStats: () => {} }); -initNotification({ - addDanger: () => {}, -}); +initHttp(axios.create({ adapter: axiosXhrAdapter })); +initUiMetric(usageCollectionPluginMock.createSetupContract()); +initNotification( + notificationServiceMock.createSetupContract().toasts, + fatalErrorsServiceMock.createSetupContract() +); let server; +let httpRequestsMockHelpers; let store; const policy = { phases: { @@ -70,9 +79,11 @@ for (let i = 0; i < 105; i++) { window.scrollTo = jest.fn(); window.TextEncoder = null; let component; -const activatePhase = (rendered, phase) => { +const activatePhase = async (rendered, phase) => { const testSubject = `enablePhaseSwitch-${phase}`; - findTestSubject(rendered, testSubject).simulate('click'); + await act(async () => { + await findTestSubject(rendered, testSubject).simulate('click'); + }); rendered.update(); }; const expectedErrorMessages = (rendered, expectedErrorMessages) => { @@ -120,16 +131,13 @@ describe('edit policy', () => { store = indexLifecycleManagementStore(); component = ( - {}} /> + {} }} getUrlForApp={() => {}} /> ); store.dispatch(fetchedPolicies(policies)); - server = sinon.fakeServer.create(); - server.respondWith('/api/index_lifecycle_management/policies', [ - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify(policies), - ]); + ({ server, httpRequestsMockHelpers } = initHttpRequests()); + + httpRequestsMockHelpers.setPoliciesResponse(policies); }); describe('top level form', () => { test('should show error when trying to save empty form', () => { @@ -242,48 +250,56 @@ describe('edit policy', () => { }); }); describe('warm phase', () => { - test('should show number required error when trying to save empty warm phase', () => { + beforeEach(() => { + server.respondImmediately = true; + httpRequestsMockHelpers.setNodesListResponse({}); + httpRequestsMockHelpers.setNodesDetailsResponse('attribute:true', [ + { nodeId: 'testNodeId', stats: { name: 'testNodeName', host: 'testHost' } }, + ]); + }); + + test('should show number required error when trying to save empty warm phase', async () => { const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'warm'); + await activatePhase(rendered, 'warm'); setPhaseAfter(rendered, 'warm', ''); save(rendered); expectedErrorMessages(rendered, [numberRequiredMessage]); }); - test('should allow 0 for phase timing', () => { + test('should allow 0 for phase timing', async () => { const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'warm'); + await activatePhase(rendered, 'warm'); setPhaseAfter(rendered, 'warm', 0); save(rendered); expectedErrorMessages(rendered, []); }); - test('should show positive number required error when trying to save warm phase with -1 for after', () => { + test('should show positive number required error when trying to save warm phase with -1 for after', async () => { const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'warm'); + await activatePhase(rendered, 'warm'); setPhaseAfter(rendered, 'warm', -1); save(rendered); expectedErrorMessages(rendered, [positiveNumberRequiredMessage]); }); - test('should show positive number required error when trying to save warm phase with -1 for index priority', () => { + test('should show positive number required error when trying to save warm phase with -1 for index priority', async () => { const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'warm'); + await activatePhase(rendered, 'warm'); setPhaseAfter(rendered, 'warm', 1); setPhaseIndexPriority(rendered, 'warm', -1); save(rendered); expectedErrorMessages(rendered, [positiveNumberRequiredMessage]); }); - test('should show positive number required above zero error when trying to save warm phase with 0 for shrink', () => { + test('should show positive number required above zero error when trying to save warm phase with 0 for shrink', async () => { const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'warm'); + await activatePhase(rendered, 'warm'); findTestSubject(rendered, 'shrinkSwitch').simulate('click'); rendered.update(); setPhaseAfter(rendered, 'warm', 1); @@ -293,11 +309,11 @@ describe('edit policy', () => { save(rendered); expectedErrorMessages(rendered, [positiveNumbersAboveZeroErrorMessage]); }); - test('should show positive number above 0 required error when trying to save warm phase with -1 for shrink', () => { + test('should show positive number above 0 required error when trying to save warm phase with -1 for shrink', async () => { const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'warm'); + await activatePhase(rendered, 'warm'); setPhaseAfter(rendered, 'warm', 1); findTestSubject(rendered, 'shrinkSwitch').simulate('click'); rendered.update(); @@ -307,11 +323,11 @@ describe('edit policy', () => { save(rendered); expectedErrorMessages(rendered, [positiveNumbersAboveZeroErrorMessage]); }); - test('should show positive number required above zero error when trying to save warm phase with 0 for force merge', () => { + test('should show positive number required above zero error when trying to save warm phase with 0 for force merge', async () => { const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'warm'); + await activatePhase(rendered, 'warm'); setPhaseAfter(rendered, 'warm', 1); findTestSubject(rendered, 'forceMergeSwitch').simulate('click'); rendered.update(); @@ -321,11 +337,11 @@ describe('edit policy', () => { save(rendered); expectedErrorMessages(rendered, [positiveNumbersAboveZeroErrorMessage]); }); - test('should show positive number above 0 required error when trying to save warm phase with -1 for force merge', () => { + test('should show positive number above 0 required error when trying to save warm phase with -1 for force merge', async () => { const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'warm'); + await activatePhase(rendered, 'warm'); setPhaseAfter(rendered, 'warm', 1); findTestSubject(rendered, 'forceMergeSwitch').simulate('click'); rendered.update(); @@ -335,43 +351,43 @@ describe('edit policy', () => { save(rendered); expectedErrorMessages(rendered, [positiveNumbersAboveZeroErrorMessage]); }); - test('should show spinner for node attributes input when loading', () => { + test('should show spinner for node attributes input when loading', async () => { + server.respondImmediately = false; const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'warm'); + await activatePhase(rendered, 'warm'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeTruthy(); expect(rendered.find('.euiCallOut--warning').exists()).toBeFalsy(); expect(getNodeAttributeSelect(rendered, 'warm').exists()).toBeFalsy(); }); - test('should show warning instead of node attributes input when none exist', () => { - store.dispatch(fetchedNodes({})); + test('should show warning instead of node attributes input when none exist', async () => { const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'warm'); + await activatePhase(rendered, 'warm'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); expect(rendered.find('.euiCallOut--warning').exists()).toBeTruthy(); expect(getNodeAttributeSelect(rendered, 'warm').exists()).toBeFalsy(); }); - test('should show node attributes input when attributes exist', () => { - store.dispatch(fetchedNodes({ 'attribute:true': ['node1'] })); + test('should show node attributes input when attributes exist', async () => { + httpRequestsMockHelpers.setNodesListResponse({ 'attribute:true': ['node1'] }); const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'warm'); + await activatePhase(rendered, 'warm'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); expect(rendered.find('.euiCallOut--warning').exists()).toBeFalsy(); const nodeAttributesSelect = getNodeAttributeSelect(rendered, 'warm'); expect(nodeAttributesSelect.exists()).toBeTruthy(); expect(nodeAttributesSelect.find('option').length).toBe(2); }); - test('should show view node attributes link when attribute selected and show flyout when clicked', () => { - store.dispatch(fetchedNodes({ 'attribute:true': ['node1'] })); + test('should show view node attributes link when attribute selected and show flyout when clicked', async () => { + httpRequestsMockHelpers.setNodesListResponse({ 'attribute:true': ['node1'] }); const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'warm'); + await activatePhase(rendered, 'warm'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); expect(rendered.find('.euiCallOut--warning').exists()).toBeFalsy(); const nodeAttributesSelect = getNodeAttributeSelect(rendered, 'warm'); @@ -382,67 +398,76 @@ describe('edit policy', () => { rendered.update(); const flyoutButton = findTestSubject(rendered, 'warm-viewNodeDetailsFlyoutButton'); expect(flyoutButton.exists()).toBeTruthy(); - flyoutButton.simulate('click'); + await act(async () => { + await flyoutButton.simulate('click'); + }); rendered.update(); expect(rendered.find('.euiFlyout').exists()).toBeTruthy(); }); }); describe('cold phase', () => { - test('should allow 0 for phase timing', () => { + beforeEach(() => { + server.respondImmediately = true; + httpRequestsMockHelpers.setNodesListResponse({}); + httpRequestsMockHelpers.setNodesDetailsResponse('attribute:true', [ + { nodeId: 'testNodeId', stats: { name: 'testNodeName', host: 'testHost' } }, + ]); + }); + test('should allow 0 for phase timing', async () => { const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'cold'); + await activatePhase(rendered, 'cold'); setPhaseAfter(rendered, 'cold', 0); save(rendered); expectedErrorMessages(rendered, []); }); - test('should show positive number required error when trying to save cold phase with -1 for after', () => { + test('should show positive number required error when trying to save cold phase with -1 for after', async () => { const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'cold'); + await activatePhase(rendered, 'cold'); setPhaseAfter(rendered, 'cold', -1); save(rendered); expectedErrorMessages(rendered, [positiveNumberRequiredMessage]); }); - test('should show spinner for node attributes input when loading', () => { + test('should show spinner for node attributes input when loading', async () => { + server.respondImmediately = false; const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'cold'); + await activatePhase(rendered, 'cold'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeTruthy(); expect(rendered.find('.euiCallOut--warning').exists()).toBeFalsy(); expect(getNodeAttributeSelect(rendered, 'cold').exists()).toBeFalsy(); }); - test('should show warning instead of node attributes input when none exist', () => { - store.dispatch(fetchedNodes({})); + test('should show warning instead of node attributes input when none exist', async () => { const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'cold'); + await activatePhase(rendered, 'cold'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); expect(rendered.find('.euiCallOut--warning').exists()).toBeTruthy(); expect(getNodeAttributeSelect(rendered, 'cold').exists()).toBeFalsy(); }); - test('should show node attributes input when attributes exist', () => { - store.dispatch(fetchedNodes({ 'attribute:true': ['node1'] })); + test('should show node attributes input when attributes exist', async () => { + httpRequestsMockHelpers.setNodesListResponse({ 'attribute:true': ['node1'] }); const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'cold'); + await activatePhase(rendered, 'cold'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); expect(rendered.find('.euiCallOut--warning').exists()).toBeFalsy(); const nodeAttributesSelect = getNodeAttributeSelect(rendered, 'cold'); expect(nodeAttributesSelect.exists()).toBeTruthy(); expect(nodeAttributesSelect.find('option').length).toBe(2); }); - test('should show view node attributes link when attribute selected and show flyout when clicked', () => { - store.dispatch(fetchedNodes({ 'attribute:true': ['node1'] })); + test('should show view node attributes link when attribute selected and show flyout when clicked', async () => { + httpRequestsMockHelpers.setNodesListResponse({ 'attribute:true': ['node1'] }); const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'cold'); + await activatePhase(rendered, 'cold'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); expect(rendered.find('.euiCallOut--warning').exists()).toBeFalsy(); const nodeAttributesSelect = getNodeAttributeSelect(rendered, 'cold'); @@ -453,15 +478,17 @@ describe('edit policy', () => { rendered.update(); const flyoutButton = findTestSubject(rendered, 'cold-viewNodeDetailsFlyoutButton'); expect(flyoutButton.exists()).toBeTruthy(); - flyoutButton.simulate('click'); + await act(async () => { + await flyoutButton.simulate('click'); + }); rendered.update(); expect(rendered.find('.euiFlyout').exists()).toBeTruthy(); }); - test('should show positive number required error when trying to save with -1 for index priority', () => { + test('should show positive number required error when trying to save with -1 for index priority', async () => { const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'cold'); + await activatePhase(rendered, 'cold'); setPhaseAfter(rendered, 'cold', 1); setPhaseIndexPriority(rendered, 'cold', -1); save(rendered); @@ -469,20 +496,20 @@ describe('edit policy', () => { }); }); describe('delete phase', () => { - test('should allow 0 for phase timing', () => { + test('should allow 0 for phase timing', async () => { const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'delete'); + await activatePhase(rendered, 'delete'); setPhaseAfter(rendered, 'delete', 0); save(rendered); expectedErrorMessages(rendered, []); }); - test('should show positive number required error when trying to save delete phase with -1 for after', () => { + test('should show positive number required error when trying to save delete phase with -1 for after', async () => { const rendered = mountWithIntl(component); noRollover(rendered); setPolicyName(rendered, 'mypolicy'); - activatePhase(rendered, 'delete'); + await activatePhase(rendered, 'delete'); setPhaseAfter(rendered, 'delete', -1); save(rendered); expectedErrorMessages(rendered, [positiveNumberRequiredMessage]); diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/components/helpers/http_requests.ts b/x-pack/plugins/index_lifecycle_management/__jest__/components/helpers/http_requests.ts new file mode 100644 index 0000000000000..668cbedbf0c95 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/__jest__/components/helpers/http_requests.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import sinon, { SinonFakeServer } from 'sinon'; + +type HttpResponse = Record | any[]; + +const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { + const setPoliciesResponse = (response: HttpResponse = []) => { + server.respondWith('/api/index_lifecycle_management/policies', [ + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify(response), + ]); + }; + + const setNodesListResponse = (response: HttpResponse = []) => { + server.respondWith('/api/index_lifecycle_management/nodes/list', [ + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify(response), + ]); + }; + + const setNodesDetailsResponse = (nodeAttributes: string, response: HttpResponse = []) => { + server.respondWith(`/api/index_lifecycle_management/nodes/${nodeAttributes}/details`, [ + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify(response), + ]); + }; + + return { + setPoliciesResponse, + setNodesListResponse, + setNodesDetailsResponse, + }; +}; + +export const init = () => { + const server = sinon.fakeServer.create(); + + // Define default response for unhandled requests. + // We make requests to APIs which don't impact the component under test, e.g. UI metric telemetry, + // and we can mock them all with a 200 instead of mocking each one individually. + server.respondWith([200, {}, 'DefaultSinonMockServerResponse']); + + const httpRequestsMockHelpers = registerHttpRequestMockHelpers(server); + + return { + server, + httpRequestsMockHelpers, + }; +}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/components/learn_more_link.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/components/learn_more_link.js deleted file mode 100644 index 2284b9e39835c..0000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/components/learn_more_link.js +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { EuiLink } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; - -import { createDocLink } from '../../services/documentation'; - -export class LearnMoreLink extends React.PureComponent { - render() { - const { href, docPath, text } = this.props; - let url; - if (docPath) { - url = createDocLink(docPath); - } else { - url = href; - } - const content = text ? ( - text - ) : ( - - ); - return ( - - {content} - - ); - } -} diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/components/learn_more_link.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/components/learn_more_link.tsx new file mode 100644 index 0000000000000..623ff982438d7 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/components/learn_more_link.tsx @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { ReactNode } from 'react'; +import { EuiLink } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { createDocLink } from '../../services/documentation'; + +interface Props { + docPath: string; + text?: ReactNode; +} + +export const LearnMoreLink: React.FunctionComponent = ({ docPath, text }) => { + const content = text ? ( + text + ) : ( + + ); + return ( + + {content} + + ); +}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/cold_phase/cold_phase.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/cold_phase/cold_phase.js index d5c0744e5eb07..200bf0e767d9d 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/cold_phase/cold_phase.js +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/cold_phase/cold_phase.js @@ -34,7 +34,6 @@ import { SetPriorityInput } from '../set_priority_input'; export class ColdPhase extends PureComponent { static propTypes = { setPhaseData: PropTypes.func.isRequired, - showNodeDetailsFlyout: PropTypes.func.isRequired, isShowingErrors: PropTypes.bool.isRequired, errors: PropTypes.object.isRequired, @@ -42,7 +41,6 @@ export class ColdPhase extends PureComponent { render() { const { setPhaseData, - showNodeDetailsFlyout, phaseData, errors, isShowingErrors, @@ -114,7 +112,6 @@ export class ColdPhase extends PureComponent { ({ - nodeOptions: getNodeOptions(state), - }), - { - fetchNodes, - } -)(PresentationComponent); diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_allocation/node_allocation.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_allocation/node_allocation.js deleted file mode 100644 index 95c1878776688..0000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_allocation/node_allocation.js +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { Component, Fragment } from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { i18n } from '@kbn/i18n'; -import { EuiSelect, EuiButtonEmpty, EuiCallOut, EuiSpacer, EuiLoadingSpinner } from '@elastic/eui'; - -import { PHASE_NODE_ATTRS } from '../../../../constants'; -import { LearnMoreLink } from '../../../components/learn_more_link'; -import { ErrableFormRow } from '../../form_errors'; - -const learnMoreLinks = ( - - - - - } - docPath="shards-allocation.html" - /> - -); - -export class NodeAllocation extends Component { - componentDidMount() { - this.props.fetchNodes(); - } - - render() { - const { - phase, - setPhaseData, - isShowingErrors, - phaseData, - showNodeDetailsFlyout, - nodeOptions, - errors, - } = this.props; - if (!nodeOptions) { - return ( - - - - - ); - } - if (!nodeOptions.length) { - return ( - - - } - color="warning" - > - - {learnMoreLinks} - - - - - ); - } - - return ( - - - { - setPhaseData(PHASE_NODE_ATTRS, e.target.value); - }} - /> - - {!!phaseData[PHASE_NODE_ATTRS] ? ( - showNodeDetailsFlyout(phaseData[PHASE_NODE_ATTRS])} - > - - - ) : ( -
- )} - {learnMoreLinks} - - - ); - } -} diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_allocation/node_allocation.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_allocation/node_allocation.tsx new file mode 100644 index 0000000000000..31261de45c743 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_allocation/node_allocation.tsx @@ -0,0 +1,187 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Fragment, useState } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { + EuiSelect, + EuiButtonEmpty, + EuiCallOut, + EuiSpacer, + EuiLoadingSpinner, + EuiButton, +} from '@elastic/eui'; + +import { PHASE_NODE_ATTRS } from '../../../../constants'; +import { LearnMoreLink } from '../../../components/learn_more_link'; +import { ErrableFormRow } from '../../form_errors'; +import { useLoadNodes } from '../../../../services/api'; +import { NodeAttrsDetails } from '../node_attrs_details'; + +interface Props { + phase: string; + setPhaseData: (dataKey: string, value: any) => void; + errors: any; + phaseData: any; + isShowingErrors: boolean; +} + +const learnMoreLink = ( + + + + } + docPath="modules-cluster.html#cluster-shard-allocation-settings" + /> + +); + +export const NodeAllocation: React.FunctionComponent = ({ + phase, + setPhaseData, + errors, + phaseData, + isShowingErrors, +}) => { + const { isLoading, data: nodes, error, sendRequest } = useLoadNodes(); + + const [selectedNodeAttrsForDetails, setSelectedNodeAttrsForDetails] = useState( + null + ); + + if (isLoading) { + return ( + + + + + ); + } + + if (error) { + const { statusCode, message } = error; + return ( + + + } + color="danger" + > +

+ {message} ({statusCode}) +

+ + + +
+ + +
+ ); + } + + let nodeOptions = Object.keys(nodes).map((attrs) => ({ + text: `${attrs} (${nodes[attrs].length})`, + value: attrs, + })); + + nodeOptions.sort((a, b) => a.value.localeCompare(b.value)); + if (nodeOptions.length) { + nodeOptions = [ + { + text: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.defaultNodeAllocation', { + defaultMessage: "Default allocation (don't use attributes)", + }), + value: '', + }, + ...nodeOptions, + ]; + } + if (!nodeOptions.length) { + return ( + + + } + color="warning" + > + + {learnMoreLink} + + + + + ); + } + + return ( + + + { + setPhaseData(PHASE_NODE_ATTRS, e.target.value); + }} + /> + + {!!phaseData[PHASE_NODE_ATTRS] ? ( + setSelectedNodeAttrsForDetails(phaseData[PHASE_NODE_ATTRS])} + > + + + ) : null} + {learnMoreLink} + + + {selectedNodeAttrsForDetails ? ( + setSelectedNodeAttrsForDetails(null)} + /> + ) : null} + + ); +}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/index.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/index.ts similarity index 78% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/index.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/index.ts index 885e965c46c4b..056d2f2f600f3 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/index.js +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { NodeAttrsDetails } from './node_attrs_details.container'; +export { NodeAttrsDetails } from './node_attrs_details'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.container.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.container.js deleted file mode 100644 index ca7c310723b62..0000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.container.js +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { connect } from 'react-redux'; - -import { getNodeDetails } from '../../../../store/selectors'; -import { fetchNodeDetails } from '../../../../store/actions'; -import { NodeAttrsDetails as PresentationComponent } from './node_attrs_details'; - -export const NodeAttrsDetails = connect( - (state, ownProps) => ({ - details: getNodeDetails(state, ownProps.selectedNodeAttrs), - }), - { fetchNodeDetails } -)(PresentationComponent); diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.js deleted file mode 100644 index 67bc8f0386abf..0000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.js +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; - -import { - EuiFlyoutBody, - EuiFlyout, - EuiTitle, - EuiInMemoryTable, - EuiSpacer, - EuiPortal, -} from '@elastic/eui'; - -export class NodeAttrsDetails extends PureComponent { - static propTypes = { - fetchNodeDetails: PropTypes.func.isRequired, - close: PropTypes.func.isRequired, - - details: PropTypes.array, - selectedNodeAttrs: PropTypes.string.isRequired, - }; - - UNSAFE_componentWillMount() { - this.props.fetchNodeDetails(this.props.selectedNodeAttrs); - } - - render() { - const { selectedNodeAttrs, details, close } = this.props; - - return ( - - - - -

- -

-
- - -
-
-
- ); - } -} diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.tsx new file mode 100644 index 0000000000000..6fcbd94dc5e9a --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.tsx @@ -0,0 +1,106 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { + EuiFlyoutBody, + EuiFlyout, + EuiTitle, + EuiInMemoryTable, + EuiSpacer, + EuiPortal, + EuiLoadingContent, + EuiCallOut, + EuiButton, +} from '@elastic/eui'; + +import { useLoadNodeDetails } from '../../../../services/api'; + +interface Props { + close: () => void; + selectedNodeAttrs: string; +} + +export const NodeAttrsDetails: React.FunctionComponent = ({ close, selectedNodeAttrs }) => { + const { data, isLoading, error, sendRequest } = useLoadNodeDetails(selectedNodeAttrs); + let content; + if (isLoading) { + content = ; + } else if (error) { + const { statusCode, message } = error; + content = ( + + } + color="danger" + > +

+ {message} ({statusCode}) +

+ + + +
+ ); + } else { + content = ( + + ); + } + return ( + + + + +

+ +

+
+ + {content} +
+
+
+ ); +}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/warm_phase/warm_phase.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/warm_phase/warm_phase.js index 55aec88c8bcab..60b5ab4781b6d 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/warm_phase/warm_phase.js +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/warm_phase/warm_phase.js @@ -38,7 +38,6 @@ import { MinAgeInput } from '../min_age_input'; export class WarmPhase extends PureComponent { static propTypes = { setPhaseData: PropTypes.func.isRequired, - showNodeDetailsFlyout: PropTypes.func.isRequired, isShowingErrors: PropTypes.bool.isRequired, errors: PropTypes.object.isRequired, @@ -47,7 +46,6 @@ export class WarmPhase extends PureComponent { render() { const { setPhaseData, - showNodeDetailsFlyout, phaseData, errors, isShowingErrors, @@ -152,7 +150,6 @@ export class WarmPhase extends PureComponent { { - this.setState({ isShowingNodeDetailsFlyout: true, selectedNodeAttrsForDetails }); - }; - togglePolicyJsonFlyout = () => { this.setState(({ isShowingPolicyJsonFlyout }) => ({ isShowingPolicyJsonFlyout: !isShowingPolicyJsonFlyout, @@ -291,7 +284,6 @@ export class EditPolicy extends Component { @@ -299,7 +291,6 @@ export class EditPolicy extends Component { @@ -370,13 +361,6 @@ export class EditPolicy extends Component { - {this.state.isShowingNodeDetailsFlyout ? ( - this.setState({ isShowingNodeDetailsFlyout: false })} - /> - ) : null} - {this.state.isShowingPolicyJsonFlyout ? ( { +type Props = EuiFormRowProps & { + errorKey: string; + isShowingErrors: boolean; + errors: Record; +}; + +export const ErrableFormRow: React.FunctionComponent = ({ + errorKey, + isShowingErrors, + errors, + children, + ...rest +}) => { return ( 0} @@ -16,7 +28,7 @@ export const ErrableFormRow = ({ errorKey, isShowingErrors, errors, children, .. > {Children.map(children, (child) => - cloneElement(child, { + cloneElement(child as ReactElement, { isInvalid: isShowingErrors && errors[errorKey].length > 0, }) )} diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/api.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/api.ts index 30c341baa6194..61de37bbfad11 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/api.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/api.ts @@ -21,13 +21,20 @@ interface GenericObject { [key: string]: any; } -export async function loadNodes() { - return await sendGet(`nodes/list`); -} +export const useLoadNodes = () => { + return useRequest({ + path: `nodes/list`, + method: 'get', + initialData: [], + }); +}; -export async function loadNodeDetails(selectedNodeAttrs: string) { - return await sendGet(`nodes/${selectedNodeAttrs}/details`); -} +export const useLoadNodeDetails = (selectedNodeAttrs: string) => { + return useRequest({ + path: `nodes/${selectedNodeAttrs}/details`, + method: 'get', + }); +}; export async function loadIndexTemplates() { return await sendGet(`templates`); diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/http.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/http.ts index 0b5f39a52c13f..fb1a651b5f550 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/http.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/http.ts @@ -8,7 +8,6 @@ import { HttpSetup } from 'src/core/public'; import { UseRequestConfig, useRequest as _useRequest, - Error, } from '../../../../../../src/plugins/es_ui_shared/public'; interface GenericObject { @@ -43,6 +42,8 @@ export function sendDelete(path: string) { return _httpClient.delete(getFullPath(path)); } -export const useRequest = (config: UseRequestConfig) => { - return _useRequest(_httpClient, { ...config, path: getFullPath(config.path) }); +export const useRequest = ( + config: UseRequestConfig +) => { + return _useRequest(_httpClient, { ...config, path: getFullPath(config.path) }); }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/store/actions/nodes.js b/x-pack/plugins/index_lifecycle_management/public/application/store/actions/nodes.js index f2520abc7a441..3f1c00db621a7 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/store/actions/nodes.js +++ b/x-pack/plugins/index_lifecycle_management/public/application/store/actions/nodes.js @@ -3,51 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { i18n } from '@kbn/i18n'; import { createAction } from 'redux-actions'; -import { showApiError } from '../../services/api_errors'; -import { loadNodes, loadNodeDetails } from '../../services/api'; import { SET_SELECTED_NODE_ATTRS } from '../../constants'; export const setSelectedNodeAttrs = createAction(SET_SELECTED_NODE_ATTRS); export const setSelectedPrimaryShardCount = createAction('SET_SELECTED_PRIMARY_SHARED_COUNT'); export const setSelectedReplicaCount = createAction('SET_SELECTED_REPLICA_COUNT'); -export const fetchedNodes = createAction('FETCHED_NODES'); -let fetchingNodes = false; -export const fetchNodes = () => async (dispatch) => { - try { - if (!fetchingNodes) { - fetchingNodes = true; - const nodes = await loadNodes(); - dispatch(fetchedNodes(nodes)); - } - } catch (err) { - const title = i18n.translate('xpack.indexLifecycleMgmt.editPolicy.nodeInfoErrorMessage', { - defaultMessage: 'Error loading node attribute information', - }); - showApiError(err, title); - } finally { - fetchingNodes = false; - } -}; - -export const fetchedNodeDetails = createAction( - 'FETCHED_NODE_DETAILS', - (selectedNodeAttrs, details) => ({ - selectedNodeAttrs, - details, - }) -); -export const fetchNodeDetails = (selectedNodeAttrs) => async (dispatch) => { - let details; - try { - details = await loadNodeDetails(selectedNodeAttrs); - } catch (err) { - const title = i18n.translate('xpack.indexLifecycleMgmt.editPolicy.nodeDetailErrorMessage', { - defaultMessage: 'Error loading node attribute details', - }); - showApiError(err, title); - return false; - } - dispatch(fetchedNodeDetails(selectedNodeAttrs, details)); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/store/reducers/nodes.js b/x-pack/plugins/index_lifecycle_management/public/application/store/reducers/nodes.js index 443b257b6fb7e..383e61b5aacde 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/store/reducers/nodes.js +++ b/x-pack/plugins/index_lifecycle_management/public/application/store/reducers/nodes.js @@ -5,13 +5,7 @@ */ import { handleActions } from 'redux-actions'; -import { - fetchedNodes, - setSelectedNodeAttrs, - setSelectedPrimaryShardCount, - setSelectedReplicaCount, - fetchedNodeDetails, -} from '../actions/nodes'; +import { setSelectedPrimaryShardCount, setSelectedReplicaCount } from '../actions'; const defaultState = { isLoading: false, @@ -24,29 +18,6 @@ const defaultState = { export const nodes = handleActions( { - [fetchedNodes](state, { payload: nodes }) { - return { - ...state, - isLoading: false, - nodes, - }; - }, - [fetchedNodeDetails](state, { payload }) { - const { selectedNodeAttrs, details } = payload; - return { - ...state, - details: { - ...state.details, - [selectedNodeAttrs]: details, - }, - }; - }, - [setSelectedNodeAttrs](state, { payload: selectedNodeAttrs }) { - return { - ...state, - selectedNodeAttrs, - }; - }, [setSelectedPrimaryShardCount](state, { payload }) { let selectedPrimaryShardCount = parseInt(payload); if (isNaN(selectedPrimaryShardCount)) { diff --git a/x-pack/plugins/index_lifecycle_management/public/application/store/selectors/nodes.js b/x-pack/plugins/index_lifecycle_management/public/application/store/selectors/nodes.js index 63d849217f59e..72bfd4b15a78a 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/store/selectors/nodes.js +++ b/x-pack/plugins/index_lifecycle_management/public/application/store/selectors/nodes.js @@ -4,43 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { createSelector } from 'reselect'; - export const getNodes = (state) => state.nodes.nodes; -export const getNodeOptions = createSelector([(state) => getNodes(state)], (nodes) => { - if (!nodes) { - return null; - } - - const options = Object.keys(nodes).map((attrs) => ({ - text: `${attrs} (${nodes[attrs].length})`, - value: attrs, - })); - - options.sort((a, b) => a.value.localeCompare(b.value)); - if (options.length) { - return [{ text: "Default allocation (don't use attributes)", value: '' }, ...options]; - } else { - return options; - } -}); - export const getSelectedPrimaryShardCount = (state) => state.nodes.selectedPrimaryShardCount; export const getSelectedReplicaCount = (state) => state.nodes.selectedReplicaCount !== undefined ? state.nodes.selectedReplicaCount : 1; - -export const getSelectedNodeAttrs = (state) => state.nodes.selectedNodeAttrs; - -export const getNodesFromSelectedNodeAttrs = (state) => { - const nodes = getNodes(state)[getSelectedNodeAttrs(state)]; - if (nodes) { - return nodes.length; - } - return null; -}; - -export const getNodeDetails = (state, selectedNodeAttrs) => { - return state.nodes.details[selectedNodeAttrs]; -}; diff --git a/x-pack/plugins/infra/public/alerting/common/components/alert_preview.tsx b/x-pack/plugins/infra/public/alerting/common/components/alert_preview.tsx index 9d28ef71a5518..877d047c941d4 100644 --- a/x-pack/plugins/infra/public/alerting/common/components/alert_preview.tsx +++ b/x-pack/plugins/infra/public/alerting/common/components/alert_preview.tsx @@ -186,9 +186,22 @@ export const AlertPreview: React.FC = (props) => { {showNoDataResults && previewResult.resultTotals.noData ? ( {previewResult.resultTotals.noData}, + boldedResultsNumber: ( + + {i18n.translate( + 'xpack.infra.metrics.alertFlyout.alertPreviewNoDataResultNumber', + { + defaultMessage: + '{noData, plural, one {was # result} other {were # results}}', + values: { + noData: previewResult.resultTotals.noData, + }, + } + )} + + ), }} /> ) : null}{' '} diff --git a/x-pack/plugins/infra/public/apps/common_providers.tsx b/x-pack/plugins/infra/public/apps/common_providers.tsx index 9e4917856d8b2..fc82f4bf6cb00 100644 --- a/x-pack/plugins/infra/public/apps/common_providers.tsx +++ b/x-pack/plugins/infra/public/apps/common_providers.tsx @@ -4,19 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; -import { CoreStart } from 'kibana/public'; import { ApolloClient } from 'apollo-client'; -import { - useUiSetting$, - KibanaContextProvider, -} from '../../../../../src/plugins/kibana_react/public'; -import { TriggersActionsProvider } from '../utils/triggers_actions_context'; -import { InfraClientStartDeps } from '../types'; +import { CoreStart } from 'kibana/public'; +import React, { useMemo } from 'react'; +import { useUiSetting$ } from '../../../../../src/plugins/kibana_react/public'; +import { EuiThemeProvider } from '../../../observability/public'; import { TriggersAndActionsUIPublicPluginStart } from '../../../triggers_actions_ui/public'; +import { createKibanaContextForPlugin } from '../hooks/use_kibana'; +import { InfraClientStartDeps } from '../types'; import { ApolloClientContext } from '../utils/apollo_context'; -import { EuiThemeProvider } from '../../../observability/public'; import { NavigationWarningPromptProvider } from '../utils/navigation_warning_prompt'; +import { TriggersActionsProvider } from '../utils/triggers_actions_context'; export const CommonInfraProviders: React.FC<{ apolloClient: ApolloClient<{}>; @@ -39,9 +37,14 @@ export const CoreProviders: React.FC<{ core: CoreStart; plugins: InfraClientStartDeps; }> = ({ children, core, plugins }) => { + const { Provider: KibanaContextProviderForPlugin } = useMemo( + () => createKibanaContextForPlugin(core, plugins), + [core, plugins] + ); + return ( - + {children} - + ); }; diff --git a/x-pack/plugins/infra/public/components/loading_page.tsx b/x-pack/plugins/infra/public/components/loading_page.tsx index 9d37fed45b583..c410f37e7bf6b 100644 --- a/x-pack/plugins/infra/public/components/loading_page.tsx +++ b/x-pack/plugins/infra/public/components/loading_page.tsx @@ -11,12 +11,12 @@ import { EuiPageBody, EuiPageContent, } from '@elastic/eui'; -import React from 'react'; +import React, { ReactNode } from 'react'; import { FlexPage } from './page'; interface LoadingPageProps { - message?: string | JSX.Element; + message?: ReactNode; } export const LoadingPage = ({ message }: LoadingPageProps) => ( diff --git a/x-pack/plugins/infra/public/hooks/use_kibana.ts b/x-pack/plugins/infra/public/hooks/use_kibana.ts new file mode 100644 index 0000000000000..24511014d1a06 --- /dev/null +++ b/x-pack/plugins/infra/public/hooks/use_kibana.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { CoreStart } from '../../../../../src/core/public'; +import { + createKibanaReactContext, + KibanaReactContextValue, + useKibana, +} from '../../../../../src/plugins/kibana_react/public'; +import { InfraClientStartDeps } from '../types'; + +export type PluginKibanaContextValue = CoreStart & InfraClientStartDeps; + +export const createKibanaContextForPlugin = (core: CoreStart, pluginsStart: InfraClientStartDeps) => + createKibanaReactContext({ + ...core, + ...pluginsStart, + }); + +export const useKibanaContextForPlugin = useKibana as () => KibanaReactContextValue< + PluginKibanaContextValue +>; diff --git a/x-pack/plugins/infra/public/hooks/use_kibana_space.ts b/x-pack/plugins/infra/public/hooks/use_kibana_space.ts new file mode 100644 index 0000000000000..1c06263008961 --- /dev/null +++ b/x-pack/plugins/infra/public/hooks/use_kibana_space.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useAsync } from 'react-use'; +import { useKibanaContextForPlugin } from '../hooks/use_kibana'; +import type { Space } from '../../../spaces/public'; + +export type ActiveSpace = + | { isLoading: true; error: undefined; space: undefined } + | { isLoading: false; error: Error; space: undefined } + | { isLoading: false; error: undefined; space: Space }; + +export const useActiveKibanaSpace = (): ActiveSpace => { + const kibana = useKibanaContextForPlugin(); + + const asyncActiveSpace = useAsync(kibana.services.spaces.getActiveSpace); + + if (asyncActiveSpace.loading) { + return { + isLoading: true, + error: undefined, + space: undefined, + }; + } else if (asyncActiveSpace.error) { + return { + isLoading: false, + error: asyncActiveSpace.error, + space: undefined, + }; + } else { + return { + isLoading: false, + error: undefined, + space: asyncActiveSpace.value!, + }; + } +}; diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/page_providers.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/page_providers.tsx index 48ad156714ccf..723d833799e29 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/page_providers.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/page_providers.tsx @@ -7,18 +7,25 @@ import React from 'react'; import { LogEntryCategoriesModuleProvider } from '../../../containers/logs/log_analysis/modules/log_entry_categories'; import { useLogSourceContext } from '../../../containers/logs/log_source'; -import { useKibanaSpaceId } from '../../../utils/use_kibana_space_id'; +import { useActiveKibanaSpace } from '../../../hooks/use_kibana_space'; export const LogEntryCategoriesPageProviders: React.FunctionComponent = ({ children }) => { - const { sourceId, sourceConfiguration } = useLogSourceContext(); - const spaceId = useKibanaSpaceId(); + const { sourceConfiguration, sourceId } = useLogSourceContext(); + const { space } = useActiveKibanaSpace(); + + // This is a rather crude way of guarding the dependent providers against + // arguments that are only made available asynchronously. Ideally, we'd use + // React concurrent mode and Suspense in order to handle that more gracefully. + if (sourceConfiguration?.configuration.logAlias == null || space == null) { + return null; + } return ( {children} diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/page_providers.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/page_providers.tsx index ac11260d2075d..e986fa37c2b2c 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/page_providers.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/page_providers.tsx @@ -9,23 +9,30 @@ import { LogAnalysisSetupFlyoutStateProvider } from '../../../components/logging import { LogEntryCategoriesModuleProvider } from '../../../containers/logs/log_analysis/modules/log_entry_categories'; import { LogEntryRateModuleProvider } from '../../../containers/logs/log_analysis/modules/log_entry_rate'; import { useLogSourceContext } from '../../../containers/logs/log_source'; -import { useKibanaSpaceId } from '../../../utils/use_kibana_space_id'; +import { useActiveKibanaSpace } from '../../../hooks/use_kibana_space'; export const LogEntryRatePageProviders: React.FunctionComponent = ({ children }) => { const { sourceId, sourceConfiguration } = useLogSourceContext(); - const spaceId = useKibanaSpaceId(); + const { space } = useActiveKibanaSpace(); + + // This is a rather crude way of guarding the dependent providers against + // arguments that are only made available asynchronously. Ideally, we'd use + // React concurrent mode and Suspense in order to handle that more gracefully. + if (sourceConfiguration?.configuration.logAlias == null || space == null) { + return null; + } return ( {children} diff --git a/x-pack/plugins/infra/public/types.ts b/x-pack/plugins/infra/public/types.ts index 357f07265ac6e..a1494a023201f 100644 --- a/x-pack/plugins/infra/public/types.ts +++ b/x-pack/plugins/infra/public/types.ts @@ -4,16 +4,20 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CoreSetup, CoreStart, Plugin as PluginClass } from 'kibana/public'; -import { DataPublicPluginStart } from '../../../../src/plugins/data/public'; -import { HomePublicPluginSetup } from '../../../../src/plugins/home/public'; -import { +import type { CoreSetup, CoreStart, Plugin as PluginClass } from 'kibana/public'; +import type { DataPublicPluginStart } from '../../../../src/plugins/data/public'; +import type { HomePublicPluginSetup } from '../../../../src/plugins/home/public'; +import type { UsageCollectionSetup, UsageCollectionStart, } from '../../../../src/plugins/usage_collection/public'; -import { TriggersAndActionsUIPublicPluginSetup } from '../../../plugins/triggers_actions_ui/public'; -import { DataEnhancedSetup, DataEnhancedStart } from '../../data_enhanced/public'; -import { ObservabilityPluginSetup, ObservabilityPluginStart } from '../../observability/public'; +import type { TriggersAndActionsUIPublicPluginSetup } from '../../../plugins/triggers_actions_ui/public'; +import type { DataEnhancedSetup, DataEnhancedStart } from '../../data_enhanced/public'; +import type { + ObservabilityPluginSetup, + ObservabilityPluginStart, +} from '../../observability/public'; +import type { SpacesPluginStart } from '../../spaces/public'; // Our own setup and start contract values export type InfraClientSetupExports = void; @@ -31,6 +35,7 @@ export interface InfraClientStartDeps { data: DataPublicPluginStart; dataEnhanced: DataEnhancedStart; observability: ObservabilityPluginStart; + spaces: SpacesPluginStart; triggers_actions_ui: TriggersAndActionsUIPublicPluginSetup; usageCollection: UsageCollectionStart; } diff --git a/x-pack/plugins/infra/public/utils/use_kibana_space_id.ts b/x-pack/plugins/infra/public/utils/use_kibana_space_id.ts deleted file mode 100644 index 86597f52928d5..0000000000000 --- a/x-pack/plugins/infra/public/utils/use_kibana_space_id.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { fold } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; -import * as rt from 'io-ts'; -import { useKibana } from '../../../../../src/plugins/kibana_react/public'; - -export const useKibanaSpaceId = (): string => { - const kibana = useKibana(); - // NOTE: The injectedMetadata service will be deprecated at some point. We should migrate - // this to the client side Spaces plugin when it becomes available. - const activeSpace = kibana.services.injectedMetadata?.getInjectedVar('activeSpace'); - - return pipe( - activeSpaceRT.decode(activeSpace), - fold( - () => 'default', - (decodedActiveSpace) => decodedActiveSpace.space.id - ) - ); -}; - -const activeSpaceRT = rt.type({ - space: rt.type({ - id: rt.string, - }), -}); diff --git a/x-pack/plugins/ingest_manager/common/services/config_to_yaml.ts b/x-pack/plugins/ingest_manager/common/services/config_to_yaml.ts index 1fb6fead454ef..e2e6393738d1f 100644 --- a/x-pack/plugins/ingest_manager/common/services/config_to_yaml.ts +++ b/x-pack/plugins/ingest_manager/common/services/config_to_yaml.ts @@ -10,6 +10,7 @@ const CONFIG_KEYS_ORDER = [ 'id', 'name', 'revision', + 'dataset', 'type', 'outputs', 'agent', diff --git a/x-pack/plugins/ingest_manager/common/services/package_configs_to_agent_inputs.test.ts b/x-pack/plugins/ingest_manager/common/services/package_configs_to_agent_inputs.test.ts index a4d87f54b0915..d6c09f058ab85 100644 --- a/x-pack/plugins/ingest_manager/common/services/package_configs_to_agent_inputs.test.ts +++ b/x-pack/plugins/ingest_manager/common/services/package_configs_to_agent_inputs.test.ts @@ -39,7 +39,7 @@ describe('Ingest Manager - storedPackageConfigsToAgentInputs', () => { { id: 'test-logs-foo', enabled: true, - dataset: { name: 'foo', type: 'logs' }, + data_stream: { dataset: 'foo', type: 'logs' }, vars: { fooVar: { value: 'foo-value' }, fooVar2: { value: [1, 2] }, @@ -52,7 +52,7 @@ describe('Ingest Manager - storedPackageConfigsToAgentInputs', () => { { id: 'test-logs-bar', enabled: true, - dataset: { name: 'bar', type: 'logs' }, + data_stream: { dataset: 'bar', type: 'logs' }, vars: { barVar: { value: 'bar-value' }, barVar2: { value: [1, 2] }, @@ -118,7 +118,7 @@ describe('Ingest Manager - storedPackageConfigsToAgentInputs', () => { id: 'some-uuid', name: 'mock-package-config', type: 'test-logs', - dataset: { namespace: 'default' }, + data_stream: { namespace: 'default' }, use_output: 'default', meta: { package: { @@ -129,13 +129,13 @@ describe('Ingest Manager - storedPackageConfigsToAgentInputs', () => { streams: [ { id: 'test-logs-foo', - dataset: { name: 'foo', type: 'logs' }, + data_stream: { dataset: 'foo', type: 'logs' }, fooKey: 'fooValue1', fooKey2: ['fooValue2'], }, { id: 'test-logs-bar', - dataset: { name: 'bar', type: 'logs' }, + data_stream: { dataset: 'bar', type: 'logs' }, }, ], }, @@ -160,12 +160,12 @@ describe('Ingest Manager - storedPackageConfigsToAgentInputs', () => { id: 'some-uuid', name: 'mock-package-config', type: 'test-logs', - dataset: { namespace: 'default' }, + data_stream: { namespace: 'default' }, use_output: 'default', streams: [ { id: 'test-logs-foo', - dataset: { name: 'foo', type: 'logs' }, + data_stream: { dataset: 'foo', type: 'logs' }, fooKey: 'fooValue1', fooKey2: ['fooValue2'], }, diff --git a/x-pack/plugins/ingest_manager/common/services/package_configs_to_agent_inputs.ts b/x-pack/plugins/ingest_manager/common/services/package_configs_to_agent_inputs.ts index 64ba6b8a52b57..b94fc39e0567c 100644 --- a/x-pack/plugins/ingest_manager/common/services/package_configs_to_agent_inputs.ts +++ b/x-pack/plugins/ingest_manager/common/services/package_configs_to_agent_inputs.ts @@ -24,7 +24,7 @@ export const storedPackageConfigsToAgentInputs = ( id: packageConfig.id || packageConfig.name, name: packageConfig.name, type: input.type, - dataset: { + data_stream: { namespace: packageConfig.namespace || 'default', }, use_output: DEFAULT_OUTPUT.name, @@ -37,7 +37,7 @@ export const storedPackageConfigsToAgentInputs = ( .map((stream) => { const fullStream: FullAgentConfigInputStream = { id: stream.id, - dataset: stream.dataset, + data_stream: stream.data_stream, ...stream.compiled_stream, ...Object.entries(stream.config || {}).reduce((acc, [key, { value }]) => { acc[key] = value; diff --git a/x-pack/plugins/ingest_manager/common/services/package_to_config.test.ts b/x-pack/plugins/ingest_manager/common/services/package_to_config.test.ts index e0cd32df1535e..1f4cd43247be1 100644 --- a/x-pack/plugins/ingest_manager/common/services/package_to_config.test.ts +++ b/x-pack/plugins/ingest_manager/common/services/package_to_config.test.ts @@ -83,14 +83,16 @@ describe('Ingest Manager - packageToConfig', () => { { type: 'foo', enabled: true, - streams: [{ id: 'foo-foo', enabled: true, dataset: { name: 'foo', type: 'logs' } }], + streams: [ + { id: 'foo-foo', enabled: true, data_stream: { dataset: 'foo', type: 'logs' } }, + ], }, { type: 'bar', enabled: true, streams: [ - { id: 'bar-bar', enabled: true, dataset: { name: 'bar', type: 'logs' } }, - { id: 'bar-bar2', enabled: true, dataset: { name: 'bar2', type: 'logs' } }, + { id: 'bar-bar', enabled: true, data_stream: { dataset: 'bar', type: 'logs' } }, + { id: 'bar-bar2', enabled: true, data_stream: { dataset: 'bar2', type: 'logs' } }, ], }, ]); @@ -141,7 +143,7 @@ describe('Ingest Manager - packageToConfig', () => { { id: 'foo-foo', enabled: true, - dataset: { name: 'foo', type: 'logs' }, + data_stream: { dataset: 'foo', type: 'logs' }, vars: { 'var-name': { value: 'foo-var-value' } }, }, ], @@ -153,13 +155,13 @@ describe('Ingest Manager - packageToConfig', () => { { id: 'bar-bar', enabled: true, - dataset: { name: 'bar', type: 'logs' }, + data_stream: { dataset: 'bar', type: 'logs' }, vars: { 'var-name': { type: 'text', value: 'bar-var-value' } }, }, { id: 'bar-bar2', enabled: true, - dataset: { name: 'bar2', type: 'logs' }, + data_stream: { dataset: 'bar2', type: 'logs' }, vars: { 'var-name': { type: 'yaml', value: 'bar2-var-value' } }, }, ], @@ -257,7 +259,7 @@ describe('Ingest Manager - packageToConfig', () => { { id: 'foo-foo', enabled: true, - dataset: { name: 'foo', type: 'logs' }, + data_stream: { dataset: 'foo', type: 'logs' }, vars: { 'var-name': { value: 'foo-var-value' }, }, @@ -275,7 +277,7 @@ describe('Ingest Manager - packageToConfig', () => { { id: 'bar-bar', enabled: true, - dataset: { name: 'bar', type: 'logs' }, + data_stream: { dataset: 'bar', type: 'logs' }, vars: { 'var-name': { value: 'bar-var-value' }, }, @@ -283,7 +285,7 @@ describe('Ingest Manager - packageToConfig', () => { { id: 'bar-bar2', enabled: true, - dataset: { name: 'bar2', type: 'logs' }, + data_stream: { dataset: 'bar2', type: 'logs' }, vars: { 'var-name': { value: 'bar2-var-value' }, }, @@ -297,7 +299,7 @@ describe('Ingest Manager - packageToConfig', () => { { id: 'with-disabled-streams-disabled', enabled: false, - dataset: { name: 'disabled', type: 'logs' }, + data_stream: { dataset: 'disabled', type: 'logs' }, vars: { 'var-name': { value: [] }, }, @@ -305,7 +307,7 @@ describe('Ingest Manager - packageToConfig', () => { { id: 'with-disabled-streams-disabled2', enabled: false, - dataset: { name: 'disabled2', type: 'logs' }, + data_stream: { dataset: 'disabled2', type: 'logs' }, }, ], }, diff --git a/x-pack/plugins/ingest_manager/common/services/package_to_config.ts b/x-pack/plugins/ingest_manager/common/services/package_to_config.ts index 5957267c7304c..184b44cb9e530 100644 --- a/x-pack/plugins/ingest_manager/common/services/package_to_config.ts +++ b/x-pack/plugins/ingest_manager/common/services/package_to_config.ts @@ -19,17 +19,17 @@ import { const getStreamsForInputType = ( inputType: string, packageInfo: PackageInfo -): Array => { - const streams: Array = []; +): Array => { + const streams: Array = []; (packageInfo.datasets || []).forEach((dataset) => { (dataset.streams || []).forEach((stream) => { if (stream.input === inputType) { streams.push({ ...stream, - dataset: { + data_stream: { type: dataset.type, - name: dataset.name, + dataset: dataset.name, }, }); } @@ -76,12 +76,9 @@ export const packageToPackageConfigInputs = (packageInfo: PackageInfo): PackageC packageInfo ).map((packageStream) => { const stream: PackageConfigInputStream = { - id: `${packageInput.type}-${packageStream.dataset.name}`, + id: `${packageInput.type}-${packageStream.data_stream.dataset}`, enabled: packageStream.enabled === false ? false : true, - dataset: { - name: packageStream.dataset.name, - type: packageStream.dataset.type, - }, + data_stream: packageStream.data_stream, }; if (packageStream.vars && packageStream.vars.length) { stream.vars = packageStream.vars.reduce(varsReducer, {}); diff --git a/x-pack/plugins/ingest_manager/common/types/models/agent_config.ts b/x-pack/plugins/ingest_manager/common/types/models/agent_config.ts index 00ba51fc1843a..cdaea1cc5f9a4 100644 --- a/x-pack/plugins/ingest_manager/common/types/models/agent_config.ts +++ b/x-pack/plugins/ingest_manager/common/types/models/agent_config.ts @@ -32,8 +32,8 @@ export type AgentConfigSOAttributes = Omit; export interface FullAgentConfigInputStream { id: string; - dataset: { - name: string; + data_stream: { + dataset: string; type: string; }; [key: string]: any; @@ -43,7 +43,7 @@ export interface FullAgentConfigInput { id: string; name: string; type: string; - dataset: { namespace: string }; + data_stream: { namespace: string }; use_output: string; meta?: { package?: Pick; diff --git a/x-pack/plugins/ingest_manager/common/types/models/package_config.ts b/x-pack/plugins/ingest_manager/common/types/models/package_config.ts index 0ff56e6d05d37..635afbd47850e 100644 --- a/x-pack/plugins/ingest_manager/common/types/models/package_config.ts +++ b/x-pack/plugins/ingest_manager/common/types/models/package_config.ts @@ -20,8 +20,8 @@ export type PackageConfigConfigRecord = Record, + packageInputStreams: Array, packageConfigInput: PackageConfigInput ): boolean => { return ( @@ -52,7 +52,7 @@ const shouldShowStreamsByDefault = ( hasInvalidButRequiredVar( stream.vars, packageConfigInput.streams.find( - (pkgStream) => stream.dataset.name === pkgStream.dataset.name + (pkgStream) => stream.data_stream.dataset === pkgStream.data_stream.dataset )?.vars ) ) @@ -62,7 +62,7 @@ const shouldShowStreamsByDefault = ( export const PackageConfigInputPanel: React.FunctionComponent<{ packageInput: RegistryInput; - packageInputStreams: Array; + packageInputStreams: Array; packageConfigInput: PackageConfigInput; updatePackageConfigInput: (updatedInput: Partial) => void; inputValidationResults: PackageConfigInputValidationResults; @@ -90,7 +90,7 @@ export const PackageConfigInputPanel: React.FunctionComponent<{ return { packageInputStream, packageConfigInputStream: packageConfigInput.streams.find( - (stream) => stream.dataset.name === packageInputStream.dataset.name + (stream) => stream.data_stream.dataset === packageInputStream.data_stream.dataset ), }; }) @@ -201,7 +201,8 @@ export const PackageConfigInputPanel: React.FunctionComponent<{ updatedStream: Partial ) => { const indexOfUpdatedStream = packageConfigInput.streams.findIndex( - (stream) => stream.dataset.name === packageInputStream.dataset.name + (stream) => + stream.data_stream.dataset === packageInputStream.data_stream.dataset ); const newStreams = [...packageConfigInput.streams]; newStreams[indexOfUpdatedStream] = { diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/services/validate_package_config.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/services/validate_package_config.ts index bd9d216ca969a..0514ad574a8cd 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/services/validate_package_config.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/services/validate_package_config.ts @@ -134,7 +134,7 @@ export const validatePackageConfig = ( if (stream.vars) { const streamVarsByName = ( ( - registryStreamsByDataset[stream.dataset.name].find( + registryStreamsByDataset[stream.data_stream.dataset].find( (registryStream) => registryStream.input === input.type ) || {} ).vars || [] diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/services/validate_package_config.ts.test.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/services/validate_package_config.ts.test.ts index 41d46f03dca23..47874525b8a5a 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/services/validate_package_config.ts.test.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/services/validate_package_config.ts.test.ts @@ -159,7 +159,7 @@ describe('Ingest Manager - validatePackageConfig()', () => { streams: [ { id: 'foo-foo', - dataset: { name: 'foo', type: 'logs' }, + data_stream: { dataset: 'foo', type: 'logs' }, enabled: true, vars: { 'var-name': { value: 'test_yaml: value', type: 'yaml' } }, }, @@ -175,13 +175,13 @@ describe('Ingest Manager - validatePackageConfig()', () => { streams: [ { id: 'bar-bar', - dataset: { name: 'bar', type: 'logs' }, + data_stream: { dataset: 'bar', type: 'logs' }, enabled: true, vars: { 'var-name': { value: 'test_yaml: value', type: 'yaml' } }, }, { id: 'bar-bar2', - dataset: { name: 'bar2', type: 'logs' }, + data_stream: { dataset: 'bar2', type: 'logs' }, enabled: true, vars: { 'var-name': { value: undefined, type: 'text' } }, }, @@ -198,13 +198,13 @@ describe('Ingest Manager - validatePackageConfig()', () => { streams: [ { id: 'with-disabled-streams-disabled', - dataset: { name: 'disabled', type: 'logs' }, + data_stream: { dataset: 'disabled', type: 'logs' }, enabled: false, vars: { 'var-name': { value: undefined, type: 'text' } }, }, { id: 'with-disabled-streams-disabled-without-vars', - dataset: { name: 'disabled2', type: 'logs' }, + data_stream: { dataset: 'disabled2', type: 'logs' }, enabled: false, }, ], @@ -218,7 +218,7 @@ describe('Ingest Manager - validatePackageConfig()', () => { streams: [ { id: 'with-no-stream-vars-bar', - dataset: { name: 'bar', type: 'logs' }, + data_stream: { dataset: 'bar', type: 'logs' }, enabled: true, }, ], @@ -241,7 +241,7 @@ describe('Ingest Manager - validatePackageConfig()', () => { streams: [ { id: 'foo-foo', - dataset: { name: 'foo', type: 'logs' }, + data_stream: { dataset: 'foo', type: 'logs' }, enabled: true, vars: { 'var-name': { value: 'invalidyaml: test\n foo bar:', type: 'yaml' } }, }, @@ -257,13 +257,13 @@ describe('Ingest Manager - validatePackageConfig()', () => { streams: [ { id: 'bar-bar', - dataset: { name: 'bar', type: 'logs' }, + data_stream: { dataset: 'bar', type: 'logs' }, enabled: true, vars: { 'var-name': { value: ' \n\n', type: 'yaml' } }, }, { id: 'bar-bar2', - dataset: { name: 'bar2', type: 'logs' }, + data_stream: { dataset: 'bar2', type: 'logs' }, enabled: true, vars: { 'var-name': { value: undefined, type: 'text' } }, }, @@ -280,7 +280,7 @@ describe('Ingest Manager - validatePackageConfig()', () => { streams: [ { id: 'with-disabled-streams-disabled', - dataset: { name: 'disabled', type: 'logs' }, + data_stream: { dataset: 'disabled', type: 'logs' }, enabled: false, vars: { 'var-name': { @@ -291,7 +291,7 @@ describe('Ingest Manager - validatePackageConfig()', () => { }, { id: 'with-disabled-streams-disabled-without-vars', - dataset: { name: 'disabled2', type: 'logs' }, + data_stream: { dataset: 'disabled2', type: 'logs' }, enabled: false, }, ], @@ -305,7 +305,7 @@ describe('Ingest Manager - validatePackageConfig()', () => { streams: [ { id: 'with-no-stream-vars-bar', - dataset: { name: 'bar', type: 'logs' }, + data_stream: { dataset: 'bar', type: 'logs' }, enabled: true, }, ], diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_configure_package.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_configure_package.tsx index 380a03e15695b..a41d4d72db34c 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_configure_package.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_package_config_page/step_configure_package.tsx @@ -14,16 +14,16 @@ import { CreatePackageConfigFrom } from './types'; const findStreamsForInputType = ( inputType: string, packageInfo: PackageInfo -): Array => { - const streams: Array = []; +): Array => { + const streams: Array = []; (packageInfo.datasets || []).forEach((dataset) => { (dataset.streams || []).forEach((stream) => { if (stream.input === inputType) { streams.push({ ...stream, - dataset: { - name: dataset.name, + data_stream: { + dataset: dataset.name, }, }); } diff --git a/x-pack/plugins/ingest_manager/server/routes/epm/handlers.ts b/x-pack/plugins/ingest_manager/server/routes/epm/handlers.ts index f8f39f6294260..bbd91b97a86c9 100644 --- a/x-pack/plugins/ingest_manager/server/routes/epm/handlers.ts +++ b/x-pack/plugins/ingest_manager/server/routes/epm/handlers.ts @@ -33,6 +33,7 @@ import { getInstallationObject, } from '../../services/epm/packages'; import { IngestManagerError, getHTTPResponseCode } from '../../errors'; +import { splitPkgKey } from '../../services/epm/registry'; export const getCategoriesHandler: RequestHandler< undefined, @@ -131,7 +132,7 @@ export const getInfoHandler: RequestHandler { // if this is an update because a package is being unisntalled (no pkgkey argument passed) and no other packages are installed, remove the index pattern if (!pkgName && installedPackages.length === 0) { diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts index 1346b75c81e48..0911aaf248e7a 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts @@ -103,7 +103,7 @@ export async function installPackage({ force?: boolean; }): Promise { // TODO: change epm API to /packageName/version so we don't need to do this - const [pkgName, pkgVersion] = pkgkey.split('-'); + const { pkgName, pkgVersion } = Registry.splitPkgKey(pkgkey); // TODO: calls to getInstallationObject, Registry.fetchInfo, and Registry.fetchFindLatestPackge // and be replaced by getPackageInfo after adjusting for it to not group/use archive assets const latestPackage = await Registry.fetchFindLatestPackage(pkgName); diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/remove.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/remove.ts index 1acf2131dcb01..1e50c67d63c42 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/remove.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/remove.ts @@ -13,6 +13,7 @@ import { getInstallation, savedObjectTypes } from './index'; import { deletePipeline } from '../elasticsearch/ingest_pipeline/'; import { installIndexPatterns } from '../kibana/index_pattern/install'; import { packageConfigService, appContextService } from '../..'; +import { splitPkgKey } from '../registry'; export async function removeInstallation(options: { savedObjectsClient: SavedObjectsClientContract; @@ -21,7 +22,7 @@ export async function removeInstallation(options: { }): Promise { const { savedObjectsClient, pkgkey, callCluster } = options; // TODO: the epm api should change to /name/version so we don't need to do this - const [pkgName] = pkgkey.split('-'); + const { pkgName } = splitPkgKey(pkgkey); const installation = await getInstallation({ savedObjectsClient, pkgName }); if (!installation) throw Boom.badRequest(`${pkgName} is not installed`); if (installation.removable === false) diff --git a/x-pack/plugins/ingest_manager/server/services/epm/registry/index.test.ts b/x-pack/plugins/ingest_manager/server/services/epm/registry/index.test.ts index eae84275a49b9..085dc990fa376 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/registry/index.test.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/registry/index.test.ts @@ -5,7 +5,7 @@ */ import { AssetParts } from '../../../types'; -import { pathParts } from './index'; +import { pathParts, splitPkgKey } from './index'; const testPaths = [ { @@ -48,3 +48,35 @@ test('testPathParts', () => { expect(pathParts(value.path)).toStrictEqual(value.assetParts as AssetParts); } }); + +describe('splitPkgKey tests', () => { + it('throws an error if the delimiter is not found', () => { + expect(() => { + splitPkgKey('awesome_package'); + }).toThrow(); + }); + + it('throws an error if there is nothing before the delimiter', () => { + expect(() => { + splitPkgKey('-0.0.1-dev1'); + }).toThrow(); + }); + + it('throws an error if the version is not a semver', () => { + expect(() => { + splitPkgKey('awesome-laskdfj'); + }).toThrow(); + }); + + it('returns the name and version if the delimiter is found once', () => { + const { pkgName, pkgVersion } = splitPkgKey('awesome-0.1.0'); + expect(pkgName).toBe('awesome'); + expect(pkgVersion).toBe('0.1.0'); + }); + + it('returns the name and version if the delimiter is found multiple times', () => { + const { pkgName, pkgVersion } = splitPkgKey('endpoint-0.13.0-alpha.1+abcd'); + expect(pkgName).toBe('endpoint'); + expect(pkgVersion).toBe('0.13.0-alpha.1+abcd'); + }); +}); diff --git a/x-pack/plugins/ingest_manager/server/services/epm/registry/index.ts b/x-pack/plugins/ingest_manager/server/services/epm/registry/index.ts index c701762e50b50..b635378960468 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/registry/index.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/registry/index.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import semver from 'semver'; import { Response } from 'node-fetch'; import { URL } from 'url'; import { @@ -35,6 +36,26 @@ export interface CategoriesParams { experimental?: boolean; } +/** + * Extract the package name and package version from a string. + * + * @param pkgkey a string containing the package name delimited by the package version + */ +export function splitPkgKey(pkgkey: string): { pkgName: string; pkgVersion: string } { + // this will return an empty string if `indexOf` returns -1 + const pkgName = pkgkey.substr(0, pkgkey.indexOf('-')); + if (pkgName === '') { + throw new Error('Package key parsing failed: package name was empty'); + } + + // this will return the entire string if `indexOf` return -1 + const pkgVersion = pkgkey.substr(pkgkey.indexOf('-') + 1); + if (!semver.valid(pkgVersion)) { + throw new Error('Package key parsing failed: package version was not a valid semver'); + } + return { pkgName, pkgVersion }; +} + export const pkgToPkgKey = ({ name, version }: { name: string; version: string }) => `${name}-${version}`; diff --git a/x-pack/plugins/ingest_manager/server/services/package_config.test.ts b/x-pack/plugins/ingest_manager/server/services/package_config.test.ts index e86e2608e252d..28aa0d773d75b 100644 --- a/x-pack/plugins/ingest_manager/server/services/package_config.test.ts +++ b/x-pack/plugins/ingest_manager/server/services/package_config.test.ts @@ -65,7 +65,7 @@ describe('Package config service', () => { streams: [ { id: 'dataset01', - dataset: { name: 'package.dataset1', type: 'logs' }, + data_stream: { dataset: 'package.dataset1', type: 'logs' }, enabled: true, vars: { paths: { @@ -85,7 +85,7 @@ describe('Package config service', () => { streams: [ { id: 'dataset01', - dataset: { name: 'package.dataset1', type: 'logs' }, + data_stream: { dataset: 'package.dataset1', type: 'logs' }, enabled: true, vars: { paths: { @@ -131,7 +131,7 @@ describe('Package config service', () => { streams: [ { id: 'dataset01', - dataset: { name: 'package.dataset1', type: 'logs' }, + data_stream: { dataset: 'package.dataset1', type: 'logs' }, enabled: true, }, ], @@ -151,7 +151,7 @@ describe('Package config service', () => { streams: [ { id: 'dataset01', - dataset: { name: 'package.dataset1', type: 'logs' }, + data_stream: { dataset: 'package.dataset1', type: 'logs' }, enabled: true, compiled_stream: { metricset: ['dataset1'], diff --git a/x-pack/plugins/ingest_manager/server/services/package_config.ts b/x-pack/plugins/ingest_manager/server/services/package_config.ts index a369aa5c41cd4..665c08316588c 100644 --- a/x-pack/plugins/ingest_manager/server/services/package_config.ts +++ b/x-pack/plugins/ingest_manager/server/services/package_config.ts @@ -379,14 +379,14 @@ async function _assignPackageStreamToStream( if (!stream.enabled) { return { ...stream, compiled_stream: undefined }; } - const datasetPath = getDataset(stream.dataset.name); + const datasetPath = getDataset(stream.data_stream.dataset); const packageDatasets = pkgInfo.datasets; if (!packageDatasets) { throw new Error('Stream template not found, no datasets'); } const packageDataset = packageDatasets.find( - (pkgDataset) => pkgDataset.name === stream.dataset.name + (pkgDataset) => pkgDataset.name === stream.data_stream.dataset ); if (!packageDataset) { throw new Error(`Stream template not found, unable to find dataset ${datasetPath}`); diff --git a/x-pack/plugins/ingest_manager/server/types/models/package_config.ts b/x-pack/plugins/ingest_manager/server/types/models/package_config.ts index 0823ccd85a32b..9b7ffb4f78175 100644 --- a/x-pack/plugins/ingest_manager/server/types/models/package_config.ts +++ b/x-pack/plugins/ingest_manager/server/types/models/package_config.ts @@ -45,7 +45,7 @@ const PackageConfigBaseSchema = { schema.object({ id: schema.string(), enabled: schema.boolean(), - dataset: schema.object({ name: schema.string(), type: schema.string() }), + data_stream: schema.object({ dataset: schema.string(), type: schema.string() }), vars: schema.maybe(ConfigRecordSchema), config: schema.maybe( schema.recordOf( diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/__jest__/pipeline_processors_editor.helpers.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/__jest__/pipeline_processors_editor.helpers.tsx index 227513dcdaacc..5ac43953e79bc 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/__jest__/pipeline_processors_editor.helpers.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/__jest__/pipeline_processors_editor.helpers.tsx @@ -89,7 +89,7 @@ const createActions = (testBed: TestBed) => { async addProcessor(processorsSelector: string, type: string, options: Record) { find(`${processorsSelector}.addProcessorButton`).simulate('click'); await act(async () => { - find('processorTypeSelector').simulate('change', [{ value: type, label: type }]); + find('processorTypeSelector.input').simulate('change', [{ value: type, label: type }]); }); component.update(); await act(async () => { @@ -129,7 +129,7 @@ const createActions = (testBed: TestBed) => { find(`${processorSelector}.moreMenu.button`).simulate('click'); find(`${processorSelector}.moreMenu.addOnFailureButton`).simulate('click'); await act(async () => { - find('processorTypeSelector').simulate('change', [{ value: type, label: type }]); + find('processorTypeSelector.input').simulate('change', [{ value: type, label: type }]); }); component.update(); await act(async () => { diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.tsx index b43e2bc1342c3..edabbe277e5d9 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.tsx @@ -22,6 +22,8 @@ import { ProcessorsDispatch } from '../../processors_reducer'; import { ProcessorInfo } from '../processors_tree'; +import { getProcessorDescriptor } from '../shared'; + import './pipeline_processors_editor_item.scss'; import { InlineTextInput } from './inline_text_input'; @@ -139,7 +141,7 @@ export const PipelineProcessorsEditorItem: FunctionComponent = memo( className="pipelineProcessorsEditor__item__processorTypeLabel" color={isDimmed ? 'subdued' : undefined} > - {processor.type} + {getProcessorDescriptor(processor.type)?.label ?? processor.type} diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processor_settings_form/processor_settings_form.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processor_settings_form/processor_settings_form.tsx index 015adae83e71e..b5b3a38bb6a6c 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processor_settings_form/processor_settings_form.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processor_settings_form/processor_settings_form.tsx @@ -23,8 +23,9 @@ import { import { Form, FormDataProvider, FormHook } from '../../../../../shared_imports'; import { ProcessorInternal } from '../../types'; +import { getProcessorDescriptor } from '../shared'; + import { DocumentationButton } from './documentation_button'; -import { getProcessorFormDescriptor } from './map_processor_type_to_form'; import { CommonProcessorFields, ProcessorTypeField } from './processors/common_fields'; import { Custom } from './processors/custom'; @@ -88,7 +89,7 @@ export const ProcessorSettingsForm: FunctionComponent = memo( {({ type }) => { - const formDescriptor = getProcessorFormDescriptor(type as any); + const formDescriptor = getProcessorDescriptor(type as any); if (formDescriptor) { return ( @@ -114,7 +115,7 @@ export const ProcessorSettingsForm: FunctionComponent = memo( const { type } = arg; if (type?.length) { - const formDescriptor = getProcessorFormDescriptor(type as any); + const formDescriptor = getProcessorDescriptor(type as any); if (formDescriptor?.FieldsComponent) { return ( diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processor_settings_form/processors/common_fields/processor_type_field.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processor_settings_form/processors/common_fields/processor_type_field.tsx index 4b82fbfad9b52..71ee4a714a28e 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processor_settings_form/processors/common_fields/processor_type_field.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processor_settings_form/processors/common_fields/processor_type_field.tsx @@ -3,16 +3,42 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { FunctionComponent } from 'react'; +import { flow } from 'fp-ts/lib/function'; +import { map } from 'fp-ts/lib/Array'; + import { FIELD_TYPES, FieldConfig, UseField, fieldValidators, - ComboBoxField, } from '../../../../../../../shared_imports'; -import { types } from '../../map_processor_type_to_form'; + +import { getProcessorDescriptor, mapProcessorTypeToDescriptor } from '../../../shared'; +import { + FieldValidateResponse, + VALIDATION_TYPES, +} from '../../../../../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib'; + +const extractProcessorTypesAndLabels = flow( + Object.entries, + map(([type, { label }]) => ({ + label, + value: type, + })), + (arr) => arr.sort((a, b) => a.label.localeCompare(b.label)) +); + +interface ProcessorTypeAndLabel { + value: string; + label: string; +} + +const processorTypesAndLabels: ProcessorTypeAndLabel[] = extractProcessorTypesAndLabels( + mapProcessorTypeToDescriptor +); interface Props { initialType?: string; @@ -47,22 +73,76 @@ const typeConfig: FieldConfig = { export const ProcessorTypeField: FunctionComponent = ({ initialType }) => { return ( - ({ label: type, value: type })), - noSuggestions: false, - singleSelection: { - asPlainText: true, - }, - }, + + {(typeField) => { + let selectedOptions: ProcessorTypeAndLabel[]; + if ((typeField.value as string[]).length) { + const [type] = typeField.value as string[]; + const descriptor = getProcessorDescriptor(type); + selectedOptions = descriptor + ? [{ label: descriptor.label, value: type }] + : // If there is no label for this processor type, just use the type as the label + [{ label: type, value: type }]; + } else { + selectedOptions = []; + } + + const error = typeField.getErrorsMessages(); + const isInvalid = error ? Boolean(error.length) : false; + + const onCreateComboOption = (value: string) => { + // Note: for now, all validations for a comboBox array item have to be synchronous + // If there is a need to support asynchronous validation, we'll work on it (and will need to update the logic). + const { isValid } = typeField.validate({ + value, + validationType: VALIDATION_TYPES.ARRAY_ITEM, + }) as FieldValidateResponse; + + if (!isValid) { + // Return false to explicitly reject the user's input. + return false; + } + + const newValue = [...(typeField.value as string[]), value]; + + typeField.setValue(newValue); + }; + + return ( + + { + typeField.setValue(options.map(({ value }) => value)); + }} + noSuggestions={false} + singleSelection={{ + asPlainText: true, + }} + data-test-subj="input" + /> + + ); }} - /> + ); }; diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/shared/index.ts b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/shared/index.ts new file mode 100644 index 0000000000000..1b4b975b5305e --- /dev/null +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/shared/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { + getProcessorDescriptor, + mapProcessorTypeToDescriptor, + ProcessorType, +} from './map_processor_type_to_form'; diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processor_settings_form/map_processor_type_to_form.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/shared/map_processor_type_to_form.tsx similarity index 95% rename from x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processor_settings_form/map_processor_type_to_form.tsx rename to x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/shared/map_processor_type_to_form.tsx index 5993d7fb3f87a..7055721fc8b07 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processor_settings_form/map_processor_type_to_form.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/shared/map_processor_type_to_form.tsx @@ -10,7 +10,7 @@ import { FunctionComponent } from 'react'; // import { SetProcessor } from './processors/set'; // import { Gsub } from './processors/gsub'; -interface FieldsFormDescriptor { +interface FieldDescriptor { FieldsComponent?: FunctionComponent; docLinkPath: string; /** @@ -19,7 +19,9 @@ interface FieldsFormDescriptor { label: string; } -const mapProcessorTypeToFormDescriptor: Record = { +type MapProcessorTypeToDescriptor = Record; + +export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { append: { FieldsComponent: undefined, // TODO: Implement docLinkPath: '/append-processor.html', @@ -262,12 +264,10 @@ const mapProcessorTypeToFormDescriptor: Record = { }, }; -export const types = Object.keys(mapProcessorTypeToFormDescriptor).sort(); - -export type ProcessorType = keyof typeof mapProcessorTypeToFormDescriptor; +export type ProcessorType = keyof typeof mapProcessorTypeToDescriptor; -export const getProcessorFormDescriptor = ( +export const getProcessorDescriptor = ( type: ProcessorType | string -): FieldsFormDescriptor | undefined => { - return mapProcessorTypeToFormDescriptor[type as ProcessorType]; +): FieldDescriptor | undefined => { + return mapProcessorTypeToDescriptor[type as ProcessorType]; }; diff --git a/x-pack/plugins/lens/public/app_plugin/app.tsx b/x-pack/plugins/lens/public/app_plugin/app.tsx index 4a8694862642b..ffab84a51a229 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.tsx @@ -19,6 +19,7 @@ import { import { createKbnUrlStateStorage, IStorageWrapper, + withNotifyOnErrors, } from '../../../../../src/plugins/kibana_utils/public'; import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; import { @@ -152,6 +153,7 @@ export function App({ const kbnUrlStateStorage = createKbnUrlStateStorage({ history, useHash: core.uiSettings.get('state:storeInSessionStorage'), + ...withNotifyOnErrors(core.notifications.toasts), }); const { stop: stopSyncingQueryServiceStateWithUrl } = syncQueryStateWithUrl( data.query, @@ -166,6 +168,7 @@ export function App({ }, [ data.query.filterManager, data.query.timefilter.timefilter, + core.notifications.toasts, core.uiSettings, data.query, history, @@ -333,9 +336,7 @@ export function App({ ...s, isSaveModalVisible: false, originatingApp: - saveProps.newCopyOnSave && !saveProps.returnToOrigin - ? undefined - : currentOriginatingApp, + newlyCreated && !saveProps.returnToOrigin ? undefined : currentOriginatingApp, persistedDoc: newDoc, lastKnownDoc: newDoc, })); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/change_indexpattern.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/change_indexpattern.tsx index 5e2fe9d7bbc14..a62db353e2baf 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/change_indexpattern.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/change_indexpattern.tsx @@ -57,7 +57,7 @@ export function ChangeIndexPattern({ panelPaddingSize="s" ownFocus > -
+
{i18n.translate('xpack.lens.indexPattern.changeIndexPatternTitle', { defaultMessage: 'Change index pattern', diff --git a/x-pack/plugins/lens/public/persistence/saved_object_store.test.ts b/x-pack/plugins/lens/public/persistence/saved_object_store.test.ts index f7caac6549389..f8f8d889233a7 100644 --- a/x-pack/plugins/lens/public/persistence/saved_object_store.test.ts +++ b/x-pack/plugins/lens/public/persistence/saved_object_store.test.ts @@ -4,19 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ +import { SavedObjectsClientContract, SavedObjectsBulkUpdateObject } from 'kibana/public'; import { SavedObjectIndexStore } from './saved_object_store'; describe('LensStore', () => { function testStore(testId?: string) { const client = { create: jest.fn(() => Promise.resolve({ id: testId || 'testid' })), - update: jest.fn((_type: string, id: string) => Promise.resolve({ id })), + bulkUpdate: jest.fn(([{ id }]: SavedObjectsBulkUpdateObject[]) => + Promise.resolve({ savedObjects: [{ id }, { id }] }) + ), get: jest.fn(), }; return { client, - store: new SavedObjectIndexStore(client), + store: new SavedObjectIndexStore((client as unknown) as SavedObjectsClientContract), }; } @@ -108,19 +111,35 @@ describe('LensStore', () => { }, }); - expect(client.update).toHaveBeenCalledTimes(1); - expect(client.update).toHaveBeenCalledWith('lens', 'Gandalf', { - title: 'Even the very wise cannot see all ends.', - visualizationType: 'line', - expression: '', - state: { - datasourceMetaData: { filterableIndexPatterns: [] }, - datasourceStates: { indexpattern: { type: 'index_pattern', indexPattern: 'lotr' } }, - visualization: { gear: ['staff', 'pointy hat'] }, - query: { query: '', language: 'lucene' }, - filters: [], + expect(client.bulkUpdate).toHaveBeenCalledTimes(1); + expect(client.bulkUpdate).toHaveBeenCalledWith([ + { + type: 'lens', + id: 'Gandalf', + attributes: { + title: null, + visualizationType: null, + expression: null, + state: null, + }, }, - }); + { + type: 'lens', + id: 'Gandalf', + attributes: { + title: 'Even the very wise cannot see all ends.', + visualizationType: 'line', + expression: '', + state: { + datasourceMetaData: { filterableIndexPatterns: [] }, + datasourceStates: { indexpattern: { type: 'index_pattern', indexPattern: 'lotr' } }, + visualization: { gear: ['staff', 'pointy hat'] }, + query: { query: '', language: 'lucene' }, + filters: [], + }, + }, + }, + ]); }); }); diff --git a/x-pack/plugins/lens/public/persistence/saved_object_store.ts b/x-pack/plugins/lens/public/persistence/saved_object_store.ts index af90634874fb1..59ead53956a8d 100644 --- a/x-pack/plugins/lens/public/persistence/saved_object_store.ts +++ b/x-pack/plugins/lens/public/persistence/saved_object_store.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SavedObjectAttributes } from 'kibana/server'; +import { SavedObjectAttributes, SavedObjectsClientContract } from 'kibana/public'; import { Query, Filter } from '../../../../../src/plugins/data/public'; export interface Document { @@ -27,20 +27,6 @@ export interface Document { export const DOC_TYPE = 'lens'; -interface SavedObjectClient { - create: (type: string, object: SavedObjectAttributes) => Promise<{ id: string }>; - update: (type: string, id: string, object: SavedObjectAttributes) => Promise<{ id: string }>; - get: ( - type: string, - id: string - ) => Promise<{ - id: string; - type: string; - attributes: SavedObjectAttributes; - error?: { statusCode: number; message: string }; - }>; -} - export interface DocumentSaver { save: (vis: Document) => Promise<{ id: string }>; } @@ -52,9 +38,9 @@ export interface DocumentLoader { export type SavedObjectStore = DocumentLoader & DocumentSaver; export class SavedObjectIndexStore implements SavedObjectStore { - private client: SavedObjectClient; + private client: SavedObjectsClientContract; - constructor(client: SavedObjectClient) { + constructor(client: SavedObjectsClientContract) { this.client = client; } @@ -63,13 +49,33 @@ export class SavedObjectIndexStore implements SavedObjectStore { // TODO: SavedObjectAttributes should support this kind of object, // remove this workaround when SavedObjectAttributes is updated. const attributes = (rest as unknown) as SavedObjectAttributes; + const result = await (id - ? this.client.update(DOC_TYPE, id, attributes) + ? this.safeUpdate(id, attributes) : this.client.create(DOC_TYPE, attributes)); return { ...vis, id: result.id }; } + // As Lens is using an object to store its attributes, using the update API + // will merge the new attribute object with the old one, not overwriting deleted + // keys. As Lens is using objects as maps in various places, this is a problem because + // deleted subtrees make it back into the object after a load. + // This function fixes this by doing two updates - one to empty out the document setting + // every key to null, and a second one to load the new content. + private async safeUpdate(id: string, attributes: SavedObjectAttributes) { + const resetAttributes: SavedObjectAttributes = {}; + Object.keys(attributes).forEach((key) => { + resetAttributes[key] = null; + }); + return ( + await this.client.bulkUpdate([ + { type: DOC_TYPE, id, attributes: resetAttributes }, + { type: DOC_TYPE, id, attributes }, + ]) + ).savedObjects[1]; + } + async load(id: string): Promise { const { type, attributes, error } = await this.client.get(DOC_TYPE, id); @@ -78,7 +84,7 @@ export class SavedObjectIndexStore implements SavedObjectStore { } return { - ...attributes, + ...(attributes as SavedObjectAttributes), id, type, } as Document; diff --git a/x-pack/plugins/lens/public/pie_visualization/pie_visualization.tsx b/x-pack/plugins/lens/public/pie_visualization/pie_visualization.tsx index 369ab28293fbc..5a68516db6aa3 100644 --- a/x-pack/plugins/lens/public/pie_visualization/pie_visualization.tsx +++ b/x-pack/plugins/lens/public/pie_visualization/pie_visualization.tsx @@ -122,6 +122,7 @@ export const pieVisualization: Visualization { ); const options = component - .find('[data-test-subj="lnsXY_seriesType"]') + .find(EuiButtonGroup) .first() .prop('options') as EuiButtonGroupProps['options']; @@ -79,7 +79,7 @@ describe('XY Config panels', () => { ); const options = component - .find('[data-test-subj="lnsXY_seriesType"]') + .find(EuiButtonGroup) .first() .prop('options') as EuiButtonGroupProps['options']; diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx index 6d5bc7808a678..e4bc6de5cc68a 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx @@ -95,13 +95,13 @@ export function LayerContextMenu(props: VisualizationLayerWidgetProps) { })} name="chartType" className="eui-displayInlineBlock" - data-test-subj="lnsXY_seriesType" options={visualizationTypes .filter((t) => isHorizontalSeries(t.id as SeriesType) === horizontalOnly) .map((t) => ({ id: t.id, label: t.label, iconType: t.icon || 'empty', + 'data-test-subj': `lnsXY_seriesType-${t.id}`, }))} idSelected={layer.seriesType} onChange={(seriesType) => { diff --git a/x-pack/plugins/lists/common/schemas/types/comment.test.ts b/x-pack/plugins/lists/common/schemas/types/comment.test.ts index 081bb9b4bae54..9b6f0e76bdd54 100644 --- a/x-pack/plugins/lists/common/schemas/types/comment.test.ts +++ b/x-pack/plugins/lists/common/schemas/types/comment.test.ts @@ -60,7 +60,6 @@ describe('Comment', () => { expect(getPaths(left(message.errors))).toEqual([ 'Invalid value "undefined" supplied to "({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)"', - 'Invalid value "undefined" supplied to "({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)"', ]); expect(message.schema).toEqual({}); }); @@ -200,7 +199,6 @@ describe('Comment', () => { expect(getPaths(left(message.errors))).toEqual([ 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', - 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', ]); expect(message.schema).toEqual({}); }); @@ -232,7 +230,6 @@ describe('Comment', () => { expect(getPaths(left(message.errors))).toEqual([ 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', - 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', ]); expect(message.schema).toEqual({}); }); diff --git a/x-pack/plugins/lists/common/schemas/types/default_comments_array.test.ts b/x-pack/plugins/lists/common/schemas/types/default_comments_array.test.ts index ee2dc0cf2a478..0f5ed2ee4a98b 100644 --- a/x-pack/plugins/lists/common/schemas/types/default_comments_array.test.ts +++ b/x-pack/plugins/lists/common/schemas/types/default_comments_array.test.ts @@ -39,7 +39,6 @@ describe('default_comments_array', () => { expect(getPaths(left(message.errors))).toEqual([ 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', - 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', ]); expect(message.schema).toEqual({}); }); @@ -51,7 +50,6 @@ describe('default_comments_array', () => { expect(getPaths(left(message.errors))).toEqual([ 'Invalid value "some string" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', - 'Invalid value "some string" supplied to "Array<({| comment: NonEmptyString, created_at: string, created_by: string, id: NonEmptyString |} & Partial<{| updated_at: string, updated_by: string |}>)>"', ]); expect(message.schema).toEqual({}); }); diff --git a/x-pack/plugins/lists/common/schemas/types/default_update_comments_array.test.ts b/x-pack/plugins/lists/common/schemas/types/default_update_comments_array.test.ts index 25c84af8c9ee3..a0f6a2b2a6eaa 100644 --- a/x-pack/plugins/lists/common/schemas/types/default_update_comments_array.test.ts +++ b/x-pack/plugins/lists/common/schemas/types/default_update_comments_array.test.ts @@ -39,7 +39,6 @@ describe('default_update_comments_array', () => { expect(getPaths(left(message.errors))).toEqual([ 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"', - 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"', ]); expect(message.schema).toEqual({}); }); @@ -51,7 +50,6 @@ describe('default_update_comments_array', () => { expect(getPaths(left(message.errors))).toEqual([ 'Invalid value "some string" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"', - 'Invalid value "some string" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"', ]); expect(message.schema).toEqual({}); }); diff --git a/x-pack/plugins/lists/common/schemas/types/entries.test.ts b/x-pack/plugins/lists/common/schemas/types/entries.test.ts index f5c022c7a394f..0537b0b9c6c6a 100644 --- a/x-pack/plugins/lists/common/schemas/types/entries.test.ts +++ b/x-pack/plugins/lists/common/schemas/types/entries.test.ts @@ -61,17 +61,10 @@ describe('Entries', () => { const message = pipe(decoded, foldLeftRight); expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "operator"', - 'Invalid value "nested" supplied to "type"', - 'Invalid value "undefined" supplied to "value"', 'Invalid value "undefined" supplied to "operator"', 'Invalid value "nested" supplied to "type"', 'Invalid value "undefined" supplied to "value"', 'Invalid value "undefined" supplied to "list"', - 'Invalid value "undefined" supplied to "operator"', - 'Invalid value "nested" supplied to "type"', - 'Invalid value "undefined" supplied to "operator"', - 'Invalid value "nested" supplied to "type"', ]); expect(message.schema).toEqual({}); }); diff --git a/x-pack/plugins/lists/common/schemas/types/non_empty_entries_array.test.ts b/x-pack/plugins/lists/common/schemas/types/non_empty_entries_array.test.ts index 42d476a9fefb2..d81509d080056 100644 --- a/x-pack/plugins/lists/common/schemas/types/non_empty_entries_array.test.ts +++ b/x-pack/plugins/lists/common/schemas/types/non_empty_entries_array.test.ts @@ -125,10 +125,6 @@ describe('non_empty_entries_array', () => { expect(getPaths(left(message.errors))).toEqual([ 'Invalid value "1" supplied to "NonEmptyEntriesArray"', - 'Invalid value "1" supplied to "NonEmptyEntriesArray"', - 'Invalid value "1" supplied to "NonEmptyEntriesArray"', - 'Invalid value "1" supplied to "NonEmptyEntriesArray"', - 'Invalid value "1" supplied to "NonEmptyEntriesArray"', ]); expect(message.schema).toEqual({}); }); diff --git a/x-pack/plugins/lists/common/schemas/types/non_empty_nested_entries_array.test.ts b/x-pack/plugins/lists/common/schemas/types/non_empty_nested_entries_array.test.ts index 7dbc3465610c0..2e54590368959 100644 --- a/x-pack/plugins/lists/common/schemas/types/non_empty_nested_entries_array.test.ts +++ b/x-pack/plugins/lists/common/schemas/types/non_empty_nested_entries_array.test.ts @@ -86,19 +86,6 @@ describe('non_empty_nested_entries_array', () => { 'Invalid value "undefined" supplied to "operator"', 'Invalid value "nested" supplied to "type"', 'Invalid value "undefined" supplied to "value"', - 'Invalid value "undefined" supplied to "operator"', - 'Invalid value "nested" supplied to "type"', - 'Invalid value "undefined" supplied to "value"', - 'Invalid value "undefined" supplied to "operator"', - 'Invalid value "nested" supplied to "type"', - 'Invalid value "undefined" supplied to "operator"', - 'Invalid value "nested" supplied to "type"', - 'Invalid value "undefined" supplied to "value"', - 'Invalid value "undefined" supplied to "operator"', - 'Invalid value "nested" supplied to "type"', - 'Invalid value "undefined" supplied to "value"', - 'Invalid value "undefined" supplied to "operator"', - 'Invalid value "nested" supplied to "type"', ]); expect(message.schema).toEqual({}); }); @@ -123,8 +110,6 @@ describe('non_empty_nested_entries_array', () => { expect(getPaths(left(message.errors))).toEqual([ 'Invalid value "1" supplied to "NonEmptyNestedEntriesArray"', - 'Invalid value "1" supplied to "NonEmptyNestedEntriesArray"', - 'Invalid value "1" supplied to "NonEmptyNestedEntriesArray"', ]); expect(message.schema).toEqual({}); }); diff --git a/x-pack/plugins/lists/common/schemas/types/update_comment.test.ts b/x-pack/plugins/lists/common/schemas/types/update_comment.test.ts index ac4d0304cbb8e..ba07421fe60f4 100644 --- a/x-pack/plugins/lists/common/schemas/types/update_comment.test.ts +++ b/x-pack/plugins/lists/common/schemas/types/update_comment.test.ts @@ -110,7 +110,6 @@ describe('CommentsUpdate', () => { expect(getPaths(left(message.errors))).toEqual([ 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"', - 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"', ]); expect(message.schema).toEqual({}); }); @@ -142,7 +141,6 @@ describe('CommentsUpdate', () => { expect(getPaths(left(message.errors))).toEqual([ 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"', - 'Invalid value "1" supplied to "Array<({| comment: NonEmptyString |} & Partial<{| id: NonEmptyString |}>)>"', ]); expect(message.schema).toEqual({}); }); diff --git a/x-pack/plugins/maps/public/classes/styles/color_palettes.ts b/x-pack/plugins/maps/public/classes/styles/color_palettes.ts index e7574b4e7b3e4..51aadd98c1177 100644 --- a/x-pack/plugins/maps/public/classes/styles/color_palettes.ts +++ b/x-pack/plugins/maps/public/classes/styles/color_palettes.ts @@ -129,7 +129,7 @@ export function getColorRampCenterColor(colorPaletteId: string): string | null { // Returns an array of color stops // [ stop_input_1: number, stop_output_1: color, stop_input_n: number, stop_output_n: color ] export function getOrdinalMbColorRampStops( - colorPaletteId: string, + colorPaletteId: string | null, min: number, max: number ): Array | null { diff --git a/x-pack/plugins/maps/public/classes/styles/vector/components/legend/breaked_legend.tsx b/x-pack/plugins/maps/public/classes/styles/vector/components/legend/breaked_legend.tsx index 9d5bf85005ae1..8eca89e31cf7a 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/components/legend/breaked_legend.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/components/legend/breaked_legend.tsx @@ -14,8 +14,8 @@ const EMPTY_VALUE = ''; interface Break { color: string; - label: ReactElement | string; - symbolId: string; + label: ReactElement | string | number; + symbolId?: string; } interface Props { diff --git a/x-pack/plugins/maps/public/classes/styles/vector/components/legend/category.tsx b/x-pack/plugins/maps/public/classes/styles/vector/components/legend/category.tsx index 02ca4645dd8cd..4a71eb982d4d7 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/components/legend/category.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/components/legend/category.tsx @@ -11,11 +11,11 @@ import { VectorIcon } from './vector_icon'; interface Props { styleName: VECTOR_STYLES; - label: ReactElement | string; + label: ReactElement | string | number; color: string; isLinesOnly: boolean; isPointsOnly: boolean; - symbolId: string; + symbolId?: string; } export function Category({ styleName, label, color, isLinesOnly, isPointsOnly, symbolId }: Props) { diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.js.snap b/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap similarity index 93% rename from x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.js.snap rename to x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap index 402eab355406b..c722e86512e52 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.js.snap +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap @@ -121,6 +121,17 @@ exports[`ordinal Should render custom ordinal legend with breaks 1`] = ` > + + + + + + ({ import React from 'react'; import { shallow } from 'enzyme'; +import { Feature, Point } from 'geojson'; import { DynamicColorProperty } from './dynamic_color_property'; import { COLOR_MAP_TYPE, VECTOR_STYLES } from '../../../../../common/constants'; import { mockField, MockLayer, MockStyle } from './__tests__/test_util'; +import { ColorDynamicOptions } from '../../../../../common/descriptor_types'; +import { IVectorLayer } from '../../../layers/vector_layer/vector_layer'; +import { IField } from '../../../fields/field'; -const makeProperty = (options, mockStyle, field = mockField) => { +const makeProperty = (options: ColorDynamicOptions, style?: MockStyle, field?: IField) => { return new DynamicColorProperty( options, VECTOR_STYLES.LINE_COLOR, - field, - new MockLayer(mockStyle), + field ? field : mockField, + (new MockLayer(style ? style : new MockStyle()) as unknown) as IVectorLayer, () => { - return (x) => x + '_format'; + return (value: string | number | undefined) => value + '_format'; } ); }; @@ -35,11 +39,14 @@ const defaultLegendParams = { isLinesOnly: false, }; +const fieldMetaOptions = { isEnabled: true }; + describe('ordinal', () => { test('Should render ordinal legend as bands', async () => { const colorStyle = makeProperty({ color: 'Blues', type: undefined, + fieldMetaOptions, }); const legendRow = colorStyle.renderLegendDetailRow(defaultLegendParams); @@ -59,6 +66,7 @@ describe('ordinal', () => { { color: 'Blues', type: undefined, + fieldMetaOptions, }, new MockStyle({ min: 100, max: 100 }) ); @@ -89,6 +97,7 @@ describe('ordinal', () => { color: '#00FF00', }, ], + fieldMetaOptions, }); const legendRow = colorStyle.renderLegendDetailRow(defaultLegendParams); @@ -110,6 +119,7 @@ describe('categorical', () => { type: COLOR_MAP_TYPE.CATEGORICAL, useCustomColorPalette: false, colorCategory: 'palette_0', + fieldMetaOptions, }); const legendRow = colorStyle.renderLegendDetailRow(defaultLegendParams); @@ -130,7 +140,7 @@ describe('categorical', () => { useCustomColorPalette: true, customColorPalette: [ { - stop: null, //should include the default stop + stop: null, // should include the default stop color: '#FFFF00', }, { @@ -142,6 +152,7 @@ describe('categorical', () => { color: '#00FF00', }, ], + fieldMetaOptions, }); const legendRow = colorStyle.renderLegendDetailRow(defaultLegendParams); @@ -152,14 +163,18 @@ describe('categorical', () => { }); }); -function makeFeatures(foobarPropValues) { - return foobarPropValues.map((value) => { +function makeFeatures(foobarPropValues: string[]) { + return foobarPropValues.map((value: string) => { return { type: 'Feature', + geometry: { + type: 'Point', + coordinates: [-10, 0], + } as Point, properties: { foobar: value, }, - }; + } as Feature; }); } @@ -167,6 +182,7 @@ test('Should pluck the categorical style-meta', async () => { const colorStyle = makeProperty({ type: COLOR_MAP_TYPE.CATEGORICAL, colorCategory: 'palette_0', + fieldMetaOptions, }); const features = makeFeatures(['CN', 'CN', 'US', 'CN', 'US', 'IN']); @@ -185,6 +201,7 @@ test('Should pluck the categorical style-meta from fieldmeta', async () => { const colorStyle = makeProperty({ type: COLOR_MAP_TYPE.CATEGORICAL, colorCategory: 'palette_0', + fieldMetaOptions, }); const meta = colorStyle._pluckCategoricalStyleMetaFromFieldMetaData({ @@ -210,25 +227,27 @@ test('Should pluck the categorical style-meta from fieldmeta', async () => { }); describe('supportsFieldMeta', () => { - test('should support it when field does for ordinals', () => { + test('should support fieldMeta when ordinal field supports fieldMeta', () => { const dynamicStyleOptions = { type: COLOR_MAP_TYPE.ORDINAL, + fieldMetaOptions, }; const styleProp = makeProperty(dynamicStyleOptions); expect(styleProp.supportsFieldMeta()).toEqual(true); }); - test('should support it when field does for categories', () => { + test('should support fieldMeta when categorical field supports fieldMeta', () => { const dynamicStyleOptions = { type: COLOR_MAP_TYPE.CATEGORICAL, + fieldMetaOptions, }; const styleProp = makeProperty(dynamicStyleOptions); expect(styleProp.supportsFieldMeta()).toEqual(true); }); - test('should not support it when field does not', () => { + test('should not support fieldMeta when field does not support fieldMeta', () => { const field = Object.create(mockField); field.supportsFieldMeta = function () { return false; @@ -236,37 +255,50 @@ describe('supportsFieldMeta', () => { const dynamicStyleOptions = { type: COLOR_MAP_TYPE.ORDINAL, + fieldMetaOptions, }; const styleProp = makeProperty(dynamicStyleOptions, undefined, field); expect(styleProp.supportsFieldMeta()).toEqual(false); }); - test('should not support it when field config not complete', () => { + test('should not support fieldMeta when field is not provided', () => { const dynamicStyleOptions = { type: COLOR_MAP_TYPE.ORDINAL, + fieldMetaOptions, }; - const styleProp = makeProperty(dynamicStyleOptions, undefined, null); + + const styleProp = new DynamicColorProperty( + dynamicStyleOptions, + VECTOR_STYLES.LINE_COLOR, + null, + (new MockLayer(new MockStyle()) as unknown) as IVectorLayer, + () => { + return (value: string | number | undefined) => value + '_format'; + } + ); expect(styleProp.supportsFieldMeta()).toEqual(false); }); - test('should not support it when using custom ramp for ordinals', () => { + test('should not support fieldMeta when using custom ramp for ordinal field', () => { const dynamicStyleOptions = { type: COLOR_MAP_TYPE.ORDINAL, useCustomColorRamp: true, customColorRamp: [], + fieldMetaOptions, }; const styleProp = makeProperty(dynamicStyleOptions); expect(styleProp.supportsFieldMeta()).toEqual(false); }); - test('should not support it when using custom palette for categories', () => { + test('should not support fieldMeta when using custom palette for categorical field', () => { const dynamicStyleOptions = { type: COLOR_MAP_TYPE.CATEGORICAL, useCustomColorPalette: true, customColorPalette: [], + fieldMetaOptions, }; const styleProp = makeProperty(dynamicStyleOptions); @@ -279,6 +311,7 @@ describe('get mapbox color expression (via internal _getMbColor)', () => { test('should return null when field is not provided', async () => { const dynamicStyleOptions = { type: COLOR_MAP_TYPE.ORDINAL, + fieldMetaOptions, }; const colorProperty = makeProperty(dynamicStyleOptions); expect(colorProperty._getMbColor()).toBeNull(); @@ -288,7 +321,9 @@ describe('get mapbox color expression (via internal _getMbColor)', () => { const dynamicStyleOptions = { type: COLOR_MAP_TYPE.ORDINAL, field: {}, + fieldMetaOptions, }; + // @ts-expect-error - test is verifing behavior when field is invalid. const colorProperty = makeProperty(dynamicStyleOptions); expect(colorProperty._getMbColor()).toBeNull(); }); @@ -297,6 +332,7 @@ describe('get mapbox color expression (via internal _getMbColor)', () => { test('should return null when color ramp is not provided', async () => { const dynamicStyleOptions = { type: COLOR_MAP_TYPE.ORDINAL, + fieldMetaOptions, }; const colorProperty = makeProperty(dynamicStyleOptions); expect(colorProperty._getMbColor()).toBeNull(); @@ -305,6 +341,7 @@ describe('get mapbox color expression (via internal _getMbColor)', () => { const dynamicStyleOptions = { type: COLOR_MAP_TYPE.ORDINAL, color: 'Blues', + fieldMetaOptions, }; const colorProperty = makeProperty(dynamicStyleOptions); expect(colorProperty._getMbColor()).toEqual([ @@ -343,19 +380,11 @@ describe('get mapbox color expression (via internal _getMbColor)', () => { }); describe('custom color ramp', () => { - const dynamicStyleOptions = { - type: COLOR_MAP_TYPE.ORDINAL, - useCustomColorRamp: true, - customColorRamp: [ - { stop: 10, color: '#f7faff' }, - { stop: 100, color: '#072f6b' }, - ], - }; - test('should return null when customColorRamp is not provided', async () => { const dynamicStyleOptions = { type: COLOR_MAP_TYPE.ORDINAL, useCustomColorRamp: true, + fieldMetaOptions, }; const colorProperty = makeProperty(dynamicStyleOptions); expect(colorProperty._getMbColor()).toBeNull(); @@ -366,12 +395,22 @@ describe('get mapbox color expression (via internal _getMbColor)', () => { type: COLOR_MAP_TYPE.ORDINAL, useCustomColorRamp: true, customColorRamp: [], + fieldMetaOptions, }; const colorProperty = makeProperty(dynamicStyleOptions); expect(colorProperty._getMbColor()).toBeNull(); }); test('should use `feature-state` by default', async () => { + const dynamicStyleOptions = { + type: COLOR_MAP_TYPE.ORDINAL, + useCustomColorRamp: true, + customColorRamp: [ + { stop: 10, color: '#f7faff' }, + { stop: 100, color: '#072f6b' }, + ], + fieldMetaOptions, + }; const colorProperty = makeProperty(dynamicStyleOptions); expect(colorProperty._getMbColor()).toEqual([ 'step', @@ -389,6 +428,15 @@ describe('get mapbox color expression (via internal _getMbColor)', () => { field.canReadFromGeoJson = function () { return false; }; + const dynamicStyleOptions = { + type: COLOR_MAP_TYPE.ORDINAL, + useCustomColorRamp: true, + customColorRamp: [ + { stop: 10, color: '#f7faff' }, + { stop: 100, color: '#072f6b' }, + ], + fieldMetaOptions, + }; const colorProperty = makeProperty(dynamicStyleOptions, undefined, field); expect(colorProperty._getMbColor()).toEqual([ 'step', @@ -407,6 +455,7 @@ describe('get mapbox color expression (via internal _getMbColor)', () => { test('should return null when field is not provided', async () => { const dynamicStyleOptions = { type: COLOR_MAP_TYPE.CATEGORICAL, + fieldMetaOptions, }; const colorProperty = makeProperty(dynamicStyleOptions); expect(colorProperty._getMbColor()).toBeNull(); @@ -416,7 +465,9 @@ describe('get mapbox color expression (via internal _getMbColor)', () => { const dynamicStyleOptions = { type: COLOR_MAP_TYPE.CATEGORICAL, field: {}, + fieldMetaOptions, }; + // @ts-expect-error - test is verifing behavior when field is invalid. const colorProperty = makeProperty(dynamicStyleOptions); expect(colorProperty._getMbColor()).toBeNull(); }); @@ -425,6 +476,7 @@ describe('get mapbox color expression (via internal _getMbColor)', () => { test('should return null when color palette is not provided', async () => { const dynamicStyleOptions = { type: COLOR_MAP_TYPE.CATEGORICAL, + fieldMetaOptions, }; const colorProperty = makeProperty(dynamicStyleOptions); expect(colorProperty._getMbColor()).toBeNull(); @@ -434,6 +486,7 @@ describe('get mapbox color expression (via internal _getMbColor)', () => { const dynamicStyleOptions = { type: COLOR_MAP_TYPE.CATEGORICAL, colorCategory: 'palette_0', + fieldMetaOptions, }; const colorProperty = makeProperty(dynamicStyleOptions); expect(colorProperty._getMbColor()).toEqual([ @@ -453,6 +506,7 @@ describe('get mapbox color expression (via internal _getMbColor)', () => { const dynamicStyleOptions = { type: COLOR_MAP_TYPE.CATEGORICAL, useCustomColorPalette: true, + fieldMetaOptions, }; const colorProperty = makeProperty(dynamicStyleOptions); expect(colorProperty._getMbColor()).toBeNull(); @@ -463,6 +517,7 @@ describe('get mapbox color expression (via internal _getMbColor)', () => { type: COLOR_MAP_TYPE.CATEGORICAL, useCustomColorPalette: true, customColorPalette: [], + fieldMetaOptions, }; const colorProperty = makeProperty(dynamicStyleOptions); expect(colorProperty._getMbColor()).toBeNull(); @@ -476,6 +531,7 @@ describe('get mapbox color expression (via internal _getMbColor)', () => { { stop: null, color: '#f7faff' }, { stop: 'MX', color: '#072f6b' }, ], + fieldMetaOptions, }; const colorProperty = makeProperty(dynamicStyleOptions); expect(colorProperty._getMbColor()).toEqual([ @@ -494,6 +550,7 @@ test('isCategorical should return true when type is categorical', async () => { const categoricalColorStyle = makeProperty({ type: COLOR_MAP_TYPE.CATEGORICAL, colorCategory: 'palette_0', + fieldMetaOptions, }); expect(categoricalColorStyle.isOrdinal()).toEqual(false); @@ -504,6 +561,7 @@ test('isOrdinal should return true when type is ordinal', async () => { const ordinalColorStyle = makeProperty({ type: undefined, color: 'Blues', + fieldMetaOptions, }); expect(ordinalColorStyle.isOrdinal()).toEqual(true); @@ -514,6 +572,7 @@ test('Should read out ordinal type correctly', async () => { const ordinalColorStyle2 = makeProperty({ type: COLOR_MAP_TYPE.ORDINAL, colorCategory: 'palette_0', + fieldMetaOptions, }); expect(ordinalColorStyle2.isOrdinal()).toEqual(true); diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.js b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.tsx similarity index 79% rename from x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.js rename to x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.tsx index e643abcaf8d54..faecf51d4ced5 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.js +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.tsx @@ -4,69 +4,73 @@ * you may not use this file except in compliance with the Elastic License. */ +import { Map as MbMap } from 'mapbox-gl'; +import React from 'react'; +import { EuiTextColor } from '@elastic/eui'; import { DynamicStyleProperty } from './dynamic_style_property'; import { makeMbClampedNumberExpression, dynamicRound } from '../style_util'; import { getOrdinalMbColorRampStops, getColorPalette } from '../../color_palettes'; -import React from 'react'; import { COLOR_MAP_TYPE } from '../../../../../common/constants'; import { isCategoricalStopsInvalid, getOtherCategoryLabel, + // @ts-expect-error } from '../components/color/color_stops_utils'; import { BreakedLegend } from '../components/legend/breaked_legend'; -import { EuiTextColor } from '@elastic/eui'; +import { ColorDynamicOptions, OrdinalColorStop } from '../../../../../common/descriptor_types'; +import { LegendProps } from './style_property'; const EMPTY_STOPS = { stops: [], defaultColor: null }; const RGBA_0000 = 'rgba(0,0,0,0)'; -export class DynamicColorProperty extends DynamicStyleProperty { - syncCircleColorWithMb(mbLayerId, mbMap, alpha) { +export class DynamicColorProperty extends DynamicStyleProperty { + syncCircleColorWithMb(mbLayerId: string, mbMap: MbMap, alpha: number) { const color = this._getMbColor(); mbMap.setPaintProperty(mbLayerId, 'circle-color', color); mbMap.setPaintProperty(mbLayerId, 'circle-opacity', alpha); } - syncIconColorWithMb(mbLayerId, mbMap) { + syncIconColorWithMb(mbLayerId: string, mbMap: MbMap) { const color = this._getMbColor(); mbMap.setPaintProperty(mbLayerId, 'icon-color', color); } - syncHaloBorderColorWithMb(mbLayerId, mbMap) { + syncHaloBorderColorWithMb(mbLayerId: string, mbMap: MbMap) { const color = this._getMbColor(); mbMap.setPaintProperty(mbLayerId, 'icon-halo-color', color); } - syncCircleStrokeWithMb(pointLayerId, mbMap, alpha) { + syncCircleStrokeWithMb(pointLayerId: string, mbMap: MbMap, alpha: number) { const color = this._getMbColor(); mbMap.setPaintProperty(pointLayerId, 'circle-stroke-color', color); mbMap.setPaintProperty(pointLayerId, 'circle-stroke-opacity', alpha); } - syncFillColorWithMb(mbLayerId, mbMap, alpha) { + syncFillColorWithMb(mbLayerId: string, mbMap: MbMap, alpha: number) { const color = this._getMbColor(); mbMap.setPaintProperty(mbLayerId, 'fill-color', color); mbMap.setPaintProperty(mbLayerId, 'fill-opacity', alpha); } - syncLineColorWithMb(mbLayerId, mbMap, alpha) { + syncLineColorWithMb(mbLayerId: string, mbMap: MbMap, alpha: number) { const color = this._getMbColor(); mbMap.setPaintProperty(mbLayerId, 'line-color', color); mbMap.setPaintProperty(mbLayerId, 'line-opacity', alpha); } - syncLabelColorWithMb(mbLayerId, mbMap, alpha) { + syncLabelColorWithMb(mbLayerId: string, mbMap: MbMap, alpha: number) { const color = this._getMbColor(); mbMap.setPaintProperty(mbLayerId, 'text-color', color); mbMap.setPaintProperty(mbLayerId, 'text-opacity', alpha); } - syncLabelBorderColorWithMb(mbLayerId, mbMap) { + syncLabelBorderColorWithMb(mbLayerId: string, mbMap: MbMap) { const color = this._getMbColor(); mbMap.setPaintProperty(mbLayerId, 'text-halo-color', color); } supportsFieldMeta() { - if (!this.isComplete() || !this._field.supportsFieldMeta()) { + if (!this.isComplete() || !this._field || !this._field.supportsFieldMeta()) { return false; } @@ -87,12 +91,16 @@ export class DynamicColorProperty extends DynamicStyleProperty { } getNumberOfCategories() { + if (!this._options.colorCategory) { + return 0; + } + const colors = getColorPalette(this._options.colorCategory); return colors ? colors.length : 0; } _getMbColor() { - if (!this._field || !this._field.getName()) { + if (!this.getFieldName()) { return null; } @@ -102,17 +110,20 @@ export class DynamicColorProperty extends DynamicStyleProperty { } _getOrdinalColorMbExpression() { - const targetName = this._field.getName(); + const targetName = this.getFieldName(); if (this._options.useCustomColorRamp) { if (!this._options.customColorRamp || !this._options.customColorRamp.length) { // custom color ramp config is not complete return null; } - const colorStops = this._options.customColorRamp.reduce((accumulatedStops, nextStop) => { - return [...accumulatedStops, nextStop.stop, nextStop.color]; - }, []); - const firstStopValue = colorStops[0]; + const colorStops: Array = this._options.customColorRamp.reduce( + (accumulatedStops: Array, nextStop: OrdinalColorStop) => { + return [...accumulatedStops, nextStop.stop, nextStop.color]; + }, + [] + ); + const firstStopValue = colorStops[0] as number; const lessThanFirstStopValue = firstStopValue - 1; return [ 'step', @@ -127,7 +138,7 @@ export class DynamicColorProperty extends DynamicStyleProperty { } const colorStops = getOrdinalMbColorRampStops( - this._options.color, + this._options.color ? this._options.color : null, rangeFieldMeta.min, rangeFieldMeta.max ); @@ -179,7 +190,9 @@ export class DynamicColorProperty extends DynamicStyleProperty { return EMPTY_STOPS; } - const colors = getColorPalette(this._options.colorCategory); + const colors = this._options.colorCategory + ? getColorPalette(this._options.colorCategory) + : null; if (!colors) { return EMPTY_STOPS; } @@ -209,7 +222,7 @@ export class DynamicColorProperty extends DynamicStyleProperty { const { stops, defaultColor } = this._getColorPaletteStops(); if (stops.length < 1) { - //occurs when no data + // occurs when no data return null; } @@ -225,8 +238,8 @@ export class DynamicColorProperty extends DynamicStyleProperty { mbStops.push(stop.color); } - mbStops.push(defaultColor); //last color is default color - return ['match', ['to-string', ['get', this._field.getName()]], ...mbStops]; + mbStops.push(defaultColor); // last color is default color + return ['match', ['to-string', ['get', this.getFieldName()]], ...mbStops]; } _getColorRampStops() { @@ -246,7 +259,7 @@ export class DynamicColorProperty extends DynamicStyleProperty { const colors = getColorPalette(this._options.color); if (rangeFieldMeta.delta === 0) { - //map to last color. + // map to last color. return [ { color: colors[colors.length - 1], @@ -277,11 +290,11 @@ export class DynamicColorProperty extends DynamicStyleProperty { } } - renderLegendDetailRow({ isPointsOnly, isLinesOnly, symbolId }) { + renderLegendDetailRow({ isPointsOnly, isLinesOnly, symbolId }: LegendProps) { const { stops, defaultColor } = this._getColorStops(); const breaks = []; - stops.forEach(({ stop, color }) => { - if (stop) { + stops.forEach(({ stop, color }: { stop: string | number | null; color: string }) => { + if (stop !== null) { breaks.push({ color, symbolId, diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.test.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.test.tsx index c60547f3606c5..db44ae0da562d 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.test.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.test.tsx @@ -18,31 +18,52 @@ import { shallow } from 'enzyme'; import { DynamicSizeProperty } from './dynamic_size_property'; import { VECTOR_STYLES } from '../../../../../common/constants'; import { IField } from '../../../fields/field'; -import { MockMbMap } from './__tests__/test_util'; - +import { Map as MbMap } from 'mapbox-gl'; +import { SizeDynamicOptions } from '../../../../../common/descriptor_types'; import { mockField, MockLayer, MockStyle } from './__tests__/test_util'; +import { IVectorLayer } from '../../../layers/vector_layer/vector_layer'; + +export class MockMbMap { + _paintPropertyCalls: unknown[]; + + constructor() { + this._paintPropertyCalls = []; + } + setPaintProperty(...args: unknown[]) { + this._paintPropertyCalls.push([...args]); + } -const makeProperty = (options: object, mockStyle: MockStyle, field: IField = mockField) => { + getPaintPropertyCalls(): unknown[] { + return this._paintPropertyCalls; + } +} + +const makeProperty = ( + options: SizeDynamicOptions, + mockStyle: MockStyle, + field: IField = mockField +) => { return new DynamicSizeProperty( options, VECTOR_STYLES.ICON_SIZE, field, - new MockLayer(mockStyle), + (new MockLayer(mockStyle) as unknown) as IVectorLayer, () => { - return (x: string) => x + '_format'; - } + return (value: string | number | undefined) => value + '_format'; + }, + false ); }; -const defaultLegendParams = { - isPointsOnly: true, - isLinesOnly: false, -}; +const fieldMetaOptions = { isEnabled: true }; describe('renderLegendDetailRow', () => { test('Should render as range', async () => { - const sizeProp = makeProperty({}, new MockStyle({ min: 0, max: 100 })); - const legendRow = sizeProp.renderLegendDetailRow(defaultLegendParams); + const sizeProp = makeProperty( + { minSize: 0, maxSize: 10, fieldMetaOptions }, + new MockStyle({ min: 0, max: 100 }) + ); + const legendRow = sizeProp.renderLegendDetailRow(); const component = shallow(legendRow); // Ensure all promises resolve @@ -55,11 +76,15 @@ describe('renderLegendDetailRow', () => { describe('syncSize', () => { test('Should sync with circle-radius prop', async () => { - const sizeProp = makeProperty({ minSize: 8, maxSize: 32 }, new MockStyle({ min: 0, max: 100 })); - const mockMbMap = new MockMbMap(); + const sizeProp = makeProperty( + { minSize: 8, maxSize: 32, fieldMetaOptions }, + new MockStyle({ min: 0, max: 100 }) + ); + const mockMbMap = (new MockMbMap() as unknown) as MbMap; sizeProp.syncCircleRadiusWithMb('foobar', mockMbMap); + // @ts-expect-error expect(mockMbMap.getPaintPropertyCalls()).toEqual([ [ 'foobar', @@ -88,13 +113,14 @@ describe('syncSize', () => { test('Should truncate interpolate expression to max when no delta', async () => { const sizeProp = makeProperty( - { minSize: 8, maxSize: 32 }, + { minSize: 8, maxSize: 32, fieldMetaOptions }, new MockStyle({ min: 100, max: 100 }) ); - const mockMbMap = new MockMbMap(); + const mockMbMap = (new MockMbMap() as unknown) as MbMap; sizeProp.syncCircleRadiusWithMb('foobar', mockMbMap); + // @ts-expect-error expect(mockMbMap.getPaintPropertyCalls()).toEqual([ [ 'foobar', diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.js b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.tsx similarity index 72% rename from x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.js rename to x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.tsx index 83bd4b70ba5c3..35c830f3cb5e3 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.js +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.tsx @@ -4,20 +4,34 @@ * you may not use this file except in compliance with the Elastic License. */ -import { DynamicStyleProperty } from './dynamic_style_property'; +import _ from 'lodash'; +import React from 'react'; +import { Map as MbMap } from 'mapbox-gl'; +import { DynamicStyleProperty, FieldFormatter } from './dynamic_style_property'; import { OrdinalLegend } from '../components/legend/ordinal_legend'; import { makeMbClampedNumberExpression } from '../style_util'; import { HALF_LARGE_MAKI_ICON_SIZE, LARGE_MAKI_ICON_SIZE, SMALL_MAKI_ICON_SIZE, + // @ts-expect-error } from '../symbol_utils'; import { MB_LOOKUP_FUNCTION, VECTOR_STYLES } from '../../../../../common/constants'; -import _ from 'lodash'; -import React from 'react'; - -export class DynamicSizeProperty extends DynamicStyleProperty { - constructor(options, styleName, field, vectorLayer, getFieldFormatter, isSymbolizedAsIcon) { +import { SizeDynamicOptions } from '../../../../../common/descriptor_types'; +import { IField } from '../../../fields/field'; +import { IVectorLayer } from '../../../layers/vector_layer/vector_layer'; + +export class DynamicSizeProperty extends DynamicStyleProperty { + private readonly _isSymbolizedAsIcon: boolean; + + constructor( + options: SizeDynamicOptions, + styleName: VECTOR_STYLES, + field: IField | null, + vectorLayer: IVectorLayer, + getFieldFormatter: (fieldName: string) => null | FieldFormatter, + isSymbolizedAsIcon: boolean + ) { super(options, styleName, field, vectorLayer, getFieldFormatter); this._isSymbolizedAsIcon = isSymbolizedAsIcon; } @@ -36,7 +50,7 @@ export class DynamicSizeProperty extends DynamicStyleProperty { return super.supportsMbFeatureState(); } - syncHaloWidthWithMb(mbLayerId, mbMap) { + syncHaloWidthWithMb(mbLayerId: string, mbMap: MbMap) { const haloWidth = this.getMbSizeExpression(); mbMap.setPaintProperty(mbLayerId, 'icon-halo-width', haloWidth); } @@ -47,9 +61,9 @@ export class DynamicSizeProperty extends DynamicStyleProperty { : SMALL_MAKI_ICON_SIZE; } - syncIconSizeWithMb(symbolLayerId, mbMap) { + syncIconSizeWithMb(symbolLayerId: string, mbMap: MbMap) { const rangeFieldMeta = this.getRangeFieldMeta(); - if (this._isSizeDynamicConfigComplete(this._options) && rangeFieldMeta) { + if (this._isSizeDynamicConfigComplete() && rangeFieldMeta) { const halfIconPixels = this.getIconPixelSize() / 2; const targetName = this.getFieldName(); // Using property state instead of feature-state because layout properties do not support feature-state @@ -73,29 +87,29 @@ export class DynamicSizeProperty extends DynamicStyleProperty { } } - syncCircleStrokeWidthWithMb(mbLayerId, mbMap) { + syncCircleStrokeWidthWithMb(mbLayerId: string, mbMap: MbMap) { const lineWidth = this.getMbSizeExpression(); mbMap.setPaintProperty(mbLayerId, 'circle-stroke-width', lineWidth); } - syncCircleRadiusWithMb(mbLayerId, mbMap) { + syncCircleRadiusWithMb(mbLayerId: string, mbMap: MbMap) { const circleRadius = this.getMbSizeExpression(); mbMap.setPaintProperty(mbLayerId, 'circle-radius', circleRadius); } - syncLineWidthWithMb(mbLayerId, mbMap) { + syncLineWidthWithMb(mbLayerId: string, mbMap: MbMap) { const lineWidth = this.getMbSizeExpression(); mbMap.setPaintProperty(mbLayerId, 'line-width', lineWidth); } - syncLabelSizeWithMb(mbLayerId, mbMap) { + syncLabelSizeWithMb(mbLayerId: string, mbMap: MbMap) { const lineWidth = this.getMbSizeExpression(); mbMap.setLayoutProperty(mbLayerId, 'text-size', lineWidth); } getMbSizeExpression() { const rangeFieldMeta = this.getRangeFieldMeta(); - if (!this._isSizeDynamicConfigComplete(this._options) || !rangeFieldMeta) { + if (!this._isSizeDynamicConfigComplete() || !rangeFieldMeta) { return null; } @@ -108,7 +122,19 @@ export class DynamicSizeProperty extends DynamicStyleProperty { }); } - _getMbDataDrivenSize({ targetName, minSize, maxSize, minValue, maxValue }) { + _getMbDataDrivenSize({ + targetName, + minSize, + maxSize, + minValue, + maxValue, + }: { + targetName: string; + minSize: number; + maxSize: number; + minValue: number; + maxValue: number; + }) { const stops = minValue === maxValue ? [maxValue, maxSize] : [minValue, minSize, maxValue, maxSize]; return [ diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx index 39ceb580e92b9..47659e055936e 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx @@ -47,7 +47,7 @@ export interface IDynamicStyleProperty extends IStyleProperty { getValueSuggestions(query: string): Promise; } -type FieldFormatter = (value: string | number | undefined) => string | number; +export type FieldFormatter = (value: string | number | undefined) => string | number; export class DynamicStyleProperty extends AbstractStyleProperty implements IDynamicStyleProperty { diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_text_property.js b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_text_property.ts similarity index 80% rename from x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_text_property.js rename to x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_text_property.ts index a7a3130875a95..d55a6e1cfb444 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_text_property.js +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_text_property.ts @@ -4,11 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ +import { Map as MbMap } from 'mapbox-gl'; import { DynamicStyleProperty } from './dynamic_style_property'; import { getComputedFieldName } from '../style_util'; +import { LabelDynamicOptions } from '../../../../../common/descriptor_types'; -export class DynamicTextProperty extends DynamicStyleProperty { - syncTextFieldWithMb(mbLayerId, mbMap) { +export class DynamicTextProperty extends DynamicStyleProperty { + syncTextFieldWithMb(mbLayerId: string, mbMap: MbMap) { if (this._field && this._field.isValid()) { // Fields that support auto-domain are normalized with a field-formatter and stored into a computed-field // Otherwise, the raw value is just carried over and no computed field is created. diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/label_border_size_property.js b/x-pack/plugins/maps/public/classes/styles/vector/properties/label_border_size_property.ts similarity index 68% rename from x-pack/plugins/maps/public/classes/styles/vector/properties/label_border_size_property.js rename to x-pack/plugins/maps/public/classes/styles/vector/properties/label_border_size_property.ts index 3016b15d0a05c..bda7a4584370f 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/label_border_size_property.js +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/label_border_size_property.ts @@ -5,15 +5,20 @@ */ import _ from 'lodash'; +import { Map as MbMap } from 'mapbox-gl'; import { AbstractStyleProperty } from './style_property'; import { DEFAULT_LABEL_SIZE } from '../vector_style_defaults'; import { LABEL_BORDER_SIZES } from '../../../../../common/constants'; +import { LabelBorderSizeOptions } from '../../../../../common/descriptor_types'; +import { VECTOR_STYLES } from '../../../../../common/constants'; +import { StaticSizeProperty } from './static_size_property'; +import { DynamicSizeProperty } from './dynamic_size_property'; const SMALL_SIZE = 1 / 16; const MEDIUM_SIZE = 1 / 8; const LARGE_SIZE = 1 / 5; // halo of 1/4 is just a square. Use smaller ratio to preserve contour on letters -function getWidthRatio(size) { +function getWidthRatio(size: LABEL_BORDER_SIZES) { switch (size) { case LABEL_BORDER_SIZES.LARGE: return LARGE_SIZE; @@ -24,13 +29,19 @@ function getWidthRatio(size) { } } -export class LabelBorderSizeProperty extends AbstractStyleProperty { - constructor(options, styleName, labelSizeProperty) { +export class LabelBorderSizeProperty extends AbstractStyleProperty { + private readonly _labelSizeProperty: StaticSizeProperty | DynamicSizeProperty; + + constructor( + options: LabelBorderSizeOptions, + styleName: VECTOR_STYLES, + labelSizeProperty: StaticSizeProperty | DynamicSizeProperty + ) { super(options, styleName); this._labelSizeProperty = labelSizeProperty; } - syncLabelBorderSizeWithMb(mbLayerId, mbMap) { + syncLabelBorderSizeWithMb(mbLayerId: string, mbMap: MbMap) { if (this.getOptions().size === LABEL_BORDER_SIZES.NONE) { mbMap.setPaintProperty(mbLayerId, 'text-halo-width', 0); return; @@ -39,7 +50,8 @@ export class LabelBorderSizeProperty extends AbstractStyleProperty { const widthRatio = getWidthRatio(this.getOptions().size); if (this._labelSizeProperty.isDynamic() && this._labelSizeProperty.isComplete()) { - const labelSizeExpression = this._labelSizeProperty.getMbSizeExpression(); + const labelSizeExpression = (this + ._labelSizeProperty as DynamicSizeProperty).getMbSizeExpression(); if (labelSizeExpression) { mbMap.setPaintProperty(mbLayerId, 'text-halo-width', [ 'max', diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/static_color_property.js b/x-pack/plugins/maps/public/classes/styles/vector/properties/static_color_property.ts similarity index 63% rename from x-pack/plugins/maps/public/classes/styles/vector/properties/static_color_property.js rename to x-pack/plugins/maps/public/classes/styles/vector/properties/static_color_property.ts index ebe2a322711fc..45d25565b6f23 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/static_color_property.js +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/static_color_property.ts @@ -4,43 +4,45 @@ * you may not use this file except in compliance with the Elastic License. */ +import { Map as MbMap } from 'mapbox-gl'; import { StaticStyleProperty } from './static_style_property'; +import { ColorStaticOptions } from '../../../../../common/descriptor_types'; -export class StaticColorProperty extends StaticStyleProperty { - syncCircleColorWithMb(mbLayerId, mbMap, alpha) { +export class StaticColorProperty extends StaticStyleProperty { + syncCircleColorWithMb(mbLayerId: string, mbMap: MbMap, alpha: number) { mbMap.setPaintProperty(mbLayerId, 'circle-color', this._options.color); mbMap.setPaintProperty(mbLayerId, 'circle-opacity', alpha); } - syncFillColorWithMb(mbLayerId, mbMap, alpha) { + syncFillColorWithMb(mbLayerId: string, mbMap: MbMap, alpha: number) { mbMap.setPaintProperty(mbLayerId, 'fill-color', this._options.color); mbMap.setPaintProperty(mbLayerId, 'fill-opacity', alpha); } - syncIconColorWithMb(mbLayerId, mbMap) { + syncIconColorWithMb(mbLayerId: string, mbMap: MbMap) { mbMap.setPaintProperty(mbLayerId, 'icon-color', this._options.color); } - syncHaloBorderColorWithMb(mbLayerId, mbMap) { + syncHaloBorderColorWithMb(mbLayerId: string, mbMap: MbMap) { mbMap.setPaintProperty(mbLayerId, 'icon-halo-color', this._options.color); } - syncLineColorWithMb(mbLayerId, mbMap, alpha) { + syncLineColorWithMb(mbLayerId: string, mbMap: MbMap, alpha: number) { mbMap.setPaintProperty(mbLayerId, 'line-color', this._options.color); mbMap.setPaintProperty(mbLayerId, 'line-opacity', alpha); } - syncCircleStrokeWithMb(mbLayerId, mbMap, alpha) { + syncCircleStrokeWithMb(mbLayerId: string, mbMap: MbMap, alpha: number) { mbMap.setPaintProperty(mbLayerId, 'circle-stroke-color', this._options.color); mbMap.setPaintProperty(mbLayerId, 'circle-stroke-opacity', alpha); } - syncLabelColorWithMb(mbLayerId, mbMap, alpha) { + syncLabelColorWithMb(mbLayerId: string, mbMap: MbMap, alpha: number) { mbMap.setPaintProperty(mbLayerId, 'text-color', this._options.color); mbMap.setPaintProperty(mbLayerId, 'text-opacity', alpha); } - syncLabelBorderColorWithMb(mbLayerId, mbMap) { + syncLabelBorderColorWithMb(mbLayerId: string, mbMap: MbMap) { mbMap.setPaintProperty(mbLayerId, 'text-halo-color', this._options.color); } } diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/static_icon_property.js b/x-pack/plugins/maps/public/classes/styles/vector/properties/static_icon_property.ts similarity index 67% rename from x-pack/plugins/maps/public/classes/styles/vector/properties/static_icon_property.js rename to x-pack/plugins/maps/public/classes/styles/vector/properties/static_icon_property.ts index 3b5be083dd3c9..58c569e8132d6 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/static_icon_property.js +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/static_icon_property.ts @@ -4,11 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ +import { Map as MbMap } from 'mapbox-gl'; import { StaticStyleProperty } from './static_style_property'; +// @ts-expect-error import { getMakiSymbolAnchor, getMakiIconId } from '../symbol_utils'; +import { IconStaticOptions } from '../../../../../common/descriptor_types'; -export class StaticIconProperty extends StaticStyleProperty { - syncIconWithMb(symbolLayerId, mbMap, iconPixelSize) { +export class StaticIconProperty extends StaticStyleProperty { + syncIconWithMb(symbolLayerId: string, mbMap: MbMap, iconPixelSize: number) { const symbolId = this._options.value; mbMap.setLayoutProperty(symbolLayerId, 'icon-anchor', getMakiSymbolAnchor(symbolId)); mbMap.setLayoutProperty(symbolLayerId, 'icon-image', getMakiIconId(symbolId, iconPixelSize)); diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/static_orientation_property.js b/x-pack/plugins/maps/public/classes/styles/vector/properties/static_orientation_property.ts similarity index 62% rename from x-pack/plugins/maps/public/classes/styles/vector/properties/static_orientation_property.js rename to x-pack/plugins/maps/public/classes/styles/vector/properties/static_orientation_property.ts index 0c8cae10d6189..388cfbd645468 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/static_orientation_property.js +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/static_orientation_property.ts @@ -4,10 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ +import { Map as MbMap } from 'mapbox-gl'; import { StaticStyleProperty } from './static_style_property'; +import { VECTOR_STYLES } from '../../../../../common/constants'; +import { OrientationStaticOptions } from '../../../../../common/descriptor_types'; -export class StaticOrientationProperty extends StaticStyleProperty { - constructor(options, styleName) { +export class StaticOrientationProperty extends StaticStyleProperty { + constructor(options: OrientationStaticOptions, styleName: VECTOR_STYLES) { if (typeof options.orientation !== 'number') { super({ orientation: 0 }, styleName); } else { @@ -15,7 +18,7 @@ export class StaticOrientationProperty extends StaticStyleProperty { } } - syncIconRotationWithMb(symbolLayerId, mbMap) { + syncIconRotationWithMb(symbolLayerId: string, mbMap: MbMap) { mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', this._options.orientation); } } diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/static_size_property.js b/x-pack/plugins/maps/public/classes/styles/vector/properties/static_size_property.ts similarity index 65% rename from x-pack/plugins/maps/public/classes/styles/vector/properties/static_size_property.js rename to x-pack/plugins/maps/public/classes/styles/vector/properties/static_size_property.ts index d86556c6218cf..c9ee64ca56647 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/static_size_property.js +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/static_size_property.ts @@ -4,15 +4,19 @@ * you may not use this file except in compliance with the Elastic License. */ +import { Map as MbMap } from 'mapbox-gl'; import { StaticStyleProperty } from './static_style_property'; +import { VECTOR_STYLES } from '../../../../../common/constants'; import { HALF_LARGE_MAKI_ICON_SIZE, LARGE_MAKI_ICON_SIZE, SMALL_MAKI_ICON_SIZE, + // @ts-expect-error } from '../symbol_utils'; +import { SizeStaticOptions } from '../../../../../common/descriptor_types'; -export class StaticSizeProperty extends StaticStyleProperty { - constructor(options, styleName) { +export class StaticSizeProperty extends StaticStyleProperty { + constructor(options: SizeStaticOptions, styleName: VECTOR_STYLES) { if (typeof options.size !== 'number') { super({ size: 1 }, styleName); } else { @@ -20,7 +24,7 @@ export class StaticSizeProperty extends StaticStyleProperty { } } - syncHaloWidthWithMb(mbLayerId, mbMap) { + syncHaloWidthWithMb(mbLayerId: string, mbMap: MbMap) { mbMap.setPaintProperty(mbLayerId, 'icon-halo-width', this._options.size); } @@ -30,12 +34,12 @@ export class StaticSizeProperty extends StaticStyleProperty { : SMALL_MAKI_ICON_SIZE; } - syncIconSizeWithMb(symbolLayerId, mbMap) { + syncIconSizeWithMb(symbolLayerId: string, mbMap: MbMap) { const halfIconPixels = this.getIconPixelSize() / 2; mbMap.setLayoutProperty(symbolLayerId, 'icon-size', this._options.size / halfIconPixels); } - syncCircleStrokeWidthWithMb(mbLayerId, mbMap, hasNoRadius) { + syncCircleStrokeWidthWithMb(mbLayerId: string, mbMap: MbMap, hasNoRadius: boolean) { if (hasNoRadius) { mbMap.setPaintProperty(mbLayerId, 'circle-stroke-width', 0); } else { @@ -43,15 +47,15 @@ export class StaticSizeProperty extends StaticStyleProperty { } } - syncCircleRadiusWithMb(mbLayerId, mbMap) { + syncCircleRadiusWithMb(mbLayerId: string, mbMap: MbMap) { mbMap.setPaintProperty(mbLayerId, 'circle-radius', this._options.size); } - syncLineWidthWithMb(mbLayerId, mbMap) { + syncLineWidthWithMb(mbLayerId: string, mbMap: MbMap) { mbMap.setPaintProperty(mbLayerId, 'line-width', this._options.size); } - syncLabelSizeWithMb(mbLayerId, mbMap) { + syncLabelSizeWithMb(mbLayerId: string, mbMap: MbMap) { mbMap.setLayoutProperty(mbLayerId, 'text-size', this._options.size); } } diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/static_style_property.js b/x-pack/plugins/maps/public/classes/styles/vector/properties/static_style_property.ts similarity index 84% rename from x-pack/plugins/maps/public/classes/styles/vector/properties/static_style_property.js rename to x-pack/plugins/maps/public/classes/styles/vector/properties/static_style_property.ts index a02aa15e28b28..ea39f4fa06a78 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/static_style_property.js +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/static_style_property.ts @@ -7,6 +7,6 @@ import { AbstractStyleProperty } from './style_property'; import { STYLE_TYPE } from '../../../../../common/constants'; -export class StaticStyleProperty extends AbstractStyleProperty { +export class StaticStyleProperty extends AbstractStyleProperty { static type = STYLE_TYPE.STATIC; } diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/static_text_property.js b/x-pack/plugins/maps/public/classes/styles/vector/properties/static_text_property.ts similarity index 69% rename from x-pack/plugins/maps/public/classes/styles/vector/properties/static_text_property.js rename to x-pack/plugins/maps/public/classes/styles/vector/properties/static_text_property.ts index 7a4a4672152c0..e24e7553d0b38 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/static_text_property.js +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/static_text_property.ts @@ -4,14 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ +import { Map as MbMap } from 'mapbox-gl'; import { StaticStyleProperty } from './static_style_property'; +import { LabelStaticOptions } from '../../../../../common/descriptor_types'; -export class StaticTextProperty extends StaticStyleProperty { +export class StaticTextProperty extends StaticStyleProperty { isComplete() { return this.getOptions().value.length > 0; } - syncTextFieldWithMb(mbLayerId, mbMap) { + syncTextFieldWithMb(mbLayerId: string, mbMap: MbMap) { if (this.getOptions().value.length) { mbMap.setLayoutProperty(mbLayerId, 'text-field', this.getOptions().value); } else { diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/symbolize_as_property.js b/x-pack/plugins/maps/public/classes/styles/vector/properties/symbolize_as_property.ts similarity index 74% rename from x-pack/plugins/maps/public/classes/styles/vector/properties/symbolize_as_property.js rename to x-pack/plugins/maps/public/classes/styles/vector/properties/symbolize_as_property.ts index 9ae1ef5054e30..8bfc06a1c7fa9 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/symbolize_as_property.js +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/symbolize_as_property.ts @@ -6,12 +6,9 @@ import { AbstractStyleProperty } from './style_property'; import { SYMBOLIZE_AS_TYPES } from '../../../../../common/constants'; +import { SymbolizeAsOptions } from '../../../../../common/descriptor_types'; -export class SymbolizeAsProperty extends AbstractStyleProperty { - constructor(options, styleName) { - super(options, styleName); - } - +export class SymbolizeAsProperty extends AbstractStyleProperty { isSymbolizedAsIcon = () => { return this.getOptions().value === SYMBOLIZE_AS_TYPES.ICON; }; diff --git a/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/__snapshots__/toc_entry_actions_popover.test.tsx.snap b/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/__snapshots__/toc_entry_actions_popover.test.tsx.snap index 388712e1ebcca..8a5b7cf9186a8 100644 --- a/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/__snapshots__/toc_entry_actions_popover.test.tsx.snap +++ b/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/__snapshots__/toc_entry_actions_popover.test.tsx.snap @@ -82,7 +82,7 @@ exports[`TOCEntryActionsPopover is rendered 1`] = ` "data-test-subj": "layerVisibilityToggleButton", "icon": , "name": "Hide layer", "onClick": [Function], @@ -210,7 +210,7 @@ exports[`TOCEntryActionsPopover should disable fit to data when supportsFitToBou "data-test-subj": "layerVisibilityToggleButton", "icon": , "name": "Hide layer", "onClick": [Function], @@ -256,7 +256,7 @@ exports[`TOCEntryActionsPopover should disable fit to data when supportsFitToBou `; -exports[`TOCEntryActionsPopover should not show edit actions in read only mode 1`] = ` +exports[`TOCEntryActionsPopover should have "show layer" action when layer is not visible 1`] = ` , + "name": "Show layer", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "editLayerButton", + "disabled": false, + "icon": , + "name": "Edit layer", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "cloneLayerButton", + "icon": , + "name": "Clone layer", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "removeLayerButton", + "icon": , + "name": "Remove layer", + "onClick": [Function], + "toolTipContent": null, + }, + ], + "title": "Layer actions", + }, + ] + } + /> + +`; + +exports[`TOCEntryActionsPopover should not show edit actions in read only mode 1`] = ` + + simulated tooltip content at zoom: 0 +
+ + mockFootnoteIcon + + + simulated footnote at isUsingSearch: true +
+ + } + delay="regular" + position="top" + title="layer 1" + > + + + + mockIcon + + + layer 1 + + + + + mockFootnoteIcon + + + + + } + className="mapLayTocActions" + closePopover={[Function]} + display="inlineBlock" + hasArrow={true} + id="contextMenu" + isOpen={false} + ownFocus={false} + panelPaddingSize="none" + withTitle={true} +> + , + "name": "Fit to data", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "layerVisibilityToggleButton", + "icon": , "name": "Hide layer", "onClick": [Function], "toolTipContent": null, diff --git a/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.test.tsx b/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.test.tsx index c7ed5ec74ac7a..95f13574105b7 100644 --- a/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.test.tsx +++ b/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.test.tsx @@ -6,7 +6,7 @@ /* eslint-disable max-classes-per-file */ import React from 'react'; -import { shallowWithIntl } from 'test_utils/enzyme_helpers'; +import { shallow } from 'enzyme'; import { AbstractLayer, ILayer } from '../../../../../../classes/layers/layer'; import { AbstractSource, ISource } from '../../../../../../classes/sources/source'; import { AbstractStyle, IStyle } from '../../../../../../classes/styles/style'; @@ -76,7 +76,7 @@ describe('TOCEntryActionsPopover', () => { }); test('is rendered', async () => { - const component = shallowWithIntl(); + const component = shallow(); // Ensure all promises resolve await new Promise((resolve) => process.nextTick(resolve)); @@ -87,9 +87,7 @@ describe('TOCEntryActionsPopover', () => { }); test('should not show edit actions in read only mode', async () => { - const component = shallowWithIntl( - - ); + const component = shallow(); // Ensure all promises resolve await new Promise((resolve) => process.nextTick(resolve)); @@ -101,7 +99,22 @@ describe('TOCEntryActionsPopover', () => { test('should disable fit to data when supportsFitToBounds is false', async () => { supportsFitToBounds = false; - const component = shallowWithIntl(); + const component = shallow(); + + // Ensure all promises resolve + await new Promise((resolve) => process.nextTick(resolve)); + // Ensure the state changes are reflected + component.update(); + + expect(component).toMatchSnapshot(); + }); + + test('should have "show layer" action when layer is not visible', async () => { + const layer = new LayerMock(); + layer.isVisible = () => { + return false; + }; + const component = shallow(); // Ensure all promises resolve await new Promise((resolve) => process.nextTick(resolve)); diff --git a/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.tsx b/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.tsx index 5baac0a474ffa..a1b9026fc57da 100644 --- a/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.tsx +++ b/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.tsx @@ -158,7 +158,7 @@ export class TOCEntryActionsPopover extends Component { : i18n.translate('xpack.maps.layerTocActions.showLayerTitle', { defaultMessage: 'Show layer', }), - icon: , + icon: , 'data-test-subj': 'layerVisibilityToggleButton', toolTipContent: null, onClick: () => { diff --git a/x-pack/plugins/maps/public/routing/maps_router.js b/x-pack/plugins/maps/public/routing/maps_router.js index 30b2137399c1e..9992bd7a92ab1 100644 --- a/x-pack/plugins/maps/public/routing/maps_router.js +++ b/x-pack/plugins/maps/public/routing/maps_router.js @@ -7,8 +7,11 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { Router, Switch, Route, Redirect } from 'react-router-dom'; -import { getCoreI18n } from '../kibana_services'; -import { createKbnUrlStateStorage } from '../../../../../src/plugins/kibana_utils/public'; +import { getCoreI18n, getToasts } from '../kibana_services'; +import { + createKbnUrlStateStorage, + withNotifyOnErrors, +} from '../../../../../src/plugins/kibana_utils/public'; import { getStore } from './store_operations'; import { Provider } from 'react-redux'; import { LoadListAndRender } from './routes/list/load_list_and_render'; @@ -19,7 +22,11 @@ export let kbnUrlStateStorage; export async function renderApp(context, { appBasePath, element, history, onAppLeave }) { goToSpecifiedPath = (path) => history.push(path); - kbnUrlStateStorage = createKbnUrlStateStorage({ useHash: false, history }); + kbnUrlStateStorage = createKbnUrlStateStorage({ + useHash: false, + history, + ...withNotifyOnErrors(getToasts()), + }); render(, element); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/analytics_list.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/analytics_list.tsx index 90e24f6da5d0a..0652ec5f8acb1 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/analytics_list.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/analytics_list.tsx @@ -38,7 +38,10 @@ import { getTaskStateBadge, getJobTypeBadge, useColumns } from './use_columns'; import { ExpandedRow } from './expanded_row'; import { AnalyticStatsBarStats, StatsBar } from '../../../../../components/stats_bar'; import { CreateAnalyticsButton } from '../create_analytics_button'; -import { getSelectedJobIdFromUrl } from '../../../../../jobs/jobs_list/components/utils'; +import { + getSelectedIdFromUrl, + getGroupQueryText, +} from '../../../../../jobs/jobs_list/components/utils'; import { SourceSelection } from '../source_selection'; function getItemIdToExpandedRowMap( @@ -99,16 +102,22 @@ export const DataFrameAnalyticsList: FC = ({ // Query text/job_id based on url but only after getAnalytics is done first // selectedJobIdFromUrlInitialized makes sure the query is only run once since analytics is being refreshed constantly - const [selectedJobIdFromUrlInitialized, setSelectedJobIdFromUrlInitialized] = useState(false); + const [selectedIdFromUrlInitialized, setSelectedIdFromUrlInitialized] = useState(false); useEffect(() => { - if (selectedJobIdFromUrlInitialized === false && analytics.length > 0) { - const selectedJobIdFromUrl = getSelectedJobIdFromUrl(window.location.href); - if (selectedJobIdFromUrl !== undefined) { - setSelectedJobIdFromUrlInitialized(true); - setSearchQueryText(selectedJobIdFromUrl); + if (selectedIdFromUrlInitialized === false && analytics.length > 0) { + const { jobId, groupIds } = getSelectedIdFromUrl(window.location.href); + let queryText = ''; + + if (groupIds !== undefined) { + queryText = getGroupQueryText(groupIds); + } else if (jobId !== undefined) { + queryText = jobId; } + + setSelectedIdFromUrlInitialized(true); + setSearchQueryText(queryText); } - }, [selectedJobIdFromUrlInitialized, analytics]); + }, [selectedIdFromUrlInitialized, analytics]); // Subscribe to the refresh observable to trigger reloading the analytics list. useRefreshAnalyticsList({ diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/common.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/common.ts index cc52138d7c7b7..39489836773b3 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/common.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/common.ts @@ -35,6 +35,11 @@ interface ProgressSection { export interface DataFrameAnalyticsStats { assignment_explanation?: string; id: DataFrameAnalyticsId; + memory_usage?: { + timestamp?: string; + peak_usage_bytes: number; + status: string; + }; node?: { attributes: Record; ephemeral_id: string; @@ -121,6 +126,7 @@ export enum DataFrameAnalyticsListColumn { configCreateTime = 'config.create_time', description = 'config.description', id = 'id', + memoryStatus = 'stats.memory_usage.status', } export type ItemIdToExpandedRowMap = Record; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/use_columns.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/use_columns.tsx index 1b115496c2091..7001681b6917a 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/use_columns.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/use_columns.tsx @@ -19,7 +19,7 @@ import { EuiLink, RIGHT_ALIGNMENT, } from '@elastic/eui'; -import { getJobIdUrl } from '../../../../../util/get_job_id_url'; +import { getJobIdUrl, TAB_IDS } from '../../../../../util/get_selected_ids_url'; import { getAnalysisType, DataFrameAnalyticsId } from '../../../../common'; import { @@ -137,7 +137,7 @@ export const progressColumn = { }; export const getDFAnalyticsJobIdLink = (item: DataFrameAnalyticsListRow) => ( - {item.id} + {item.id} ); export const useColumns = ( @@ -213,6 +213,14 @@ export const useColumns = ( truncateText: true, 'data-test-subj': 'mlAnalyticsTableColumnJobDescription', }, + { + field: DataFrameAnalyticsListColumn.memoryStatus, + name: i18n.translate('xpack.ml.dataframe.analyticsList.memoryStatus', { + defaultMessage: 'Memory status', + }), + truncateText: true, + 'data-test-subj': 'mlAnalyticsTableColumnJobMemoryStatus', + }, { field: DataFrameAnalyticsListColumn.configSourceIndex, name: i18n.translate('xpack.ml.dataframe.analyticsList.sourceIndex', { diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/file_datavisualizer_view.js b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/file_datavisualizer_view.js index 7cb545cd5a776..56b81e36f1e92 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/file_datavisualizer_view.js +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/file_datavisualizer_view.js @@ -20,6 +20,7 @@ import { EditFlyout } from '../edit_flyout'; import { ExplanationFlyout } from '../explanation_flyout'; import { ImportView } from '../import_view'; import { + DEFAULT_LINES_TO_SAMPLE, getMaxBytes, readFile, createUrlOverrides, @@ -55,7 +56,9 @@ export class FileDataVisualizerView extends Component { this.overrides = {}; this.previousOverrides = {}; - this.originalSettings = {}; + this.originalSettings = { + linesToSample: DEFAULT_LINES_TO_SAMPLE, + }; this.maxFileUploadBytes = getMaxBytes(); } @@ -129,7 +132,7 @@ export class FileDataVisualizerView extends Component { const serverSettings = processResults(resp); const serverOverrides = resp.overrides; - this.previousOverrides = this.overrides; + this.previousOverrides = overrides; this.overrides = {}; if (serverSettings.format === 'xml') { @@ -185,9 +188,8 @@ export class FileDataVisualizerView extends Component { serverError: error, }); - // as long as the previous overrides are different to the current overrides, // reload the results with the previous overrides - if (overrides !== undefined && isEqual(this.previousOverrides, overrides) === false) { + if (isRetry === false) { this.setState({ loading: true, loaded: false, @@ -244,6 +246,11 @@ export class FileDataVisualizerView extends Component { }; onCancel = () => { + this.overrides = {}; + this.previousOverrides = {}; + this.originalSettings = { + linesToSample: DEFAULT_LINES_TO_SAMPLE, + }; this.changeMode(MODE.READ); this.onFilePickerChange([]); }; @@ -276,7 +283,7 @@ export class FileDataVisualizerView extends Component { return (
{mode === MODE.READ && ( - + <> {!loading && !loaded && } {loading && } @@ -286,10 +293,14 @@ export class FileDataVisualizerView extends Component { )} {fileCouldNotBeRead && loading === false && ( - - + <> + - + )} {loaded && ( @@ -298,8 +309,8 @@ export class FileDataVisualizerView extends Component { explanation={explanation} fileName={fileName} data={fileContents} - showEditFlyout={() => this.showEditFlyout()} - showExplanationFlyout={() => this.showExplanationFlyout()} + showEditFlyout={this.showEditFlyout} + showExplanationFlyout={this.showExplanationFlyout} disableButtons={isEditFlyoutVisible || isExplanationFlyoutVisible} /> )} @@ -317,19 +328,20 @@ export class FileDataVisualizerView extends Component { )} {bottomBarVisible && loaded && ( - + <> + + + )} - - - + )} {mode === MODE.IMPORT && ( - + <> {bottomBarVisible && ( - + <> + + + )} - - - + )}
); @@ -360,10 +373,10 @@ export class FileDataVisualizerView extends Component { function BottomPadding() { // padding for the BottomBar return ( - + <> - + ); } diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/file_error_callouts.tsx b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/file_error_callouts.tsx index 7333c96a0d8ea..d869676e48827 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/file_error_callouts.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/file_error_callouts.tsx @@ -7,7 +7,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import React, { FC } from 'react'; -import { EuiCallOut, EuiSpacer } from '@elastic/eui'; +import { EuiCallOut, EuiSpacer, EuiButtonEmpty, EuiHorizontalRule } from '@elastic/eui'; import numeral from '@elastic/numeral'; import { ErrorResponse } from '../../../../../../common/types/errors'; @@ -77,34 +77,57 @@ export const FileTooLarge: FC = ({ fileSize, maxFileSize }) = interface FileCouldNotBeReadProps { error: ErrorResponse; loaded: boolean; + showEditFlyout(): void; } -export const FileCouldNotBeRead: FC = ({ error, loaded }) => { +export const FileCouldNotBeRead: FC = ({ + error, + loaded, + showEditFlyout, +}) => { const message = error?.body?.message || ''; return ( - - } - color="danger" - iconType="cross" - data-test-subj="mlFileUploadErrorCallout fileCouldNotBeRead" - > - {message} - - {loaded && ( - <> - + <> + - - )} - + } + color="danger" + iconType="cross" + data-test-subj="mlFileUploadErrorCallout fileCouldNotBeRead" + > + {loaded === false && ( + <> + +
+ + + + + + )} + {message} + + {loaded && ( + <> + + + + )} +
+ ); }; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/index.ts b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/index.ts index 492a797f7a2f2..67d5b1176459b 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/index.ts +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/index.ts @@ -11,4 +11,5 @@ export { readFile, getMaxBytes, getMaxBytesFormatted, + DEFAULT_LINES_TO_SAMPLE, } from './utils'; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/utils.ts b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/utils.ts index 49ee5ec6b90b0..781f400180b10 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/utils.ts +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/utils.ts @@ -18,7 +18,7 @@ import { import { getUiSettings } from '../../../../util/dependency_cache'; import { FILE_DATA_VISUALIZER_MAX_FILE_SIZE } from '../../../../../../common/constants/settings'; -const DEFAULT_LINES_TO_SAMPLE = 1000; +export const DEFAULT_LINES_TO_SAMPLE = 1000; const UPLOAD_SIZE_MB = 5; const overrideDefaults = { diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_filter_bar/job_filter_bar.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_filter_bar/job_filter_bar.js index b274a8d572adb..6eb7b00e5620c 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_filter_bar/job_filter_bar.js +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_filter_bar/job_filter_bar.js @@ -9,7 +9,7 @@ import React, { Component, Fragment } from 'react'; import { ml } from '../../../../services/ml_api_service'; import { JobGroup } from '../job_group'; -import { getSelectedJobIdFromUrl, clearSelectedJobIdFromUrl } from '../utils'; +import { getGroupQueryText, getSelectedIdFromUrl, clearSelectedJobIdFromUrl } from '../utils'; import { EuiSearchBar, EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -54,15 +54,23 @@ export class JobFilterBar extends Component { componentDidMount() { // If job id is selected in url, filter table to that id - const selectedId = getSelectedJobIdFromUrl(window.location.href); - if (selectedId !== undefined) { + let defaultQueryText; + const { jobId, groupIds } = getSelectedIdFromUrl(window.location.href); + + if (groupIds !== undefined) { + defaultQueryText = getGroupQueryText(groupIds); + } else if (jobId !== undefined) { + defaultQueryText = jobId; + } + + if (defaultQueryText !== undefined) { this.setState( { - selectedId, + defaultQueryText, }, () => { // trigger onChange with query for job id to trigger table filter - const query = EuiSearchBar.Query.parse(selectedId); + const query = EuiSearchBar.Query.parse(defaultQueryText); this.onChange({ query }); } ); @@ -87,7 +95,7 @@ export class JobFilterBar extends Component { }; render() { - const { error, selectedId } = this.state; + const { error, defaultQueryText } = this.state; const filters = [ { type: 'field_value_toggle_group', @@ -147,7 +155,7 @@ export class JobFilterBar extends Component { return ( - {selectedId === undefined && ( + {defaultQueryText === undefined && ( )} - {selectedId !== undefined && ( + {defaultQueryText !== undefined && (
{job.description}   - {job.groups.map((group) => ( - - ))} + {job.groups.map((group) => { + if (isManagementTable === true) { + return ( + + + + ); + } + return ; + })}
); } JobDescription.propTypes = { job: PropTypes.object.isRequired, + isManagementTable: PropTypes.bool, }; diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js index 23b68551ca0f5..f90bbf3cf3fe6 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js @@ -14,7 +14,7 @@ import { toLocaleString } from '../../../../util/string_utils'; import { ResultLinks, actionsMenuContent } from '../job_actions'; import { JobDescription } from './job_description'; import { JobIcon } from '../../../../components/job_message_icon'; -import { getJobIdUrl } from '../../../../util/get_job_id_url'; +import { getJobIdUrl, TAB_IDS } from '../../../../util/get_selected_ids_url'; import { TIME_FORMAT } from '../../../../../../common/constants/time_format'; import { EuiBadge, EuiBasicTable, EuiButtonIcon, EuiLink, EuiScreenReaderOnly } from '@elastic/eui'; @@ -71,7 +71,7 @@ export class JobsList extends Component { return id; } - return {id}; + return {id}; } getPageOfJobs(index, size, sortField, sortDirection) { @@ -189,7 +189,9 @@ export class JobsList extends Component { sortable: true, field: 'description', 'data-test-subj': 'mlJobListColumnDescription', - render: (description, item) => , + render: (description, item) => ( + + ), textOnly: true, width: '20%', }, diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.d.ts b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.d.ts index 5f72d155cbd5a..cf4fad9513de5 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.d.ts +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.d.ts @@ -3,5 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -export function getSelectedJobIdFromUrl(str: string): string; + +export function getSelectedIdFromUrl(str: string): { groupIds?: string[]; jobId?: string }; +export function getGroupQueryText(arr: string[]): string; export function clearSelectedJobIdFromUrl(str: string): void; diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.js index 6fabd0299a936..913727bda67df 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.js +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.js @@ -370,21 +370,34 @@ function getUrlVars(url) { return vars; } -export function getSelectedJobIdFromUrl(url) { +export function getSelectedIdFromUrl(url) { + const result = {}; if (typeof url === 'string') { + const isGroup = url.includes('groupIds'); url = decodeURIComponent(url); - if (url.includes('mlManagement') && url.includes('jobId')) { + + if (url.includes('mlManagement')) { const urlParams = getUrlVars(url); const decodedJson = rison.decode(urlParams.mlManagement); - return decodedJson.jobId; + + if (isGroup) { + result.groupIds = decodedJson.groupIds; + } else { + result.jobId = decodedJson.jobId; + } } } + return result; +} + +export function getGroupQueryText(groupIds) { + return `groups:(${groupIds.join(' or ')})`; } export function clearSelectedJobIdFromUrl(url) { if (typeof url === 'string') { url = decodeURIComponent(url); - if (url.includes('mlManagement') && url.includes('jobId')) { + if (url.includes('mlManagement') && (url.includes('jobId') || url.includes('groupIds'))) { const urlParams = getUrlVars(url); const clearedParams = `ml#/jobs?_g=${urlParams._g}`; window.history.replaceState({}, document.title, clearedParams); diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.test.ts b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.test.ts new file mode 100644 index 0000000000000..e4c3c21c5a54a --- /dev/null +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.test.ts @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getGroupQueryText, getSelectedIdFromUrl } from './utils'; + +describe('ML - Jobs List utils', () => { + const jobId = 'test_job_id_1'; + const jobIdUrl = `http://localhost:5601/aql/app/ml#/jobs?mlManagement=(jobId:${jobId})`; + const groupIdOne = 'test_group_id_1'; + const groupIdTwo = 'test_group_id_2'; + const groupIdsUrl = `http://localhost:5601/aql/app/ml#/jobs?mlManagement=(groupIds:!(${groupIdOne},${groupIdTwo}))`; + const groupIdUrl = `http://localhost:5601/aql/app/ml#/jobs?mlManagement=(groupIds:!(${groupIdOne}))`; + + describe('getSelectedIdFromUrl', () => { + it('should get selected job id from the url', () => { + const actual = getSelectedIdFromUrl(jobIdUrl); + expect(actual).toStrictEqual({ jobId }); + }); + + it('should get selected group ids from the url', () => { + const expected = { groupIds: [groupIdOne, groupIdTwo] }; + const actual = getSelectedIdFromUrl(groupIdsUrl); + expect(actual).toStrictEqual(expected); + }); + + it('should get selected group id from the url', () => { + const expected = { groupIds: [groupIdOne] }; + const actual = getSelectedIdFromUrl(groupIdUrl); + expect(actual).toStrictEqual(expected); + }); + }); + + describe('getGroupQueryText', () => { + it('should get query string for selected group ids', () => { + const actual = getGroupQueryText([groupIdOne, groupIdTwo]); + expect(actual).toBe(`groups:(${groupIdOne} or ${groupIdTwo})`); + }); + + it('should get query string for selected group id', () => { + const actual = getGroupQueryText([groupIdOne]); + expect(actual).toBe(`groups:(${groupIdOne})`); + }); + }); +}); diff --git a/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx b/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx index 33bb78c51e013..0af6030df28b1 100644 --- a/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx +++ b/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx @@ -5,6 +5,7 @@ */ import React, { useEffect, useState, Fragment, FC } from 'react'; +import { Router } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { CoreStart } from 'kibana/public'; @@ -20,6 +21,8 @@ import { EuiTitle, } from '@elastic/eui'; +import { ManagementAppMountParams } from '../../../../../../../../../src/plugins/management/public/'; + import { checkGetManagementMlJobsResolver } from '../../../../capabilities/check_capabilities'; import { KibanaContextProvider } from '../../../../../../../../../src/plugins/kibana_react/public'; @@ -30,6 +33,7 @@ import { DataFrameAnalyticsList } from '../../../../data_frame_analytics/pages/a import { AccessDeniedPage } from '../access_denied_page'; interface Tab { + 'data-test-subj': string; id: string; name: string; content: any; @@ -38,6 +42,7 @@ interface Tab { function getTabs(isMlEnabledInSpace: boolean): Tab[] { return [ { + 'data-test-subj': 'mlStackManagementJobsListAnomalyDetectionTab', id: 'anomaly_detection_jobs', name: i18n.translate('xpack.ml.management.jobsList.anomalyDetectionTab', { defaultMessage: 'Anomaly detection', @@ -50,6 +55,7 @@ function getTabs(isMlEnabledInSpace: boolean): Tab[] { ), }, { + 'data-test-subj': 'mlStackManagementJobsListAnalyticsTab', id: 'analytics_jobs', name: i18n.translate('xpack.ml.management.jobsList.analyticsTab', { defaultMessage: 'Analytics', @@ -67,7 +73,10 @@ function getTabs(isMlEnabledInSpace: boolean): Tab[] { ]; } -export const JobsListPage: FC<{ coreStart: CoreStart }> = ({ coreStart }) => { +export const JobsListPage: FC<{ + coreStart: CoreStart; + history: ManagementAppMountParams['history']; +}> = ({ coreStart, history }) => { const [initialized, setInitialized] = useState(false); const [accessDenied, setAccessDenied] = useState(false); const [isMlEnabledInSpace, setIsMlEnabledInSpace] = useState(false); @@ -128,46 +137,51 @@ export const JobsListPage: FC<{ coreStart: CoreStart }> = ({ coreStart }) => { return ( - - - - -

- {i18n.translate('xpack.ml.management.jobsList.jobsListTitle', { - defaultMessage: 'Machine Learning Jobs', - })} -

-
- - - {currentTabId === 'anomaly_detection_jobs' - ? anomalyDetectionDocsLabel - : analyticsDocsLabel} - - -
-
- - - - {i18n.translate('xpack.ml.management.jobsList.jobsListTagline', { - defaultMessage: 'View machine learning analytics and anomaly detection jobs.', - })} - - - - {renderTabs()} -
+ + + + + +

+ {i18n.translate('xpack.ml.management.jobsList.jobsListTitle', { + defaultMessage: 'Machine Learning Jobs', + })} +

+
+ + + {currentTabId === 'anomaly_detection_jobs' + ? anomalyDetectionDocsLabel + : analyticsDocsLabel} + + +
+
+ + + + {i18n.translate('xpack.ml.management.jobsList.jobsListTagline', { + defaultMessage: 'View machine learning analytics and anomaly detection jobs.', + })} + + + + {renderTabs()} +
+
); diff --git a/x-pack/plugins/ml/public/application/management/jobs_list/index.ts b/x-pack/plugins/ml/public/application/management/jobs_list/index.ts index 81190a412abc0..afea5a573b8b5 100644 --- a/x-pack/plugins/ml/public/application/management/jobs_list/index.ts +++ b/x-pack/plugins/ml/public/application/management/jobs_list/index.ts @@ -14,8 +14,12 @@ import { getJobsListBreadcrumbs } from '../breadcrumbs'; import { setDependencyCache, clearCache } from '../../util/dependency_cache'; import './_index.scss'; -const renderApp = (element: HTMLElement, coreStart: CoreStart) => { - ReactDOM.render(React.createElement(JobsListPage, { coreStart }), element); +const renderApp = ( + element: HTMLElement, + history: ManagementAppMountParams['history'], + coreStart: CoreStart +) => { + ReactDOM.render(React.createElement(JobsListPage, { coreStart, history }), element); return () => { unmountComponentAtNode(element); clearCache(); @@ -37,5 +41,5 @@ export async function mountApp( params.setBreadcrumbs(getJobsListBreadcrumbs()); - return renderApp(params.element, coreStart); + return renderApp(params.element, params.history, coreStart); } diff --git a/x-pack/plugins/ml/public/application/util/get_job_id_url.ts b/x-pack/plugins/ml/public/application/util/get_job_id_url.ts deleted file mode 100644 index a6ca575f21b50..0000000000000 --- a/x-pack/plugins/ml/public/application/util/get_job_id_url.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import rison from 'rison-node'; - -import { getBasePath } from './dependency_cache'; - -export function getJobIdUrl(tabId: string, jobId: string): string { - // Create url for filtering by job id for kibana management table - const settings = { - jobId, - }; - const encoded = rison.encode(settings); - const url = `?mlManagement=${encoded}`; - const basePath = getBasePath(); - - return `${basePath.get()}/app/ml#/${tabId}${url}`; -} diff --git a/x-pack/plugins/ml/public/application/util/get_selected_ids_url.ts b/x-pack/plugins/ml/public/application/util/get_selected_ids_url.ts new file mode 100644 index 0000000000000..806626577008e --- /dev/null +++ b/x-pack/plugins/ml/public/application/util/get_selected_ids_url.ts @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import rison from 'rison-node'; +import { getBasePath } from './dependency_cache'; + +export enum TAB_IDS { + DATA_FRAME_ANALYTICS = 'data_frame_analytics', + ANOMALY_DETECTION = 'jobs', +} + +function getSelectedIdsUrl(tabId: TAB_IDS, settings: { [key: string]: string | string[] }): string { + // Create url for filtering by job id or group ids for kibana management table + const encoded = rison.encode(settings); + const url = `?mlManagement=${encoded}`; + const basePath = getBasePath(); + + return `${basePath.get()}/app/ml#/${tabId}${url}`; +} + +// Create url for filtering by group ids for kibana management table +export function getGroupIdsUrl(tabId: TAB_IDS, ids: string[]): string { + const settings = { + groupIds: ids, + }; + + return getSelectedIdsUrl(tabId, settings); +} + +// Create url for filtering by job id for kibana management table +export function getJobIdUrl(tabId: TAB_IDS, id: string): string { + const settings = { + jobId: id, + }; + + return getSelectedIdsUrl(tabId, settings); +} diff --git a/x-pack/plugins/ml/server/lib/license/ml_server_license.ts b/x-pack/plugins/ml/server/lib/license/ml_server_license.ts index 382e785b39ca3..bd0a29721248a 100644 --- a/x-pack/plugins/ml/server/lib/license/ml_server_license.ts +++ b/x-pack/plugins/ml/server/lib/license/ml_server_license.ts @@ -6,30 +6,47 @@ import { KibanaRequest, KibanaResponseFactory, - RequestHandler, RequestHandlerContext, + ILegacyScopedClusterClient, + IScopedClusterClient, + RequestHandler, } from 'kibana/server'; import { MlLicense } from '../../../common/license'; +type Handler = (handlerParams: { + legacyClient: ILegacyScopedClusterClient; + client: IScopedClusterClient; + request: KibanaRequest; + response: KibanaResponseFactory; + context: RequestHandlerContext; +}) => ReturnType; + export class MlServerLicense extends MlLicense { - public fullLicenseAPIGuard(handler: RequestHandler) { + public fullLicenseAPIGuard(handler: Handler) { return guard(() => this.isFullLicense(), handler); } - public basicLicenseAPIGuard(handler: RequestHandler) { + public basicLicenseAPIGuard(handler: Handler) { return guard(() => this.isMinimumLicense(), handler); } } -function guard(check: () => boolean, handler: RequestHandler) { +function guard(check: () => boolean, handler: Handler) { return ( context: RequestHandlerContext, - request: KibanaRequest, + request: KibanaRequest, response: KibanaResponseFactory ) => { if (check() === false) { return response.forbidden(); } - return handler(context, request, response); + + return handler({ + legacyClient: context.ml!.mlClient, + client: context.core.elasticsearch.client, + request, + response, + context, + }); }; } diff --git a/x-pack/plugins/ml/server/routes/annotations.ts b/x-pack/plugins/ml/server/routes/annotations.ts index 3e496eb31dcc5..a6de80bb7e5e2 100644 --- a/x-pack/plugins/ml/server/routes/annotations.ts +++ b/x-pack/plugins/ml/server/routes/annotations.ts @@ -58,9 +58,9 @@ export function annotationRoutes( tags: ['access:ml:canGetAnnotations'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const { getAnnotations } = annotationServiceProvider(context.ml!.mlClient); + const { getAnnotations } = annotationServiceProvider(legacyClient); const resp = await getAnnotations(request.body); return response.ok({ @@ -91,16 +91,14 @@ export function annotationRoutes( tags: ['access:ml:canCreateAnnotation'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const annotationsFeatureAvailable = await isAnnotationsFeatureAvailable( - context.ml!.mlClient - ); + const annotationsFeatureAvailable = await isAnnotationsFeatureAvailable(legacyClient); if (annotationsFeatureAvailable === false) { throw getAnnotationsFeatureUnavailableErrorMessage(); } - const { indexAnnotation } = annotationServiceProvider(context.ml!.mlClient); + const { indexAnnotation } = annotationServiceProvider(legacyClient); const currentUser = securityPlugin !== undefined ? securityPlugin.authc.getCurrentUser(request) : {}; @@ -136,17 +134,15 @@ export function annotationRoutes( tags: ['access:ml:canDeleteAnnotation'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const annotationsFeatureAvailable = await isAnnotationsFeatureAvailable( - context.ml!.mlClient - ); + const annotationsFeatureAvailable = await isAnnotationsFeatureAvailable(legacyClient); if (annotationsFeatureAvailable === false) { throw getAnnotationsFeatureUnavailableErrorMessage(); } const annotationId = request.params.annotationId; - const { deleteAnnotation } = annotationServiceProvider(context.ml!.mlClient); + const { deleteAnnotation } = annotationServiceProvider(legacyClient); const resp = await deleteAnnotation(annotationId); return response.ok({ diff --git a/x-pack/plugins/ml/server/routes/anomaly_detectors.ts b/x-pack/plugins/ml/server/routes/anomaly_detectors.ts index 8a59c174eb8e7..c6bdb32b262e4 100644 --- a/x-pack/plugins/ml/server/routes/anomaly_detectors.ts +++ b/x-pack/plugins/ml/server/routes/anomaly_detectors.ts @@ -43,9 +43,9 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, response }) => { try { - const results = await context.ml!.mlClient.callAsInternalUser('ml.jobs'); + const results = await legacyClient.callAsInternalUser('ml.jobs'); return response.ok({ body: results, }); @@ -74,10 +74,10 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { jobId } = request.params; - const results = await context.ml!.mlClient.callAsInternalUser('ml.jobs', { jobId }); + const results = await legacyClient.callAsInternalUser('ml.jobs', { jobId }); return response.ok({ body: results, }); @@ -105,9 +105,9 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, response }) => { try { - const results = await context.ml!.mlClient.callAsInternalUser('ml.jobStats'); + const results = await legacyClient.callAsInternalUser('ml.jobStats'); return response.ok({ body: results, }); @@ -136,10 +136,10 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { jobId } = request.params; - const results = await context.ml!.mlClient.callAsInternalUser('ml.jobStats', { jobId }); + const results = await legacyClient.callAsInternalUser('ml.jobStats', { jobId }); return response.ok({ body: results, }); @@ -172,10 +172,10 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canCreateJob'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { jobId } = request.params; - const results = await context.ml!.mlClient.callAsInternalUser('ml.addJob', { + const results = await legacyClient.callAsInternalUser('ml.addJob', { jobId, body: request.body, }); @@ -209,10 +209,10 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canUpdateJob'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { jobId } = request.params; - const results = await context.ml!.mlClient.callAsInternalUser('ml.updateJob', { + const results = await legacyClient.callAsInternalUser('ml.updateJob', { jobId, body: request.body, }); @@ -244,10 +244,10 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canOpenJob'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { jobId } = request.params; - const results = await context.ml!.mlClient.callAsInternalUser('ml.openJob', { + const results = await legacyClient.callAsInternalUser('ml.openJob', { jobId, }); return response.ok({ @@ -278,7 +278,7 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canCloseJob'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const options: { jobId: string; force?: boolean } = { jobId: request.params.jobId, @@ -287,7 +287,7 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { if (force !== undefined) { options.force = force; } - const results = await context.ml!.mlClient.callAsInternalUser('ml.closeJob', options); + const results = await legacyClient.callAsInternalUser('ml.closeJob', options); return response.ok({ body: results, }); @@ -316,7 +316,7 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canDeleteJob'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const options: { jobId: string; force?: boolean } = { jobId: request.params.jobId, @@ -325,7 +325,7 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { if (force !== undefined) { options.force = force; } - const results = await context.ml!.mlClient.callAsInternalUser('ml.deleteJob', options); + const results = await legacyClient.callAsInternalUser('ml.deleteJob', options); return response.ok({ body: results, }); @@ -352,9 +352,9 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canCreateJob'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const results = await context.ml!.mlClient.callAsInternalUser('ml.validateDetector', { + const results = await legacyClient.callAsInternalUser('ml.validateDetector', { body: request.body, }); return response.ok({ @@ -387,11 +387,11 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canForecastJob'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const jobId = request.params.jobId; const duration = request.body.duration; - const results = await context.ml!.mlClient.callAsInternalUser('ml.forecast', { + const results = await legacyClient.callAsInternalUser('ml.forecast', { jobId, duration, }); @@ -428,9 +428,9 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const results = await context.ml!.mlClient.callAsInternalUser('ml.records', { + const results = await legacyClient.callAsInternalUser('ml.records', { jobId: request.params.jobId, body: request.body, }); @@ -467,9 +467,9 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const results = await context.ml!.mlClient.callAsInternalUser('ml.buckets', { + const results = await legacyClient.callAsInternalUser('ml.buckets', { jobId: request.params.jobId, timestamp: request.params.timestamp, body: request.body, @@ -507,9 +507,9 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const results = await context.ml!.mlClient.callAsInternalUser('ml.overallBuckets', { + const results = await legacyClient.callAsInternalUser('ml.overallBuckets', { jobId: request.params.jobId, top_n: request.body.topN, bucket_span: request.body.bucketSpan, @@ -544,9 +544,9 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const results = await context.ml!.mlClient.callAsInternalUser('ml.categories', { + const results = await legacyClient.callAsInternalUser('ml.categories', { jobId: request.params.jobId, categoryId: request.params.categoryId, }); @@ -578,9 +578,9 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const results = await context.ml!.mlClient.callAsInternalUser('ml.modelSnapshots', { + const results = await legacyClient.callAsInternalUser('ml.modelSnapshots', { jobId: request.params.jobId, }); return response.ok({ @@ -611,9 +611,9 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const results = await context.ml!.mlClient.callAsInternalUser('ml.modelSnapshots', { + const results = await legacyClient.callAsInternalUser('ml.modelSnapshots', { jobId: request.params.jobId, snapshotId: request.params.snapshotId, }); @@ -647,9 +647,9 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canCreateJob'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const results = await context.ml!.mlClient.callAsInternalUser('ml.updateModelSnapshot', { + const results = await legacyClient.callAsInternalUser('ml.updateModelSnapshot', { jobId: request.params.jobId, snapshotId: request.params.snapshotId, body: request.body, @@ -682,9 +682,9 @@ export function jobRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canCreateJob'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const results = await context.ml!.mlClient.callAsInternalUser('ml.deleteModelSnapshot', { + const results = await legacyClient.callAsInternalUser('ml.deleteModelSnapshot', { jobId: request.params.jobId, snapshotId: request.params.snapshotId, }); diff --git a/x-pack/plugins/ml/server/routes/calendars.ts b/x-pack/plugins/ml/server/routes/calendars.ts index f5d129abd515e..3beb6e437b2ee 100644 --- a/x-pack/plugins/ml/server/routes/calendars.ts +++ b/x-pack/plugins/ml/server/routes/calendars.ts @@ -4,39 +4,43 @@ * you may not use this file except in compliance with the Elastic License. */ -import { RequestHandlerContext } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { wrapError } from '../client/error_wrapper'; import { RouteInitialization } from '../types'; import { calendarSchema, calendarIdSchema, calendarIdsSchema } from './schemas/calendars_schema'; import { CalendarManager, Calendar, FormCalendar } from '../models/calendar'; -function getAllCalendars(context: RequestHandlerContext) { - const cal = new CalendarManager(context.ml!.mlClient); +function getAllCalendars(legacyClient: ILegacyScopedClusterClient) { + const cal = new CalendarManager(legacyClient); return cal.getAllCalendars(); } -function getCalendar(context: RequestHandlerContext, calendarId: string) { - const cal = new CalendarManager(context.ml!.mlClient); +function getCalendar(legacyClient: ILegacyScopedClusterClient, calendarId: string) { + const cal = new CalendarManager(legacyClient); return cal.getCalendar(calendarId); } -function newCalendar(context: RequestHandlerContext, calendar: FormCalendar) { - const cal = new CalendarManager(context.ml!.mlClient); +function newCalendar(legacyClient: ILegacyScopedClusterClient, calendar: FormCalendar) { + const cal = new CalendarManager(legacyClient); return cal.newCalendar(calendar); } -function updateCalendar(context: RequestHandlerContext, calendarId: string, calendar: Calendar) { - const cal = new CalendarManager(context.ml!.mlClient); +function updateCalendar( + legacyClient: ILegacyScopedClusterClient, + calendarId: string, + calendar: Calendar +) { + const cal = new CalendarManager(legacyClient); return cal.updateCalendar(calendarId, calendar); } -function deleteCalendar(context: RequestHandlerContext, calendarId: string) { - const cal = new CalendarManager(context.ml!.mlClient); +function deleteCalendar(legacyClient: ILegacyScopedClusterClient, calendarId: string) { + const cal = new CalendarManager(legacyClient); return cal.deleteCalendar(calendarId); } -function getCalendarsByIds(context: RequestHandlerContext, calendarIds: string) { - const cal = new CalendarManager(context.ml!.mlClient); +function getCalendarsByIds(legacyClient: ILegacyScopedClusterClient, calendarIds: string) { + const cal = new CalendarManager(legacyClient); return cal.getCalendarsByIds(calendarIds); } @@ -56,9 +60,9 @@ export function calendars({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetCalendars'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, response }) => { try { - const resp = await getAllCalendars(context); + const resp = await getAllCalendars(legacyClient); return response.ok({ body: resp, @@ -88,15 +92,15 @@ export function calendars({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetCalendars'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { let returnValue; try { const calendarIds = request.params.calendarIds.split(','); if (calendarIds.length === 1) { - returnValue = await getCalendar(context, calendarIds[0]); + returnValue = await getCalendar(legacyClient, calendarIds[0]); } else { - returnValue = await getCalendarsByIds(context, calendarIds); + returnValue = await getCalendarsByIds(legacyClient, calendarIds); } return response.ok({ @@ -127,10 +131,10 @@ export function calendars({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canCreateCalendar'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const body = request.body; - const resp = await newCalendar(context, body); + const resp = await newCalendar(legacyClient, body); return response.ok({ body: resp, @@ -162,11 +166,11 @@ export function calendars({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canCreateCalendar'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { calendarId } = request.params; const body = request.body; - const resp = await updateCalendar(context, calendarId, body); + const resp = await updateCalendar(legacyClient, calendarId, body); return response.ok({ body: resp, @@ -196,10 +200,10 @@ export function calendars({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canDeleteCalendar'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { calendarId } = request.params; - const resp = await deleteCalendar(context, calendarId); + const resp = await deleteCalendar(legacyClient, calendarId); return response.ok({ body: resp, diff --git a/x-pack/plugins/ml/server/routes/data_frame_analytics.ts b/x-pack/plugins/ml/server/routes/data_frame_analytics.ts index 94feb21a6b5fb..3b964588bef19 100644 --- a/x-pack/plugins/ml/server/routes/data_frame_analytics.ts +++ b/x-pack/plugins/ml/server/routes/data_frame_analytics.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { RequestHandlerContext } from 'kibana/server'; +import { RequestHandlerContext, ILegacyScopedClusterClient } from 'kibana/server'; import { wrapError } from '../client/error_wrapper'; import { analyticsAuditMessagesProvider } from '../models/data_frame_analytics/analytics_audit_messages'; import { RouteInitialization } from '../types'; @@ -36,13 +36,13 @@ function deleteDestIndexPatternById(context: RequestHandlerContext, indexPattern */ export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitialization) { async function userCanDeleteIndex( - context: RequestHandlerContext, + legacyClient: ILegacyScopedClusterClient, destinationIndex: string ): Promise { if (!mlLicense.isSecurityEnabled()) { return true; } - const privilege = await context.ml!.mlClient.callAsCurrentUser('ml.privilegeCheck', { + const privilege = await legacyClient.callAsCurrentUser('ml.privilegeCheck', { body: { index: [ { @@ -76,9 +76,9 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitializat tags: ['access:ml:canGetDataFrameAnalytics'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, response }) => { try { - const results = await context.ml!.mlClient.callAsInternalUser('ml.getDataFrameAnalytics'); + const results = await legacyClient.callAsInternalUser('ml.getDataFrameAnalytics'); return response.ok({ body: results, }); @@ -107,10 +107,10 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitializat tags: ['access:ml:canGetDataFrameAnalytics'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { analyticsId } = request.params; - const results = await context.ml!.mlClient.callAsInternalUser('ml.getDataFrameAnalytics', { + const results = await legacyClient.callAsInternalUser('ml.getDataFrameAnalytics', { analyticsId, }); return response.ok({ @@ -137,11 +137,9 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitializat tags: ['access:ml:canGetDataFrameAnalytics'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const results = await context.ml!.mlClient.callAsInternalUser( - 'ml.getDataFrameAnalyticsStats' - ); + const results = await legacyClient.callAsInternalUser('ml.getDataFrameAnalyticsStats'); return response.ok({ body: results, }); @@ -170,15 +168,12 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitializat tags: ['access:ml:canGetDataFrameAnalytics'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { analyticsId } = request.params; - const results = await context.ml!.mlClient.callAsInternalUser( - 'ml.getDataFrameAnalyticsStats', - { - analyticsId, - } - ); + const results = await legacyClient.callAsInternalUser('ml.getDataFrameAnalyticsStats', { + analyticsId, + }); return response.ok({ body: results, }); @@ -210,17 +205,14 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitializat tags: ['access:ml:canCreateDataFrameAnalytics'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { analyticsId } = request.params; - const results = await context.ml!.mlClient.callAsInternalUser( - 'ml.createDataFrameAnalytics', - { - body: request.body, - analyticsId, - ...getAuthorizationHeader(request), - } - ); + const results = await legacyClient.callAsInternalUser('ml.createDataFrameAnalytics', { + body: request.body, + analyticsId, + ...getAuthorizationHeader(request), + }); return response.ok({ body: results, }); @@ -249,15 +241,12 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitializat tags: ['access:ml:canGetDataFrameAnalytics'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const results = await context.ml!.mlClient.callAsInternalUser( - 'ml.evaluateDataFrameAnalytics', - { - body: request.body, - ...getAuthorizationHeader(request), - } - ); + const results = await legacyClient.callAsInternalUser('ml.evaluateDataFrameAnalytics', { + body: request.body, + ...getAuthorizationHeader(request), + }); return response.ok({ body: results, }); @@ -287,14 +276,11 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitializat tags: ['access:ml:canCreateDataFrameAnalytics'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const results = await context.ml!.mlClient.callAsInternalUser( - 'ml.explainDataFrameAnalytics', - { - body: request.body, - } - ); + const results = await legacyClient.callAsInternalUser('ml.explainDataFrameAnalytics', { + body: request.body, + }); return response.ok({ body: results, }); @@ -324,7 +310,7 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitializat tags: ['access:ml:canDeleteDataFrameAnalytics'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response, context }) => { try { const { analyticsId } = request.params; const { deleteDestIndex, deleteDestIndexPattern } = request.query; @@ -338,7 +324,7 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitializat // Check if analyticsId is valid and get destination index if (deleteDestIndex || deleteDestIndexPattern) { try { - const dfa = await context.ml!.mlClient.callAsInternalUser('ml.getDataFrameAnalytics', { + const dfa = await legacyClient.callAsInternalUser('ml.getDataFrameAnalytics', { analyticsId, }); if (Array.isArray(dfa.data_frame_analytics) && dfa.data_frame_analytics.length > 0) { @@ -351,11 +337,11 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitializat // If user checks box to delete the destinationIndex associated with the job if (destinationIndex && deleteDestIndex) { // Verify if user has privilege to delete the destination index - const userCanDeleteDestIndex = await userCanDeleteIndex(context, destinationIndex); + const userCanDeleteDestIndex = await userCanDeleteIndex(legacyClient, destinationIndex); // If user does have privilege to delete the index, then delete the index if (userCanDeleteDestIndex) { try { - await context.ml!.mlClient.callAsCurrentUser('indices.delete', { + await legacyClient.callAsCurrentUser('indices.delete', { index: destinationIndex, }); destIndexDeleted.success = true; @@ -384,7 +370,7 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitializat // Delete the data frame analytics try { - await context.ml!.mlClient.callAsInternalUser('ml.deleteDataFrameAnalytics', { + await legacyClient.callAsInternalUser('ml.deleteDataFrameAnalytics', { analyticsId, }); analyticsJobDeleted.success = true; @@ -427,15 +413,12 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitializat tags: ['access:ml:canStartStopDataFrameAnalytics'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { analyticsId } = request.params; - const results = await context.ml!.mlClient.callAsInternalUser( - 'ml.startDataFrameAnalytics', - { - analyticsId, - } - ); + const results = await legacyClient.callAsInternalUser('ml.startDataFrameAnalytics', { + analyticsId, + }); return response.ok({ body: results, }); @@ -466,7 +449,7 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitializat tags: ['access:ml:canStartStopDataFrameAnalytics'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const options: { analyticsId: string; force?: boolean | undefined } = { analyticsId: request.params.analyticsId, @@ -477,10 +460,7 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitializat options.force = request.url.query.force; } - const results = await context.ml!.mlClient.callAsInternalUser( - 'ml.stopDataFrameAnalytics', - options - ); + const results = await legacyClient.callAsInternalUser('ml.stopDataFrameAnalytics', options); return response.ok({ body: results, }); @@ -510,16 +490,13 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitializat tags: ['access:ml:canCreateDataFrameAnalytics'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { analyticsId } = request.params; - const results = await context.ml!.mlClient.callAsInternalUser( - 'ml.updateDataFrameAnalytics', - { - body: request.body, - analyticsId, - } - ); + const results = await legacyClient.callAsInternalUser('ml.updateDataFrameAnalytics', { + body: request.body, + analyticsId, + }); return response.ok({ body: results, }); @@ -548,10 +525,10 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitializat tags: ['access:ml:canGetDataFrameAnalytics'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { analyticsId } = request.params; - const { getAnalyticsAuditMessages } = analyticsAuditMessagesProvider(context.ml!.mlClient); + const { getAnalyticsAuditMessages } = analyticsAuditMessagesProvider(legacyClient); const results = await getAnalyticsAuditMessages(analyticsId); return response.ok({ diff --git a/x-pack/plugins/ml/server/routes/data_visualizer.ts b/x-pack/plugins/ml/server/routes/data_visualizer.ts index 818e981835ced..6355285127f06 100644 --- a/x-pack/plugins/ml/server/routes/data_visualizer.ts +++ b/x-pack/plugins/ml/server/routes/data_visualizer.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { RequestHandlerContext } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { wrapError } from '../client/error_wrapper'; import { DataVisualizer } from '../models/data_visualizer'; import { Field, HistogramField } from '../models/data_visualizer/data_visualizer'; @@ -17,7 +17,7 @@ import { import { RouteInitialization } from '../types'; function getOverallStats( - context: RequestHandlerContext, + legacyClient: ILegacyScopedClusterClient, indexPatternTitle: string, query: object, aggregatableFields: string[], @@ -27,7 +27,7 @@ function getOverallStats( earliestMs: number, latestMs: number ) { - const dv = new DataVisualizer(context.ml!.mlClient); + const dv = new DataVisualizer(legacyClient); return dv.getOverallStats( indexPatternTitle, query, @@ -41,7 +41,7 @@ function getOverallStats( } function getStatsForFields( - context: RequestHandlerContext, + legacyClient: ILegacyScopedClusterClient, indexPatternTitle: string, query: any, fields: Field[], @@ -52,7 +52,7 @@ function getStatsForFields( interval: number, maxExamples: number ) { - const dv = new DataVisualizer(context.ml!.mlClient); + const dv = new DataVisualizer(legacyClient); return dv.getStatsForFields( indexPatternTitle, query, @@ -67,13 +67,13 @@ function getStatsForFields( } function getHistogramsForFields( - context: RequestHandlerContext, + legacyClient: ILegacyScopedClusterClient, indexPatternTitle: string, query: any, fields: HistogramField[], samplerShardSize: number ) { - const dv = new DataVisualizer(context.ml!.mlClient); + const dv = new DataVisualizer(legacyClient); return dv.getHistogramsForFields(indexPatternTitle, query, fields, samplerShardSize); } @@ -104,7 +104,7 @@ export function dataVisualizerRoutes({ router, mlLicense }: RouteInitialization) tags: ['access:ml:canAccessML'], }, }, - mlLicense.basicLicenseAPIGuard(async (context, request, response) => { + mlLicense.basicLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { params: { indexPatternTitle }, @@ -112,7 +112,7 @@ export function dataVisualizerRoutes({ router, mlLicense }: RouteInitialization) } = request; const results = await getHistogramsForFields( - context, + legacyClient, indexPatternTitle, query, fields, @@ -151,7 +151,7 @@ export function dataVisualizerRoutes({ router, mlLicense }: RouteInitialization) tags: ['access:ml:canAccessML'], }, }, - mlLicense.basicLicenseAPIGuard(async (context, request, response) => { + mlLicense.basicLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { params: { indexPatternTitle }, @@ -168,7 +168,7 @@ export function dataVisualizerRoutes({ router, mlLicense }: RouteInitialization) } = request; const results = await getStatsForFields( - context, + legacyClient, indexPatternTitle, query, fields, @@ -216,7 +216,7 @@ export function dataVisualizerRoutes({ router, mlLicense }: RouteInitialization) tags: ['access:ml:canAccessML'], }, }, - mlLicense.basicLicenseAPIGuard(async (context, request, response) => { + mlLicense.basicLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { params: { indexPatternTitle }, @@ -232,7 +232,7 @@ export function dataVisualizerRoutes({ router, mlLicense }: RouteInitialization) } = request; const results = await getOverallStats( - context, + legacyClient, indexPatternTitle, query, aggregatableFields, diff --git a/x-pack/plugins/ml/server/routes/datafeeds.ts b/x-pack/plugins/ml/server/routes/datafeeds.ts index 855b64b0ffed0..47a9afc2244d9 100644 --- a/x-pack/plugins/ml/server/routes/datafeeds.ts +++ b/x-pack/plugins/ml/server/routes/datafeeds.ts @@ -33,9 +33,9 @@ export function dataFeedRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetDatafeeds'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const resp = await context.ml!.mlClient.callAsInternalUser('ml.datafeeds'); + const resp = await legacyClient.callAsInternalUser('ml.datafeeds'); return response.ok({ body: resp, @@ -65,10 +65,10 @@ export function dataFeedRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetDatafeeds'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const datafeedId = request.params.datafeedId; - const resp = await context.ml!.mlClient.callAsInternalUser('ml.datafeeds', { datafeedId }); + const resp = await legacyClient.callAsInternalUser('ml.datafeeds', { datafeedId }); return response.ok({ body: resp, @@ -94,9 +94,9 @@ export function dataFeedRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetDatafeeds'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const resp = await context.ml!.mlClient.callAsInternalUser('ml.datafeedStats'); + const resp = await legacyClient.callAsInternalUser('ml.datafeedStats'); return response.ok({ body: resp, @@ -126,10 +126,10 @@ export function dataFeedRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetDatafeeds'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const datafeedId = request.params.datafeedId; - const resp = await context.ml!.mlClient.callAsInternalUser('ml.datafeedStats', { + const resp = await legacyClient.callAsInternalUser('ml.datafeedStats', { datafeedId, }); @@ -163,10 +163,10 @@ export function dataFeedRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canCreateDatafeed'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const datafeedId = request.params.datafeedId; - const resp = await context.ml!.mlClient.callAsInternalUser('ml.addDatafeed', { + const resp = await legacyClient.callAsInternalUser('ml.addDatafeed', { datafeedId, body: request.body, ...getAuthorizationHeader(request), @@ -202,10 +202,10 @@ export function dataFeedRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canUpdateDatafeed'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const datafeedId = request.params.datafeedId; - const resp = await context.ml!.mlClient.callAsInternalUser('ml.updateDatafeed', { + const resp = await legacyClient.callAsInternalUser('ml.updateDatafeed', { datafeedId, body: request.body, ...getAuthorizationHeader(request), @@ -241,7 +241,7 @@ export function dataFeedRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canDeleteDatafeed'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const options: { datafeedId: string; force?: boolean } = { datafeedId: request.params.jobId, @@ -251,7 +251,7 @@ export function dataFeedRoutes({ router, mlLicense }: RouteInitialization) { options.force = force; } - const resp = await context.ml!.mlClient.callAsInternalUser('ml.deleteDatafeed', options); + const resp = await legacyClient.callAsInternalUser('ml.deleteDatafeed', options); return response.ok({ body: resp, @@ -283,12 +283,12 @@ export function dataFeedRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canStartStopDatafeed'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const datafeedId = request.params.datafeedId; const { start, end } = request.body; - const resp = await context.ml!.mlClient.callAsInternalUser('ml.startDatafeed', { + const resp = await legacyClient.callAsInternalUser('ml.startDatafeed', { datafeedId, start, end, @@ -322,11 +322,11 @@ export function dataFeedRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canStartStopDatafeed'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const datafeedId = request.params.datafeedId; - const resp = await context.ml!.mlClient.callAsInternalUser('ml.stopDatafeed', { + const resp = await legacyClient.callAsInternalUser('ml.stopDatafeed', { datafeedId, }); @@ -358,10 +358,10 @@ export function dataFeedRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canPreviewDatafeed'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const datafeedId = request.params.datafeedId; - const resp = await context.ml!.mlClient.callAsInternalUser('ml.datafeedPreview', { + const resp = await legacyClient.callAsInternalUser('ml.datafeedPreview', { datafeedId, ...getAuthorizationHeader(request), }); diff --git a/x-pack/plugins/ml/server/routes/fields_service.ts b/x-pack/plugins/ml/server/routes/fields_service.ts index b83f846b1685d..0595b31d5bbbc 100644 --- a/x-pack/plugins/ml/server/routes/fields_service.ts +++ b/x-pack/plugins/ml/server/routes/fields_service.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { RequestHandlerContext } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { wrapError } from '../client/error_wrapper'; import { RouteInitialization } from '../types'; import { @@ -13,14 +13,14 @@ import { } from './schemas/fields_service_schema'; import { fieldsServiceProvider } from '../models/fields_service'; -function getCardinalityOfFields(context: RequestHandlerContext, payload: any) { - const fs = fieldsServiceProvider(context.ml!.mlClient); +function getCardinalityOfFields(legacyClient: ILegacyScopedClusterClient, payload: any) { + const fs = fieldsServiceProvider(legacyClient); const { index, fieldNames, query, timeFieldName, earliestMs, latestMs } = payload; return fs.getCardinalityOfFields(index, fieldNames, query, timeFieldName, earliestMs, latestMs); } -function getTimeFieldRange(context: RequestHandlerContext, payload: any) { - const fs = fieldsServiceProvider(context.ml!.mlClient); +function getTimeFieldRange(legacyClient: ILegacyScopedClusterClient, payload: any) { + const fs = fieldsServiceProvider(legacyClient); const { index, timeFieldName, query } = payload; return fs.getTimeFieldRange(index, timeFieldName, query); } @@ -50,9 +50,9 @@ export function fieldsService({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canAccessML'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const resp = await getCardinalityOfFields(context, request.body); + const resp = await getCardinalityOfFields(legacyClient, request.body); return response.ok({ body: resp, @@ -85,9 +85,9 @@ export function fieldsService({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canAccessML'], }, }, - mlLicense.basicLicenseAPIGuard(async (context, request, response) => { + mlLicense.basicLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const resp = await getTimeFieldRange(context, request.body); + const resp = await getTimeFieldRange(legacyClient, request.body); return response.ok({ body: resp, diff --git a/x-pack/plugins/ml/server/routes/file_data_visualizer.ts b/x-pack/plugins/ml/server/routes/file_data_visualizer.ts index b57eda5ad56a1..88949fecbc7df 100644 --- a/x-pack/plugins/ml/server/routes/file_data_visualizer.ts +++ b/x-pack/plugins/ml/server/routes/file_data_visualizer.ts @@ -5,7 +5,7 @@ */ import { schema } from '@kbn/config-schema'; -import { RequestHandlerContext } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { MAX_FILE_SIZE_BYTES } from '../../common/constants/file_datavisualizer'; import { InputOverrides, @@ -28,13 +28,17 @@ import { importFileQuerySchema, } from './schemas/file_data_visualizer_schema'; -function analyzeFiles(context: RequestHandlerContext, data: InputData, overrides: InputOverrides) { - const { analyzeFile } = fileDataVisualizerProvider(context.ml!.mlClient); +function analyzeFiles( + legacyClient: ILegacyScopedClusterClient, + data: InputData, + overrides: InputOverrides +) { + const { analyzeFile } = fileDataVisualizerProvider(legacyClient); return analyzeFile(data, overrides); } function importData( - context: RequestHandlerContext, + legacyClient: ILegacyScopedClusterClient, id: string, index: string, settings: Settings, @@ -42,7 +46,7 @@ function importData( ingestPipeline: IngestPipelineWrapper, data: InputData ) { - const { importData: importDataFunc } = importDataProvider(context.ml!.mlClient); + const { importData: importDataFunc } = importDataProvider(legacyClient); return importDataFunc(id, index, settings, mappings, ingestPipeline, data); } @@ -74,9 +78,9 @@ export function fileDataVisualizerRoutes({ router, mlLicense }: RouteInitializat tags: ['access:ml:canFindFileStructure'], }, }, - mlLicense.basicLicenseAPIGuard(async (context, request, response) => { + mlLicense.basicLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const result = await analyzeFiles(context, request.body, request.query); + const result = await analyzeFiles(legacyClient, request.body, request.query); return response.ok({ body: result }); } catch (e) { return response.customError(wrapError(e)); @@ -109,7 +113,7 @@ export function fileDataVisualizerRoutes({ router, mlLicense }: RouteInitializat tags: ['access:ml:canFindFileStructure'], }, }, - mlLicense.basicLicenseAPIGuard(async (context, request, response) => { + mlLicense.basicLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { id } = request.query; const { index, data, settings, mappings, ingestPipeline } = request.body; @@ -122,7 +126,7 @@ export function fileDataVisualizerRoutes({ router, mlLicense }: RouteInitializat } const result = await importData( - context, + legacyClient, id, index, settings, diff --git a/x-pack/plugins/ml/server/routes/filters.ts b/x-pack/plugins/ml/server/routes/filters.ts index dcdb4caa6cd3b..bb4f8a2bebaa9 100644 --- a/x-pack/plugins/ml/server/routes/filters.ts +++ b/x-pack/plugins/ml/server/routes/filters.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { RequestHandlerContext } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { wrapError } from '../client/error_wrapper'; import { RouteInitialization } from '../types'; import { createFilterSchema, filterIdSchema, updateFilterSchema } from './schemas/filters_schema'; @@ -12,33 +12,37 @@ import { FilterManager, FormFilter } from '../models/filter'; // TODO - add function for returning a list of just the filter IDs. // TODO - add function for returning a list of filter IDs plus item count. -function getAllFilters(context: RequestHandlerContext) { - const mgr = new FilterManager(context.ml!.mlClient); +function getAllFilters(legacyClient: ILegacyScopedClusterClient) { + const mgr = new FilterManager(legacyClient); return mgr.getAllFilters(); } -function getAllFilterStats(context: RequestHandlerContext) { - const mgr = new FilterManager(context.ml!.mlClient); +function getAllFilterStats(legacyClient: ILegacyScopedClusterClient) { + const mgr = new FilterManager(legacyClient); return mgr.getAllFilterStats(); } -function getFilter(context: RequestHandlerContext, filterId: string) { - const mgr = new FilterManager(context.ml!.mlClient); +function getFilter(legacyClient: ILegacyScopedClusterClient, filterId: string) { + const mgr = new FilterManager(legacyClient); return mgr.getFilter(filterId); } -function newFilter(context: RequestHandlerContext, filter: FormFilter) { - const mgr = new FilterManager(context.ml!.mlClient); +function newFilter(legacyClient: ILegacyScopedClusterClient, filter: FormFilter) { + const mgr = new FilterManager(legacyClient); return mgr.newFilter(filter); } -function updateFilter(context: RequestHandlerContext, filterId: string, filter: FormFilter) { - const mgr = new FilterManager(context.ml!.mlClient); +function updateFilter( + legacyClient: ILegacyScopedClusterClient, + filterId: string, + filter: FormFilter +) { + const mgr = new FilterManager(legacyClient); return mgr.updateFilter(filterId, filter); } -function deleteFilter(context: RequestHandlerContext, filterId: string) { - const mgr = new FilterManager(context.ml!.mlClient); +function deleteFilter(legacyClient: ILegacyScopedClusterClient, filterId: string) { + const mgr = new FilterManager(legacyClient); return mgr.deleteFilter(filterId); } @@ -61,9 +65,9 @@ export function filtersRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetFilters'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, response }) => { try { - const resp = await getAllFilters(context); + const resp = await getAllFilters(legacyClient); return response.ok({ body: resp, @@ -96,9 +100,9 @@ export function filtersRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetFilters'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const resp = await getFilter(context, request.params.filterId); + const resp = await getFilter(legacyClient, request.params.filterId); return response.ok({ body: resp, }); @@ -130,10 +134,10 @@ export function filtersRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canCreateFilter'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const body = request.body; - const resp = await newFilter(context, body); + const resp = await newFilter(legacyClient, body); return response.ok({ body: resp, @@ -168,11 +172,11 @@ export function filtersRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canCreateFilter'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { filterId } = request.params; const body = request.body; - const resp = await updateFilter(context, filterId, body); + const resp = await updateFilter(legacyClient, filterId, body); return response.ok({ body: resp, @@ -202,10 +206,10 @@ export function filtersRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canDeleteFilter'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { filterId } = request.params; - const resp = await deleteFilter(context, filterId); + const resp = await deleteFilter(legacyClient, filterId); return response.ok({ body: resp, @@ -235,9 +239,9 @@ export function filtersRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetFilters'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, response }) => { try { - const resp = await getAllFilterStats(context); + const resp = await getAllFilterStats(legacyClient); return response.ok({ body: resp, diff --git a/x-pack/plugins/ml/server/routes/indices.ts b/x-pack/plugins/ml/server/routes/indices.ts index fb3ef7fc41c76..6a759cb97f308 100644 --- a/x-pack/plugins/ml/server/routes/indices.ts +++ b/x-pack/plugins/ml/server/routes/indices.ts @@ -31,7 +31,7 @@ export function indicesRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canAccessML'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { body: { index, fields: requestFields }, @@ -40,7 +40,7 @@ export function indicesRoutes({ router, mlLicense }: RouteInitialization) { requestFields !== undefined && Array.isArray(requestFields) ? requestFields.join(',') : '*'; - const result = await context.ml!.mlClient.callAsCurrentUser('fieldCaps', { index, fields }); + const result = await legacyClient.callAsCurrentUser('fieldCaps', { index, fields }); return response.ok({ body: result }); } catch (e) { return response.customError(wrapError(e)); diff --git a/x-pack/plugins/ml/server/routes/job_audit_messages.ts b/x-pack/plugins/ml/server/routes/job_audit_messages.ts index d4840ed650a32..2313decfabd5b 100644 --- a/x-pack/plugins/ml/server/routes/job_audit_messages.ts +++ b/x-pack/plugins/ml/server/routes/job_audit_messages.ts @@ -37,9 +37,9 @@ export function jobAuditMessagesRoutes({ router, mlLicense }: RouteInitializatio tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const { getJobAuditMessages } = jobAuditMessagesProvider(context.ml!.mlClient); + const { getJobAuditMessages } = jobAuditMessagesProvider(legacyClient); const { jobId } = request.params; const { from } = request.query; const resp = await getJobAuditMessages(jobId, from); @@ -72,9 +72,9 @@ export function jobAuditMessagesRoutes({ router, mlLicense }: RouteInitializatio tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const { getJobAuditMessages } = jobAuditMessagesProvider(context.ml!.mlClient); + const { getJobAuditMessages } = jobAuditMessagesProvider(legacyClient); const { from } = request.query; const resp = await getJobAuditMessages(undefined, from); diff --git a/x-pack/plugins/ml/server/routes/job_service.ts b/x-pack/plugins/ml/server/routes/job_service.ts index e03dbb40d623a..3d560fc857e95 100644 --- a/x-pack/plugins/ml/server/routes/job_service.ts +++ b/x-pack/plugins/ml/server/routes/job_service.ts @@ -48,9 +48,9 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canStartStopDatafeed'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const { forceStartDatafeeds } = jobServiceProvider(context.ml!.mlClient); + const { forceStartDatafeeds } = jobServiceProvider(legacyClient); const { datafeedIds, start, end } = request.body; const resp = await forceStartDatafeeds(datafeedIds, start, end); @@ -82,9 +82,9 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canStartStopDatafeed'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const { stopDatafeeds } = jobServiceProvider(context.ml!.mlClient); + const { stopDatafeeds } = jobServiceProvider(legacyClient); const { datafeedIds } = request.body; const resp = await stopDatafeeds(datafeedIds); @@ -116,9 +116,9 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canDeleteJob'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const { deleteJobs } = jobServiceProvider(context.ml!.mlClient); + const { deleteJobs } = jobServiceProvider(legacyClient); const { jobIds } = request.body; const resp = await deleteJobs(jobIds); @@ -150,9 +150,9 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canCloseJob'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const { closeJobs } = jobServiceProvider(context.ml!.mlClient); + const { closeJobs } = jobServiceProvider(legacyClient); const { jobIds } = request.body; const resp = await closeJobs(jobIds); @@ -184,9 +184,9 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canCloseJob', 'access:ml:canStartStopDatafeed'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const { forceStopAndCloseJob } = jobServiceProvider(context.ml!.mlClient); + const { forceStopAndCloseJob } = jobServiceProvider(legacyClient); const { jobId } = request.body; const resp = await forceStopAndCloseJob(jobId); @@ -223,9 +223,9 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const { jobsSummary } = jobServiceProvider(context.ml!.mlClient); + const { jobsSummary } = jobServiceProvider(legacyClient); const { jobIds } = request.body; const resp = await jobsSummary(jobIds); @@ -257,9 +257,9 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, response }) => { try { - const { jobsWithTimerange } = jobServiceProvider(context.ml!.mlClient); + const { jobsWithTimerange } = jobServiceProvider(legacyClient); const resp = await jobsWithTimerange(); return response.ok({ @@ -290,9 +290,9 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const { createFullJobsList } = jobServiceProvider(context.ml!.mlClient); + const { createFullJobsList } = jobServiceProvider(legacyClient); const { jobIds } = request.body; const resp = await createFullJobsList(jobIds); @@ -320,9 +320,9 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, response }) => { try { - const { getAllGroups } = jobServiceProvider(context.ml!.mlClient); + const { getAllGroups } = jobServiceProvider(legacyClient); const resp = await getAllGroups(); return response.ok({ @@ -353,9 +353,9 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canUpdateJob'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const { updateGroups } = jobServiceProvider(context.ml!.mlClient); + const { updateGroups } = jobServiceProvider(legacyClient); const { jobs } = request.body; const resp = await updateGroups(jobs); @@ -383,9 +383,9 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, response }) => { try { - const { deletingJobTasks } = jobServiceProvider(context.ml!.mlClient); + const { deletingJobTasks } = jobServiceProvider(legacyClient); const resp = await deletingJobTasks(); return response.ok({ @@ -416,9 +416,9 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const { jobsExist } = jobServiceProvider(context.ml!.mlClient); + const { jobsExist } = jobServiceProvider(legacyClient); const { jobIds } = request.body; const resp = await jobsExist(jobIds); @@ -449,12 +449,12 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response, context }) => { try { const { indexPattern } = request.params; const isRollup = request.query.rollup === 'true'; const savedObjectsClient = context.core.savedObjects.client; - const { newJobCaps } = jobServiceProvider(context.ml!.mlClient); + const { newJobCaps } = jobServiceProvider(legacyClient); const resp = await newJobCaps(indexPattern, isRollup, savedObjectsClient); return response.ok({ @@ -485,7 +485,7 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { indexPatternTitle, @@ -499,7 +499,7 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { splitFieldValue, } = request.body; - const { newJobLineChart } = jobServiceProvider(context.ml!.mlClient); + const { newJobLineChart } = jobServiceProvider(legacyClient); const resp = await newJobLineChart( indexPatternTitle, timeField, @@ -540,7 +540,7 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { indexPatternTitle, @@ -553,7 +553,7 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { splitFieldName, } = request.body; - const { newJobPopulationChart } = jobServiceProvider(context.ml!.mlClient); + const { newJobPopulationChart } = jobServiceProvider(legacyClient); const resp = await newJobPopulationChart( indexPatternTitle, timeField, @@ -589,9 +589,9 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, response }) => { try { - const { getAllJobAndGroupIds } = jobServiceProvider(context.ml!.mlClient); + const { getAllJobAndGroupIds } = jobServiceProvider(legacyClient); const resp = await getAllJobAndGroupIds(); return response.ok({ @@ -622,9 +622,9 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canCreateJob'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const { getLookBackProgress } = jobServiceProvider(context.ml!.mlClient); + const { getLookBackProgress } = jobServiceProvider(legacyClient); const { jobId, start, end } = request.body; const resp = await getLookBackProgress(jobId, start, end); @@ -656,9 +656,9 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canCreateJob'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const { validateCategoryExamples } = categorizationExamplesProvider(context.ml!.mlClient); + const { validateCategoryExamples } = categorizationExamplesProvider(legacyClient); const { indexPatternTitle, timeField, @@ -709,9 +709,9 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const { topCategories } = jobServiceProvider(context.ml!.mlClient); + const { topCategories } = jobServiceProvider(legacyClient); const { jobId, count } = request.body; const resp = await topCategories(jobId, count); @@ -743,9 +743,9 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canCreateJob', 'access:ml:canStartStopDatafeed'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const { revertModelSnapshot } = jobServiceProvider(context.ml!.mlClient); + const { revertModelSnapshot } = jobServiceProvider(legacyClient); const { jobId, snapshotId, diff --git a/x-pack/plugins/ml/server/routes/job_validation.ts b/x-pack/plugins/ml/server/routes/job_validation.ts index e52c6b76e918b..6da052663a002 100644 --- a/x-pack/plugins/ml/server/routes/job_validation.ts +++ b/x-pack/plugins/ml/server/routes/job_validation.ts @@ -5,7 +5,7 @@ */ import Boom from 'boom'; -import { RequestHandlerContext } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { TypeOf } from '@kbn/config-schema'; import { AnalysisConfig } from '../../common/types/anomaly_detection_jobs'; import { wrapError } from '../client/error_wrapper'; @@ -27,12 +27,12 @@ type CalculateModelMemoryLimitPayload = TypeOf; */ export function jobValidationRoutes({ router, mlLicense }: RouteInitialization, version: string) { function calculateModelMemoryLimit( - context: RequestHandlerContext, + legacyClient: ILegacyScopedClusterClient, payload: CalculateModelMemoryLimitPayload ) { const { analysisConfig, indexPattern, query, timeFieldName, earliestMs, latestMs } = payload; - return calculateModelMemoryLimitProvider(context.ml!.mlClient)( + return calculateModelMemoryLimitProvider(legacyClient)( analysisConfig as AnalysisConfig, indexPattern, query, @@ -61,10 +61,10 @@ export function jobValidationRoutes({ router, mlLicense }: RouteInitialization, tags: ['access:ml:canCreateJob'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { let errorResp; - const resp = await estimateBucketSpanFactory(context.ml!.mlClient)(request.body) + const resp = await estimateBucketSpanFactory(legacyClient)(request.body) // this catch gets triggered when the estimation code runs without error // but isn't able to come up with a bucket span estimation. // this doesn't return a HTTP error but an object with an error message @@ -109,9 +109,9 @@ export function jobValidationRoutes({ router, mlLicense }: RouteInitialization, tags: ['access:ml:canCreateJob'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const resp = await calculateModelMemoryLimit(context, request.body); + const resp = await calculateModelMemoryLimit(legacyClient, request.body); return response.ok({ body: resp, @@ -141,9 +141,9 @@ export function jobValidationRoutes({ router, mlLicense }: RouteInitialization, tags: ['access:ml:canCreateJob'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const resp = await validateCardinality(context.ml!.mlClient, request.body); + const resp = await validateCardinality(legacyClient, request.body); return response.ok({ body: resp, @@ -173,11 +173,11 @@ export function jobValidationRoutes({ router, mlLicense }: RouteInitialization, tags: ['access:ml:canCreateJob'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { // version corresponds to the version used in documentation links. const resp = await validateJob( - context.ml!.mlClient, + legacyClient, request.body, version, mlLicense.isSecurityEnabled() === false diff --git a/x-pack/plugins/ml/server/routes/modules.ts b/x-pack/plugins/ml/server/routes/modules.ts index 463babb86304f..23e37d2213029 100644 --- a/x-pack/plugins/ml/server/routes/modules.ts +++ b/x-pack/plugins/ml/server/routes/modules.ts @@ -6,7 +6,11 @@ import { TypeOf } from '@kbn/config-schema'; -import { RequestHandlerContext, KibanaRequest } from 'kibana/server'; +import { + ILegacyScopedClusterClient, + KibanaRequest, + SavedObjectsClientContract, +} from 'kibana/server'; import { DatafeedOverride, JobOverride } from '../../common/types/modules'; import { wrapError } from '../client/error_wrapper'; import { DataRecognizer } from '../models/data_recognizer'; @@ -19,16 +23,22 @@ import { import { RouteInitialization } from '../types'; function recognize( - context: RequestHandlerContext, + legacyClient: ILegacyScopedClusterClient, + savedObjectsClient: SavedObjectsClientContract, request: KibanaRequest, indexPatternTitle: string ) { - const dr = new DataRecognizer(context.ml!.mlClient, context.core.savedObjects.client, request); + const dr = new DataRecognizer(legacyClient, savedObjectsClient, request); return dr.findMatches(indexPatternTitle); } -function getModule(context: RequestHandlerContext, request: KibanaRequest, moduleId: string) { - const dr = new DataRecognizer(context.ml!.mlClient, context.core.savedObjects.client, request); +function getModule( + legacyClient: ILegacyScopedClusterClient, + savedObjectsClient: SavedObjectsClientContract, + request: KibanaRequest, + moduleId: string +) { + const dr = new DataRecognizer(legacyClient, savedObjectsClient, request); if (moduleId === undefined) { return dr.listModules(); } else { @@ -37,7 +47,8 @@ function getModule(context: RequestHandlerContext, request: KibanaRequest, modul } function setup( - context: RequestHandlerContext, + legacyClient: ILegacyScopedClusterClient, + savedObjectsClient: SavedObjectsClientContract, request: KibanaRequest, moduleId: string, prefix?: string, @@ -52,7 +63,7 @@ function setup( datafeedOverrides?: DatafeedOverride | DatafeedOverride[], estimateModelMemory?: boolean ) { - const dr = new DataRecognizer(context.ml!.mlClient, context.core.savedObjects.client, request); + const dr = new DataRecognizer(legacyClient, savedObjectsClient, request); return dr.setup( moduleId, prefix, @@ -70,11 +81,12 @@ function setup( } function dataRecognizerJobsExist( - context: RequestHandlerContext, + legacyClient: ILegacyScopedClusterClient, + savedObjectsClient: SavedObjectsClientContract, request: KibanaRequest, moduleId: string ) { - const dr = new DataRecognizer(context.ml!.mlClient, context.core.savedObjects.client, request); + const dr = new DataRecognizer(legacyClient, savedObjectsClient, request); return dr.dataRecognizerJobsExist(moduleId); } @@ -119,10 +131,15 @@ export function dataRecognizer({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canCreateJob'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response, context }) => { try { const { indexPatternTitle } = request.params; - const results = await recognize(context, request, indexPatternTitle); + const results = await recognize( + legacyClient, + context.core.savedObjects.client, + request, + indexPatternTitle + ); return response.ok({ body: results }); } catch (e) { @@ -249,7 +266,7 @@ export function dataRecognizer({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response, context }) => { try { let { moduleId } = request.params; if (moduleId === '') { @@ -257,7 +274,12 @@ export function dataRecognizer({ router, mlLicense }: RouteInitialization) { // the moduleId will be an empty string. moduleId = undefined; } - const results = await getModule(context, request, moduleId); + const results = await getModule( + legacyClient, + context.core.savedObjects.client, + request, + moduleId + ); return response.ok({ body: results }); } catch (e) { @@ -417,7 +439,7 @@ export function dataRecognizer({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canCreateJob'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response, context }) => { try { const { moduleId } = request.params; @@ -436,7 +458,8 @@ export function dataRecognizer({ router, mlLicense }: RouteInitialization) { } = request.body as TypeOf; const result = await setup( - context, + legacyClient, + context.core.savedObjects.client, request, moduleId, prefix, @@ -521,10 +544,15 @@ export function dataRecognizer({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response, context }) => { try { const { moduleId } = request.params; - const result = await dataRecognizerJobsExist(context, request, moduleId); + const result = await dataRecognizerJobsExist( + legacyClient, + context.core.savedObjects.client, + request, + moduleId + ); return response.ok({ body: result }); } catch (e) { diff --git a/x-pack/plugins/ml/server/routes/notification_settings.ts b/x-pack/plugins/ml/server/routes/notification_settings.ts index e4a9abb0784be..09c145d6257a8 100644 --- a/x-pack/plugins/ml/server/routes/notification_settings.ts +++ b/x-pack/plugins/ml/server/routes/notification_settings.ts @@ -26,13 +26,13 @@ export function notificationRoutes({ router, mlLicense }: RouteInitialization) { tags: ['access:ml:canAccessML'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, response }) => { try { const params = { includeDefaults: true, filterPath: '**.xpack.notification', }; - const resp = await context.ml!.mlClient.callAsCurrentUser('cluster.getSettings', params); + const resp = await legacyClient.callAsCurrentUser('cluster.getSettings', params); return response.ok({ body: resp, diff --git a/x-pack/plugins/ml/server/routes/results_service.ts b/x-pack/plugins/ml/server/routes/results_service.ts index c9370362816fa..0d619bf63b8e7 100644 --- a/x-pack/plugins/ml/server/routes/results_service.ts +++ b/x-pack/plugins/ml/server/routes/results_service.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { RequestHandlerContext } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { schema } from '@kbn/config-schema'; import { wrapError } from '../client/error_wrapper'; import { RouteInitialization } from '../types'; @@ -18,8 +18,8 @@ import { import { resultsServiceProvider } from '../models/results_service'; import { ML_RESULTS_INDEX_PATTERN } from '../../common/constants/index_patterns'; -function getAnomaliesTableData(context: RequestHandlerContext, payload: any) { - const rs = resultsServiceProvider(context.ml!.mlClient); +function getAnomaliesTableData(legacyClient: ILegacyScopedClusterClient, payload: any) { + const rs = resultsServiceProvider(legacyClient); const { jobIds, criteriaFields, @@ -48,25 +48,25 @@ function getAnomaliesTableData(context: RequestHandlerContext, payload: any) { ); } -function getCategoryDefinition(context: RequestHandlerContext, payload: any) { - const rs = resultsServiceProvider(context.ml!.mlClient); +function getCategoryDefinition(legacyClient: ILegacyScopedClusterClient, payload: any) { + const rs = resultsServiceProvider(legacyClient); return rs.getCategoryDefinition(payload.jobId, payload.categoryId); } -function getCategoryExamples(context: RequestHandlerContext, payload: any) { - const rs = resultsServiceProvider(context.ml!.mlClient); +function getCategoryExamples(legacyClient: ILegacyScopedClusterClient, payload: any) { + const rs = resultsServiceProvider(legacyClient); const { jobId, categoryIds, maxExamples } = payload; return rs.getCategoryExamples(jobId, categoryIds, maxExamples); } -function getMaxAnomalyScore(context: RequestHandlerContext, payload: any) { - const rs = resultsServiceProvider(context.ml!.mlClient); +function getMaxAnomalyScore(legacyClient: ILegacyScopedClusterClient, payload: any) { + const rs = resultsServiceProvider(legacyClient); const { jobIds, earliestMs, latestMs } = payload; return rs.getMaxAnomalyScore(jobIds, earliestMs, latestMs); } -function getPartitionFieldsValues(context: RequestHandlerContext, payload: any) { - const rs = resultsServiceProvider(context.ml!.mlClient); +function getPartitionFieldsValues(legacyClient: ILegacyScopedClusterClient, payload: any) { + const rs = resultsServiceProvider(legacyClient); const { jobId, searchTerm, criteriaFields, earliestMs, latestMs } = payload; return rs.getPartitionFieldsValues(jobId, searchTerm, criteriaFields, earliestMs, latestMs); } @@ -94,9 +94,9 @@ export function resultsServiceRoutes({ router, mlLicense }: RouteInitialization) tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const resp = await getAnomaliesTableData(context, request.body); + const resp = await getAnomaliesTableData(legacyClient, request.body); return response.ok({ body: resp, @@ -126,9 +126,9 @@ export function resultsServiceRoutes({ router, mlLicense }: RouteInitialization) tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const resp = await getCategoryDefinition(context, request.body); + const resp = await getCategoryDefinition(legacyClient, request.body); return response.ok({ body: resp, @@ -158,9 +158,9 @@ export function resultsServiceRoutes({ router, mlLicense }: RouteInitialization) tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const resp = await getMaxAnomalyScore(context, request.body); + const resp = await getMaxAnomalyScore(legacyClient, request.body); return response.ok({ body: resp, @@ -190,9 +190,9 @@ export function resultsServiceRoutes({ router, mlLicense }: RouteInitialization) tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const resp = await getCategoryExamples(context, request.body); + const resp = await getCategoryExamples(legacyClient, request.body); return response.ok({ body: resp, @@ -222,9 +222,9 @@ export function resultsServiceRoutes({ router, mlLicense }: RouteInitialization) tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const resp = await getPartitionFieldsValues(context, request.body); + const resp = await getPartitionFieldsValues(legacyClient, request.body); return response.ok({ body: resp, @@ -251,14 +251,14 @@ export function resultsServiceRoutes({ router, mlLicense }: RouteInitialization) tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { const body = { ...request.body, index: ML_RESULTS_INDEX_PATTERN, }; try { return response.ok({ - body: await context.ml!.mlClient.callAsInternalUser('search', body), + body: await legacyClient.callAsInternalUser('search', body), }); } catch (error) { return response.customError(wrapError(error)); diff --git a/x-pack/plugins/ml/server/routes/schemas/anomaly_detectors_schema.ts b/x-pack/plugins/ml/server/routes/schemas/anomaly_detectors_schema.ts index 196e17d0984f9..9203c7cf997a6 100644 --- a/x-pack/plugins/ml/server/routes/schemas/anomaly_detectors_schema.ts +++ b/x-pack/plugins/ml/server/routes/schemas/anomaly_detectors_schema.ts @@ -11,7 +11,7 @@ const customRulesSchema = schema.maybe( schema.maybe( schema.object({ actions: schema.arrayOf(schema.string()), - conditions: schema.arrayOf(schema.any()), + conditions: schema.maybe(schema.arrayOf(schema.any())), scope: schema.maybe(schema.any()), }) ) diff --git a/x-pack/plugins/ml/server/routes/system.ts b/x-pack/plugins/ml/server/routes/system.ts index f2d8c89046178..99ba9519b6a34 100644 --- a/x-pack/plugins/ml/server/routes/system.ts +++ b/x-pack/plugins/ml/server/routes/system.ts @@ -7,7 +7,7 @@ import { schema } from '@kbn/config-schema'; import { Request } from 'hapi'; -import { RequestHandlerContext } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { wrapError } from '../client/error_wrapper'; import { mlLog } from '../client/log'; import { capabilitiesProvider } from '../lib/capabilities'; @@ -21,9 +21,9 @@ export function systemRoutes( { router, mlLicense }: RouteInitialization, { spaces, cloud, resolveMlCapabilities }: SystemRouteDeps ) { - async function getNodeCount(context: RequestHandlerContext) { + async function getNodeCount(legacyClient: ILegacyScopedClusterClient) { const filterPath = 'nodes.*.attributes'; - const resp = await context.ml!.mlClient.callAsInternalUser('nodes.info', { + const resp = await legacyClient.callAsInternalUser('nodes.info', { filterPath, }); @@ -58,9 +58,9 @@ export function systemRoutes( tags: ['access:ml:canAccessML'], }, }, - mlLicense.basicLicenseAPIGuard(async (context, request, response) => { + mlLicense.basicLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const { callAsCurrentUser, callAsInternalUser } = context.ml!.mlClient; + const { callAsCurrentUser, callAsInternalUser } = legacyClient; let upgradeInProgress = false; try { const info = await callAsInternalUser('ml.info'); @@ -115,7 +115,7 @@ export function systemRoutes( path: '/api/ml/ml_capabilities', validate: false, }, - mlLicense.basicLicenseAPIGuard(async (context, request, response) => { + mlLicense.basicLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { // if spaces is disabled force isMlEnabledInSpace to be true const { isMlEnabledInSpace } = @@ -129,7 +129,7 @@ export function systemRoutes( } const { getCapabilities } = capabilitiesProvider( - context.ml!.mlClient, + legacyClient, mlCapabilities, mlLicense, isMlEnabledInSpace @@ -159,10 +159,10 @@ export function systemRoutes( }, }, - mlLicense.basicLicenseAPIGuard(async (context, request, response) => { + mlLicense.basicLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { return response.ok({ - body: await getNodeCount(context), + body: await getNodeCount(legacyClient), }); } catch (e) { return response.customError(wrapError(e)); @@ -185,9 +185,9 @@ export function systemRoutes( tags: ['access:ml:canAccessML'], }, }, - mlLicense.basicLicenseAPIGuard(async (context, request, response) => { + mlLicense.basicLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { - const info = await context.ml!.mlClient.callAsInternalUser('ml.info'); + const info = await legacyClient.callAsInternalUser('ml.info'); const cloudId = cloud && cloud.cloudId; return response.ok({ body: { ...info, cloudId }, @@ -216,10 +216,10 @@ export function systemRoutes( tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { return response.ok({ - body: await context.ml!.mlClient.callAsCurrentUser('search', request.body), + body: await legacyClient.callAsCurrentUser('search', request.body), }); } catch (error) { return response.customError(wrapError(error)); @@ -243,7 +243,7 @@ export function systemRoutes( tags: ['access:ml:canGetJobs'], }, }, - mlLicense.fullLicenseAPIGuard(async (context, request, response) => { + mlLicense.fullLicenseAPIGuard(async ({ legacyClient, request, response }) => { try { const { index } = request.body; @@ -255,7 +255,7 @@ export function systemRoutes( ignore: 404, }; - const fieldsResult = await context.ml!.mlClient.callAsCurrentUser('fieldCaps', options); + const fieldsResult = await legacyClient.callAsCurrentUser('fieldCaps', options); const result = { exists: false }; if (Array.isArray(fieldsResult.indices) && fieldsResult.indices.length !== 0) { diff --git a/x-pack/plugins/monitoring/public/angular/app_modules.ts b/x-pack/plugins/monitoring/public/angular/app_modules.ts index f3d77b196b26e..499610045d771 100644 --- a/x-pack/plugins/monitoring/public/angular/app_modules.ts +++ b/x-pack/plugins/monitoring/public/angular/app_modules.ts @@ -23,7 +23,7 @@ import { GlobalState } from '../url_state'; import { getSafeForExternalLink } from '../lib/get_safe_for_external_link'; // @ts-ignore -import { formatNumber, formatMetric } from '../lib/format_number'; +import { formatMetric, formatNumber } from '../lib/format_number'; // @ts-ignore import { extractIp } from '../lib/extract_ip'; // @ts-ignore @@ -65,7 +65,7 @@ export const localAppModule = ({ createLocalPrivateModule(); createLocalStorage(); createLocalConfigModule(core); - createLocalStateModule(query); + createLocalStateModule(query, core.notifications.toasts); createLocalTopNavModule(navigation); createHrefModule(core); createMonitoringAppServices(); @@ -97,7 +97,10 @@ function createMonitoringAppConfigConstants( keys.map(([key, value]) => (constantsModule = constantsModule.constant(key as string, value))); } -function createLocalStateModule(query: any) { +function createLocalStateModule( + query: MonitoringStartPluginDependencies['data']['query'], + toasts: MonitoringStartPluginDependencies['core']['notifications']['toasts'] +) { angular .module('monitoring/State', ['monitoring/Private']) .service('globalState', function ( @@ -106,7 +109,7 @@ function createLocalStateModule(query: any) { $location: ng.ILocationService ) { function GlobalStateProvider(this: any) { - const state = new GlobalState(query, $rootScope, $location, this); + const state = new GlobalState(query, toasts, $rootScope, $location, this); const initialState: any = state.getState(); for (const key in initialState) { if (!initialState.hasOwnProperty(key)) { diff --git a/x-pack/plugins/monitoring/public/url_state.ts b/x-pack/plugins/monitoring/public/url_state.ts index e53497d751f9b..65e48223d7a64 100644 --- a/x-pack/plugins/monitoring/public/url_state.ts +++ b/x-pack/plugins/monitoring/public/url_state.ts @@ -23,6 +23,7 @@ import { IKbnUrlStateStorage, ISyncStateRef, syncState, + withNotifyOnErrors, } from '../../../../src/plugins/kibana_utils/public'; interface Route { @@ -71,6 +72,7 @@ export class GlobalState { constructor( queryService: MonitoringStartPluginDependencies['data']['query'], + toasts: MonitoringStartPluginDependencies['core']['notifications']['toasts'], rootScope: ng.IRootScopeService, ngLocation: ng.ILocationService, externalState: RawObject @@ -78,7 +80,11 @@ export class GlobalState { this.timefilterRef = queryService.timefilter.timefilter; const history: History = createHashHistory(); - this.stateStorage = createKbnUrlStateStorage({ useHash: false, history }); + this.stateStorage = createKbnUrlStateStorage({ + useHash: false, + history, + ...withNotifyOnErrors(toasts), + }); const initialStateFromUrl = this.stateStorage.get(GLOBAL_STATE_KEY) as MonitoringAppState; diff --git a/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.js b/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.js index 18db738bba38e..16d42d896ca11 100644 --- a/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.js +++ b/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.js @@ -119,65 +119,67 @@ export async function getClustersFromRequest( // add alerts data if (isInCodePath(codePaths, [CODE_PATH_ALERTS])) { const alertsClient = req.getAlertsClient(); - for (const cluster of clusters) { - const verification = verifyMonitoringLicense(req.server); - if (!verification.enabled) { - // return metadata detailing that alerts is disabled because of the monitoring cluster license - cluster.alerts = { - alertsMeta: { - enabled: verification.enabled, - message: verification.message, // NOTE: this is only defined when the alert feature is disabled - }, - list: {}, - }; - continue; - } + if (alertsClient) { + for (const cluster of clusters) { + const verification = verifyMonitoringLicense(req.server); + if (!verification.enabled) { + // return metadata detailing that alerts is disabled because of the monitoring cluster license + cluster.alerts = { + alertsMeta: { + enabled: verification.enabled, + message: verification.message, // NOTE: this is only defined when the alert feature is disabled + }, + list: {}, + }; + continue; + } + + // check the license type of the production cluster for alerts feature support + const license = cluster.license || {}; + const prodLicenseInfo = checkLicenseForAlerts( + license.type, + license.status === 'active', + 'production' + ); + if (prodLicenseInfo.clusterAlerts.enabled) { + cluster.alerts = { + list: await fetchStatus( + alertsClient, + req.server.plugins.monitoring.info, + undefined, + cluster.cluster_uuid, + start, + end, + [] + ), + alertsMeta: { + enabled: true, + }, + }; + continue; + } - // check the license type of the production cluster for alerts feature support - const license = cluster.license || {}; - const prodLicenseInfo = checkLicenseForAlerts( - license.type, - license.status === 'active', - 'production' - ); - if (prodLicenseInfo.clusterAlerts.enabled) { cluster.alerts = { - list: await fetchStatus( - alertsClient, - req.server.plugins.monitoring.info, - undefined, - cluster.cluster_uuid, - start, - end, - [] - ), + list: {}, alertsMeta: { enabled: true, }, + clusterMeta: { + enabled: false, + message: i18n.translate( + 'xpack.monitoring.clusterAlerts.unsupportedClusterAlertsDescription', + { + defaultMessage: + 'Cluster [{clusterName}] license type [{licenseType}] does not support Cluster Alerts', + values: { + clusterName: cluster.cluster_name, + licenseType: `${license.type}`, + }, + } + ), + }, }; - continue; } - - cluster.alerts = { - list: {}, - alertsMeta: { - enabled: true, - }, - clusterMeta: { - enabled: false, - message: i18n.translate( - 'xpack.monitoring.clusterAlerts.unsupportedClusterAlertsDescription', - { - defaultMessage: - 'Cluster [{clusterName}] license type [{licenseType}] does not support Cluster Alerts', - values: { - clusterName: cluster.cluster_name, - licenseType: `${license.type}`, - }, - } - ), - }, - }; } } } diff --git a/x-pack/plugins/monitoring/server/plugin.ts b/x-pack/plugins/monitoring/server/plugin.ts index ed091d4b8d7a7..3aedb6831e7ab 100644 --- a/x-pack/plugins/monitoring/server/plugin.ts +++ b/x-pack/plugins/monitoring/server/plugin.ts @@ -325,8 +325,22 @@ export class Plugin { getKibanaStatsCollector: () => this.legacyShimDependencies.kibanaStatsCollector, getUiSettingsService: () => context.core.uiSettings.client, getActionTypeRegistry: () => context.actions?.listTypes(), - getAlertsClient: () => plugins.alerts.getAlertsClientWithRequest(req), - getActionsClient: () => plugins.actions.getActionsClientWithRequest(req), + getAlertsClient: () => { + try { + return plugins.alerts.getAlertsClientWithRequest(req); + } catch (err) { + // If security is disabled, this call will throw an error unless a certain config is set for dist builds + return null; + } + }, + getActionsClient: () => { + try { + return plugins.actions.getActionsClientWithRequest(req); + } catch (err) { + // If security is disabled, this call will throw an error unless a certain config is set for dist builds + return null; + } + }, server: { config: legacyConfigWrapper, newPlatform: { diff --git a/x-pack/plugins/reporting/server/config/schema.test.ts b/x-pack/plugins/reporting/server/config/schema.test.ts index ddd5491b661bc..69e4d443cf040 100644 --- a/x-pack/plugins/reporting/server/config/schema.test.ts +++ b/x-pack/plugins/reporting/server/config/schema.test.ts @@ -126,6 +126,34 @@ describe('Reporting Config Schema', () => { ).toMatchObject({ hostname: 'Frodo' }); }); + it('allows setting a wildcard for chrome proxy bypass', () => { + expect( + ConfigSchema.validate({ + capture: { + browser: { + chromium: { + proxy: { + enabled: true, + server: 'http://example.com:8080', + bypass: ['*.example.com', '*bar.example.com', 'bats.example.com'], + }, + }, + }, + }, + }).capture.browser.chromium.proxy + ).toMatchInlineSnapshot(` + Object { + "bypass": Array [ + "*.example.com", + "*bar.example.com", + "bats.example.com", + ], + "enabled": true, + "server": "http://example.com:8080", + } + `); + }); + it(`logs the proper validation messages`, () => { // kibanaServer const throwValidationErr = () => ConfigSchema.validate({ kibanaServer: { hostname: '0' } }); diff --git a/x-pack/plugins/reporting/server/config/schema.ts b/x-pack/plugins/reporting/server/config/schema.ts index 2f77aff0020d5..33249f20757e2 100644 --- a/x-pack/plugins/reporting/server/config/schema.ts +++ b/x-pack/plugins/reporting/server/config/schema.ts @@ -97,7 +97,7 @@ const CaptureSchema = schema.object({ bypass: schema.conditional( schema.siblingRef('enabled'), true, - schema.arrayOf(schema.string({ hostname: true })), + schema.arrayOf(schema.string()), schema.maybe(schema.never()) ), }), diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/create_rules_bulk_schema.test.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/create_rules_bulk_schema.test.ts index 00854f1ed5526..d335cafdb7885 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/create_rules_bulk_schema.test.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/create_rules_bulk_schema.test.ts @@ -127,7 +127,6 @@ describe('create_rules_bulk_schema', () => { const output = foldLeftRight(checked); expect(formatErrors(output.errors)).toEqual([ 'Invalid value "undefined" supplied to "risk_score"', - 'Invalid value "undefined" supplied to "risk_score"', ]); expect(output.schema).toEqual({}); }); diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/update_rules_bulk_schema.test.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/update_rules_bulk_schema.test.ts index 4cb38889045fc..33a22d9a5f805 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/update_rules_bulk_schema.test.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/update_rules_bulk_schema.test.ts @@ -123,7 +123,6 @@ describe('update_rules_bulk_schema', () => { const output = foldLeftRight(checked); expect(formatErrors(output.errors)).toEqual([ 'Invalid value "undefined" supplied to "risk_score"', - 'Invalid value "undefined" supplied to "risk_score"', ]); expect(output.schema).toEqual({}); }); diff --git a/x-pack/plugins/security_solution/common/endpoint/generate_data.test.ts b/x-pack/plugins/security_solution/common/endpoint/generate_data.test.ts index debe4a3da6a6f..46fc002e76e7f 100644 --- a/x-pack/plugins/security_solution/common/endpoint/generate_data.test.ts +++ b/x-pack/plugins/security_solution/common/endpoint/generate_data.test.ts @@ -26,6 +26,13 @@ describe('data generator', () => { generator = new EndpointDocGenerator('seed'); }); + it('creates events with a numerically increasing sequence value', () => { + const event1 = generator.generateEvent(); + const event2 = generator.generateEvent(); + + expect(event2.event.sequence).toBe(event1.event.sequence + 1); + }); + it('creates the same documents with same random seed', () => { const generator1 = new EndpointDocGenerator('seed'); const generator2 = new EndpointDocGenerator('seed'); diff --git a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts index aa3f0bf287fca..09f25fc074eff 100644 --- a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts @@ -333,6 +333,7 @@ export function getTreeOptionsWithDef(options?: TreeOptions): TreeOptionDefaults export class EndpointDocGenerator { commonInfo: HostInfo; random: seedrandom.prng; + sequence: number = 0; constructor(seed: string | seedrandom.prng = Math.random().toString()) { if (typeof seed === 'string') { this.random = seedrandom(seed); @@ -440,6 +441,7 @@ export class EndpointDocGenerator { dataset: 'endpoint', module: 'endpoint', type: 'creation', + sequence: this.sequence++, }, file: { owner: 'SYSTEM', @@ -586,6 +588,7 @@ export class EndpointDocGenerator { kind: 'event', type: options.eventType ? options.eventType : ['start'], id: this.seededUUIDv4(), + sequence: this.sequence++, }, host: this.commonInfo.host, process: { diff --git a/x-pack/plugins/security_solution/common/endpoint/models/ecs_safety_helpers.ts b/x-pack/plugins/security_solution/common/endpoint/models/ecs_safety_helpers.ts new file mode 100644 index 0000000000000..8b419e90a6ee9 --- /dev/null +++ b/x-pack/plugins/security_solution/common/endpoint/models/ecs_safety_helpers.ts @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ECSField } from '../types'; + +/** + * Use these functions to accecss information held in `ECSField`s. + */ + +/** + * True if the field contains `expected`. If the field contains an array, this will be true if the array contains `expected`. + */ +export function hasValue(valueOrCollection: ECSField, expected: T): boolean { + if (Array.isArray(valueOrCollection)) { + return valueOrCollection.includes(expected); + } else { + return valueOrCollection === expected; + } +} + +/** + * Return first non-null value. If the field contains an array, this will return the first value that isn't null. If the field isn't an array it'll be returned unless it's null. + */ +export function firstNonNullValue(valueOrCollection: ECSField): T | undefined { + if (valueOrCollection === null) { + return undefined; + } else if (Array.isArray(valueOrCollection)) { + for (const value of valueOrCollection) { + if (value !== null) { + return value; + } + } + } else { + return valueOrCollection; + } +} + +/* + * Get an array of all non-null values. If there is just 1 value, return it wrapped in an array. If there are multiple values, return the non-null ones. + * Use this when you want to consistently access the value(s) as an array. + */ +export function values(valueOrCollection: ECSField): T[] { + if (Array.isArray(valueOrCollection)) { + const nonNullValues: T[] = []; + for (const value of valueOrCollection) { + if (value !== null) { + nonNullValues.push(value); + } + } + return nonNullValues; + } else if (valueOrCollection !== null) { + // if there is a single non-null value, wrap it in an array and return it. + return [valueOrCollection]; + } else { + // if the value was null, return `[]`. + return []; + } +} diff --git a/x-pack/plugins/security_solution/common/endpoint/models/event.ts b/x-pack/plugins/security_solution/common/endpoint/models/event.ts index 1168b5edb6ffd..30e11819c0272 100644 --- a/x-pack/plugins/security_solution/common/endpoint/models/event.ts +++ b/x-pack/plugins/security_solution/common/endpoint/models/event.ts @@ -3,8 +3,26 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { LegacyEndpointEvent, ResolverEvent } from '../types'; +import { + LegacyEndpointEvent, + ResolverEvent, + SafeResolverEvent, + SafeLegacyEndpointEvent, +} from '../types'; +import { firstNonNullValue } from './ecs_safety_helpers'; +/* + * Determine if a `ResolverEvent` is the legacy variety. Can be used to narrow `ResolverEvent` to `LegacyEndpointEvent`. + */ +export function isLegacyEventSafeVersion( + event: SafeResolverEvent +): event is SafeLegacyEndpointEvent { + return 'endgame' in event && event.endgame !== undefined; +} + +/* + * Determine if a `ResolverEvent` is the legacy variety. Can be used to narrow `ResolverEvent` to `LegacyEndpointEvent`. See `isLegacyEventSafeVersion` + */ export function isLegacyEvent(event: ResolverEvent): event is LegacyEndpointEvent { return (event as LegacyEndpointEvent).endgame !== undefined; } @@ -31,6 +49,12 @@ export function isProcessRunning(event: ResolverEvent): boolean { ); } +export function timestampSafeVersion(event: SafeResolverEvent): string | undefined | number { + return isLegacyEventSafeVersion(event) + ? firstNonNullValue(event.endgame?.timestamp_utc) + : firstNonNullValue(event?.['@timestamp']); +} + export function eventTimestamp(event: ResolverEvent): string | undefined | number { if (isLegacyEvent(event)) { return event.endgame.timestamp_utc; @@ -47,6 +71,14 @@ export function eventName(event: ResolverEvent): string { } } +export function processNameSafeVersion(event: SafeResolverEvent): string | undefined { + if (isLegacyEventSafeVersion(event)) { + return firstNonNullValue(event.endgame.process_name); + } else { + return firstNonNullValue(event.process?.name); + } +} + export function eventId(event: ResolverEvent): number | undefined | string { if (isLegacyEvent(event)) { return event.endgame.serial_event_id; @@ -54,6 +86,26 @@ export function eventId(event: ResolverEvent): number | undefined | string { return event.event.id; } +export function eventSequence(event: ResolverEvent): number | undefined { + if (isLegacyEvent(event)) { + return firstNonNullValue(event.endgame.serial_event_id); + } + return firstNonNullValue(event.event?.sequence); +} + +export function eventSequenceSafeVersion(event: SafeResolverEvent): number | undefined { + if (isLegacyEventSafeVersion(event)) { + return firstNonNullValue(event.endgame.serial_event_id); + } + return firstNonNullValue(event.event?.sequence); +} + +export function eventIDSafeVersion(event: SafeResolverEvent): number | undefined | string { + return firstNonNullValue( + isLegacyEventSafeVersion(event) ? event.endgame?.serial_event_id : event.event?.id + ); +} + export function entityId(event: ResolverEvent): string { if (isLegacyEvent(event)) { return event.endgame.unique_pid ? String(event.endgame.unique_pid) : ''; @@ -61,6 +113,16 @@ export function entityId(event: ResolverEvent): string { return event.process.entity_id; } +export function entityIDSafeVersion(event: SafeResolverEvent): string | undefined { + if (isLegacyEventSafeVersion(event)) { + return event.endgame?.unique_pid === undefined + ? undefined + : String(firstNonNullValue(event.endgame.unique_pid)); + } else { + return firstNonNullValue(event.process?.entity_id); + } +} + export function parentEntityId(event: ResolverEvent): string | undefined { if (isLegacyEvent(event)) { return event.endgame.unique_ppid ? String(event.endgame.unique_ppid) : undefined; @@ -68,6 +130,13 @@ export function parentEntityId(event: ResolverEvent): string | undefined { return event.process.parent?.entity_id; } +export function parentEntityIDSafeVersion(event: SafeResolverEvent): string | undefined { + if (isLegacyEventSafeVersion(event)) { + return String(firstNonNullValue(event.endgame.unique_ppid)); + } + return firstNonNullValue(event.process?.parent?.entity_id); +} + export function ancestryArray(event: ResolverEvent): string[] | undefined { if (isLegacyEvent(event)) { return undefined; diff --git a/x-pack/plugins/security_solution/common/endpoint/types.ts b/x-pack/plugins/security_solution/common/endpoint/types.ts index 1c24e1abe5a57..2a1c95caff3a3 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types.ts @@ -182,6 +182,15 @@ export interface ResolverRelatedEvents { nextEvent: string | null; } +/** + * Safe version of `ResolverRelatedEvents` + */ +export interface SafeResolverRelatedEvents { + entityID: string; + events: SafeResolverEvent[]; + nextEvent: string | null; +} + /** * Response structure for the alerts route. */ @@ -311,6 +320,7 @@ export interface AlertEvent { dataset: string; module: string; type: string; + sequence: number; }; Endpoint: { policy: { @@ -508,11 +518,14 @@ export interface EndpointEvent { ecs: { version: string; }; + // A legacy has `endgame` and an `EndpointEvent` (AKA ECS event) will never have it. This helps TS narrow `SafeResolverEvent`. + endgame?: never; event: { category: string | string[]; type: string | string[]; id: string; kind: string; + sequence: number; }; host: Host; network?: { @@ -559,6 +572,131 @@ export interface EndpointEvent { export type ResolverEvent = EndpointEvent | LegacyEndpointEvent; +/** + * All mappings in Elasticsearch support arrays. They can also return null values or be missing. For example, a `keyword` mapping could return `null` or `[null]` or `[]` or `'hi'`, or `['hi', 'there']`. We need to handle these cases in order to avoid throwing an error. + * When dealing with an value that comes from ES, wrap the underlying type in `ECSField`. For example, if you have a `keyword` or `text` value coming from ES, cast it to `ECSField`. + */ +export type ECSField = T | null | Array; + +/** + * A more conservative version of `ResolverEvent` that treats fields as optional and use `ECSField` to type all ECS fields. + * Prefer this over `ResolverEvent`. + */ +export type SafeResolverEvent = SafeEndpointEvent | SafeLegacyEndpointEvent; + +/** + * Safer version of ResolverEvent. Please use this going forward. + */ +export type SafeEndpointEvent = Partial<{ + '@timestamp': ECSField; + agent: Partial<{ + id: ECSField; + version: ECSField; + type: ECSField; + }>; + ecs: Partial<{ + version: ECSField; + }>; + event: Partial<{ + category: ECSField; + type: ECSField; + id: ECSField; + kind: ECSField; + sequence: ECSField; + }>; + host: Partial<{ + id: ECSField; + hostname: ECSField; + name: ECSField; + ip: ECSField; + mac: ECSField; + architecture: ECSField; + os: Partial<{ + full: ECSField; + name: ECSField; + version: ECSField; + platform: ECSField; + family: ECSField; + Ext: Partial<{ + variant: ECSField; + }>; + }>; + }>; + network: Partial<{ + direction: ECSField; + forwarded_ip: ECSField; + }>; + dns: Partial<{ + question: Partial<{ name: ECSField }>; + }>; + process: Partial<{ + entity_id: ECSField; + name: ECSField; + executable: ECSField; + args: ECSField; + code_signature: Partial<{ + status: ECSField; + subject_name: ECSField; + }>; + pid: ECSField; + hash: Partial<{ + md5: ECSField; + }>; + parent: Partial<{ + entity_id: ECSField; + name: ECSField; + pid: ECSField; + }>; + /* + * The array has a special format. The entity_ids towards the beginning of the array are closer ancestors and the + * values towards the end of the array are more distant ancestors (grandparents). Therefore + * ancestry_array[0] == process.parent.entity_id and ancestry_array[1] == process.parent.parent.entity_id + */ + Ext: Partial<{ + ancestry: ECSField; + }>; + }>; + user: Partial<{ + domain: ECSField; + name: ECSField; + }>; + file: Partial<{ path: ECSField }>; + registry: Partial<{ path: ECSField; key: ECSField }>; +}>; + +export interface SafeLegacyEndpointEvent { + '@timestamp'?: ECSField; + /** + * 'legacy' events must have an `endgame` key. + */ + endgame: Partial<{ + pid: ECSField; + ppid: ECSField; + event_type_full: ECSField; + event_subtype_full: ECSField; + event_timestamp: ECSField; + event_type: ECSField; + unique_pid: ECSField; + unique_ppid: ECSField; + machine_id: ECSField; + process_name: ECSField; + process_path: ECSField; + timestamp_utc: ECSField; + serial_event_id: ECSField; + }>; + agent: Partial<{ + id: ECSField; + type: ECSField; + version: ECSField; + }>; + event: Partial<{ + action: ECSField; + type: ECSField; + category: ECSField; + id: ECSField; + }>; +} + /** * The response body for the resolver '/entity' index API */ diff --git a/x-pack/plugins/security_solution/common/format_errors.test.ts b/x-pack/plugins/security_solution/common/format_errors.test.ts index c8cd72b72816b..06bdf67097764 100644 --- a/x-pack/plugins/security_solution/common/format_errors.test.ts +++ b/x-pack/plugins/security_solution/common/format_errors.test.ts @@ -41,6 +41,22 @@ describe('utils', () => { expect(output).toEqual(['some error 1', 'some error 2']); }); + test('it filters out duplicate error messages', () => { + const validationError1: t.ValidationError = { + value: 'Some existing error 1', + context: [], + message: 'some error 1', + }; + const validationError2: t.ValidationError = { + value: 'Some existing error 1', + context: [], + message: 'some error 1', + }; + const errors: t.Errors = [validationError1, validationError2]; + const output = formatErrors(errors); + expect(output).toEqual(['some error 1']); + }); + test('will use message before context if it is set', () => { const context: t.Context = ([{ key: 'some string key' }] as unknown) as t.Context; const validationError1: t.ValidationError = { diff --git a/x-pack/plugins/security_solution/common/format_errors.ts b/x-pack/plugins/security_solution/common/format_errors.ts index ba963f34f2983..4e1f5e4796152 100644 --- a/x-pack/plugins/security_solution/common/format_errors.ts +++ b/x-pack/plugins/security_solution/common/format_errors.ts @@ -8,7 +8,7 @@ import * as t from 'io-ts'; import { isObject } from 'lodash/fp'; export const formatErrors = (errors: t.Errors): string[] => { - return errors.map((error) => { + const err = errors.map((error) => { if (error.message != null) { return error.message; } else { @@ -26,4 +26,6 @@ export const formatErrors = (errors: t.Errors): string[] => { return `Invalid value "${value}" supplied to "${suppliedValue}"`; } }); + + return [...new Set(err)]; }; diff --git a/x-pack/plugins/security_solution/public/cases/components/configure_cases/index.tsx b/x-pack/plugins/security_solution/public/cases/components/configure_cases/index.tsx index e2e3a600a95ff..63b271b8cce78 100644 --- a/x-pack/plugins/security_solution/public/cases/components/configure_cases/index.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/configure_cases/index.tsx @@ -42,6 +42,9 @@ const FormWrapper = styled.div` padding-top: ${theme.eui.paddingSizes.xl}; padding-bottom: ${theme.eui.paddingSizes.xl}; + .euiFlyout { + z-index: ${theme.eui.euiZNavigation + 1}; + } `} `; diff --git a/x-pack/plugins/security_solution/public/common/components/autocomplete/field.test.tsx b/x-pack/plugins/security_solution/public/common/components/autocomplete/field.test.tsx index 30864f246071b..a678deae41542 100644 --- a/x-pack/plugins/security_solution/public/common/components/autocomplete/field.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/autocomplete/field.test.tsx @@ -12,7 +12,7 @@ import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; import { fields, getField, -} from '../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks.ts'; +} from '../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks'; import { FieldComponent } from './field'; describe('FieldComponent', () => { diff --git a/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_lists.test.tsx b/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_lists.test.tsx index eca38b9effe1b..eef6e09d496db 100644 --- a/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_lists.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_lists.test.tsx @@ -11,7 +11,7 @@ import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; // we don't have the types for waitFor just yet, so using "as waitFor" until when we do import { wait as waitFor } from '@testing-library/react'; -import { getField } from '../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks.ts'; +import { getField } from '../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks'; import { ListSchema } from '../../../lists_plugin_deps'; import { getFoundListSchemaMock } from '../../../../../lists/common/schemas/response/found_list_schema.mock'; import { getListResponseMock } from '../../../../../lists/common/schemas/response/list_schema.mock'; diff --git a/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_match.test.tsx b/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_match.test.tsx index 998ed1f3351c8..94040ccb639be 100644 --- a/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_match.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_match.test.tsx @@ -12,7 +12,7 @@ import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; import { fields, getField, -} from '../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks.ts'; +} from '../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks'; import { AutocompleteFieldMatchComponent } from './field_value_match'; import { useFieldValueAutocomplete } from './hooks/use_field_value_autocomplete'; jest.mock('./hooks/use_field_value_autocomplete'); diff --git a/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_match_any.test.tsx b/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_match_any.test.tsx index 0a0281a9c4a51..4074150f76d06 100644 --- a/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_match_any.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/autocomplete/field_value_match_any.test.tsx @@ -12,7 +12,7 @@ import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; import { fields, getField, -} from '../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks.ts'; +} from '../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks'; import { AutocompleteFieldMatchAnyComponent } from './field_value_match_any'; import { useFieldValueAutocomplete } from './hooks/use_field_value_autocomplete'; jest.mock('./hooks/use_field_value_autocomplete'); diff --git a/x-pack/plugins/security_solution/public/common/components/autocomplete/helpers.test.ts b/x-pack/plugins/security_solution/public/common/components/autocomplete/helpers.test.ts index 289cdd5e87c00..bbcbcbcf928b3 100644 --- a/x-pack/plugins/security_solution/public/common/components/autocomplete/helpers.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/autocomplete/helpers.test.ts @@ -5,7 +5,7 @@ */ import '../../../common/mock/match_media'; -import { getField } from '../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks.ts'; +import { getField } from '../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks'; import { EXCEPTION_OPERATORS, diff --git a/x-pack/plugins/security_solution/public/common/components/autocomplete/hooks/use_field_value_autocomplete.test.ts b/x-pack/plugins/security_solution/public/common/components/autocomplete/hooks/use_field_value_autocomplete.test.ts index a76b50d11a875..82e9c21f6b839 100644 --- a/x-pack/plugins/security_solution/public/common/components/autocomplete/hooks/use_field_value_autocomplete.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/autocomplete/hooks/use_field_value_autocomplete.test.ts @@ -13,7 +13,7 @@ import { } from './use_field_value_autocomplete'; import { useKibana } from '../../../../common/lib/kibana'; import { stubIndexPatternWithFields } from '../../../../../../../../src/plugins/data/common/index_patterns/index_pattern.stub'; -import { getField } from '../../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks.ts'; +import { getField } from '../../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks'; import { OperatorTypeEnum } from '../../../../lists_plugin_deps'; jest.mock('../../../../common/lib/kibana'); diff --git a/x-pack/plugins/security_solution/public/common/components/autocomplete/operator.test.tsx b/x-pack/plugins/security_solution/public/common/components/autocomplete/operator.test.tsx index 737be199e2481..e6f6227811085 100644 --- a/x-pack/plugins/security_solution/public/common/components/autocomplete/operator.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/autocomplete/operator.test.tsx @@ -9,7 +9,7 @@ import { mount } from 'enzyme'; import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; -import { getField } from '../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks.ts'; +import { getField } from '../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks'; import { OperatorComponent } from './operator'; import { isOperator, isNotOperator } from './operators'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/builder/entry_item.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/builder/entry_item.test.tsx index 2a116c4cd8acf..59a5db2a09779 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/builder/entry_item.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/builder/entry_item.test.tsx @@ -22,7 +22,7 @@ import { import { fields, getField, -} from '../../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks.ts'; +} from '../../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks'; import { getFoundListSchemaMock } from '../../../../../../lists/common/schemas/response/found_list_schema.mock'; import { getEmptyValue } from '../../empty_value'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/builder/exception_item.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/builder/exception_item.test.tsx index e90639a2c0285..0f9be25e046b2 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/builder/exception_item.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/builder/exception_item.test.tsx @@ -10,7 +10,7 @@ import { mount } from 'enzyme'; import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; import { useKibana } from '../../../../common/lib/kibana'; -import { fields } from '../../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks.ts'; +import { fields } from '../../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks'; import { getExceptionListItemSchemaMock } from '../../../../../../lists/common/schemas/response/exception_list_item_schema.mock'; import { getEntryMatchMock } from '../../../../../../lists/common/schemas/types/entry_match.mock'; import { getEntryMatchAnyMock } from '../../../../../../lists/common/schemas/types/entry_match_any.mock'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/builder/helpers.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/builder/helpers.test.tsx index 04ab9ee7216f7..9bfd04cc19d72 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/builder/helpers.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/builder/helpers.test.tsx @@ -6,7 +6,7 @@ import { fields, getField, -} from '../../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks.ts'; +} from '../../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks'; import { getEntryNestedMock } from '../../../../../../lists/common/schemas/types/entry_nested.mock'; import { getEntryMatchMock } from '../../../../../../lists/common/schemas/types/entry_match.mock'; import { getEntryMatchAnyMock } from '../../../../../../lists/common/schemas/types/entry_match_any.mock'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/builder/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/builder/index.test.tsx index 3fa0e59f9acb0..2d389a7dbcee1 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/builder/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/builder/index.test.tsx @@ -13,7 +13,7 @@ import { wait as waitFor } from '@testing-library/react'; import { fields, getField, -} from '../../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks.ts'; +} from '../../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks'; import { getExceptionListItemSchemaMock } from '../../../../../../lists/common/schemas/response/exception_list_item_schema.mock'; import { getEntryMatchAnyMock } from '../../../../../../lists/common/schemas/types/entry_match_any.mock'; diff --git a/x-pack/plugins/security_solution/public/common/components/header_global/index.tsx b/x-pack/plugins/security_solution/public/common/components/header_global/index.tsx index fbc3d62768d00..e05e3c2e9aeb1 100644 --- a/x-pack/plugins/security_solution/public/common/components/header_global/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/header_global/index.tsx @@ -41,14 +41,15 @@ const FlexItem = styled(EuiFlexItem)` `; FlexItem.displayName = 'FlexItem'; -const FlexGroup = styled(EuiFlexGroup)<{ $globalFullScreen: boolean }>` - ${({ $globalFullScreen, theme }) => ` +const FlexGroup = styled(EuiFlexGroup)<{ $globalFullScreen: boolean; $hasSibling: boolean }>` + ${({ $globalFullScreen, $hasSibling, theme }) => ` border-bottom: ${theme.eui.euiBorderThin}; margin-bottom: 1px; padding-bottom: 4px; padding-left: ${theme.eui.paddingSizes.l}; padding-right: ${gutterTimeline}; ${$globalFullScreen ? 'display: none;' : ''} + ${$hasSibling ? `border-bottom: ${theme.eui.euiBorderThin};` : 'border-bottom-width: 0px;'} `} `; FlexGroup.displayName = 'FlexGroup'; @@ -75,6 +76,7 @@ export const HeaderGlobal = React.memo(({ hideDetectionEngine diff --git a/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx b/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx index 807f1839973fa..d71242329bcda 100644 --- a/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx @@ -104,7 +104,7 @@ const StatefulTopNComponent: React.FC = ({ value, }) => { const kibana = useKibana(); - const { from, deleteQuery, setQuery, to } = useGlobalTime(); + const { from, deleteQuery, setQuery, to } = useGlobalTime(false); const options = getOptions( timelineId === TimelineId.active ? activeTimelineEventType : undefined diff --git a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts b/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts index 8c7acfc18ece6..c4702e915c076 100644 --- a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts +++ b/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import deepEqual from 'fast-deep-equal'; import { isEmpty } from 'lodash/fp'; import { useEffect, useMemo, useState, useRef } from 'react'; @@ -34,7 +35,6 @@ export const useQuery = ({ } return configIndex; }, [configIndex, indexToAdd]); - const [, dispatchToaster] = useStateToaster(); const refetch = useRef(); const [loading, setLoading] = useState(false); @@ -43,20 +43,54 @@ export const useQuery = ({ const [totalCount, setTotalCount] = useState(-1); const apolloClient = useApolloClient(); + const [matrixHistogramVariables, setMatrixHistogramVariables] = useState< + GetMatrixHistogramQuery.Variables + >({ + filterQuery: createFilter(filterQuery), + sourceId: 'default', + timerange: { + interval: '12h', + from: startDate!, + to: endDate!, + }, + defaultIndex, + inspect: isInspected, + stackByField, + histogramType, + }); + + useEffect(() => { + setMatrixHistogramVariables((prevVariables) => { + const localVariables = { + filterQuery: createFilter(filterQuery), + sourceId: 'default', + timerange: { + interval: '12h', + from: startDate!, + to: endDate!, + }, + defaultIndex, + inspect: isInspected, + stackByField, + histogramType, + }; + if (!deepEqual(prevVariables, localVariables)) { + return localVariables; + } + return prevVariables; + }); + }, [ + defaultIndex, + filterQuery, + histogramType, + indexToAdd, + isInspected, + stackByField, + startDate, + endDate, + ]); + useEffect(() => { - const matrixHistogramVariables: GetMatrixHistogramQuery.Variables = { - filterQuery: createFilter(filterQuery), - sourceId: 'default', - timerange: { - interval: '12h', - from: startDate!, - to: endDate!, - }, - defaultIndex, - inspect: isInspected, - stackByField, - histogramType, - }; let isSubscribed = true; const abortCtrl = new AbortController(); const abortSignal = abortCtrl.signal; @@ -102,19 +136,7 @@ export const useQuery = ({ isSubscribed = false; abortCtrl.abort(); }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [ - defaultIndex, - errorMessage, - filterQuery, - histogramType, - indexToAdd, - isInspected, - stackByField, - startDate, - endDate, - data, - ]); + }, [apolloClient, dispatchToaster, errorMessage, matrixHistogramVariables]); return { data, loading, inspect, totalCount, refetch: refetch.current }; }; diff --git a/x-pack/plugins/security_solution/public/common/containers/use_global_time/index.test.tsx b/x-pack/plugins/security_solution/public/common/containers/use_global_time/index.test.tsx index 9d5f1740b0276..07ce3551e3289 100644 --- a/x-pack/plugins/security_solution/public/common/containers/use_global_time/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/use_global_time/index.test.tsx @@ -8,17 +8,22 @@ import { act, renderHook } from '@testing-library/react-hooks'; import { useGlobalTime } from '.'; +const mockDispatch = jest.fn(); + jest.mock('react-redux', () => { const originalModule = jest.requireActual('react-redux'); return { ...originalModule, - useDispatch: jest.fn().mockReturnValue(jest.fn()), + useDispatch: () => mockDispatch, useSelector: jest.fn().mockReturnValue({ from: 0, to: 0 }), }; }); describe('useGlobalTime', () => { + beforeEach(() => { + mockDispatch.mockReset(); + }); test('returns memoized value', () => { const { result, rerender } = renderHook(() => useGlobalTime()); @@ -30,4 +35,18 @@ describe('useGlobalTime', () => { expect(result1.from).toBe(0); expect(result1.to).toBe(0); }); + + test('clear all queries at unmount', () => { + const { rerender } = renderHook(() => useGlobalTime()); + act(() => rerender()); + expect(mockDispatch.mock.calls[0][0].type).toEqual( + 'x-pack/security_solution/local/inputs/DELETE_ALL_QUERY' + ); + }); + + test('do NOT clear all queries at unmount', () => { + const { rerender } = renderHook(() => useGlobalTime(false)); + act(() => rerender()); + expect(mockDispatch.mock.calls.length).toBe(0); + }); }); diff --git a/x-pack/plugins/security_solution/public/common/containers/use_global_time/index.tsx b/x-pack/plugins/security_solution/public/common/containers/use_global_time/index.tsx index b63616ecbcf56..52825caf9ce74 100644 --- a/x-pack/plugins/security_solution/public/common/containers/use_global_time/index.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/use_global_time/index.tsx @@ -11,7 +11,7 @@ import { inputsSelectors } from '../../store'; import { inputsActions } from '../../store/actions'; import { SetQuery, DeleteQuery } from './types'; -export const useGlobalTime = () => { +export const useGlobalTime = (clearAllQuery: boolean = true) => { const dispatch = useDispatch(); const { from, to } = useSelector(inputsSelectors.globalTimeRangeSelector); const [isInitializing, setIsInitializing] = useState(true); @@ -32,9 +32,11 @@ export const useGlobalTime = () => { setIsInitializing(false); } return () => { - dispatch(inputsActions.deleteAllQuery({ id: 'global' })); + if (clearAllQuery) { + dispatch(inputsActions.deleteAllQuery({ id: 'global' })); + } }; - }, [dispatch, isInitializing]); + }, [clearAllQuery, dispatch, isInitializing]); const memoizedReturn = useMemo( () => ({ diff --git a/x-pack/plugins/security_solution/public/common/mock/timeline_results.ts b/x-pack/plugins/security_solution/public/common/mock/timeline_results.ts index a415ab75f13ea..ab9f12a67fe89 100644 --- a/x-pack/plugins/security_solution/public/common/mock/timeline_results.ts +++ b/x-pack/plugins/security_solution/public/common/mock/timeline_results.ts @@ -8,7 +8,13 @@ import { FilterStateStore } from '../../../../../../src/plugins/data/common/es_q import { TimelineType, TimelineStatus } from '../../../common/types/timeline'; import { OpenTimelineResult } from '../../timelines/components/open_timeline/types'; -import { GetAllTimeline, SortFieldTimeline, TimelineResult, Direction } from '../../graphql/types'; +import { + GetAllTimeline, + SortFieldTimeline, + TimelineResult, + Direction, + DetailItem, +} from '../../graphql/types'; import { allTimelinesQuery } from '../../timelines/containers/all/index.gql_query'; import { CreateTimelineProps } from '../../detections/components/alerts_table/types'; import { TimelineModel } from '../../timelines/store/timeline/model'; @@ -2252,5 +2258,32 @@ export const defaultTimelineProps: CreateTimelineProps = { width: 1100, }, to: '2018-11-05T19:03:25.937Z', + notes: null, ruleNote: '# this is some markdown documentation', }; + +export const mockTimelineDetails: DetailItem[] = [ + { + field: 'host.name', + values: ['apache'], + originalValue: 'apache', + }, + { + field: 'user.id', + values: ['1'], + originalValue: 1, + }, +]; + +export const mockTimelineDetailsApollo = { + data: { + source: { + TimelineDetails: { + data: mockTimelineDetails, + }, + }, + }, + loading: false, + networkStatus: 7, + stale: false, +}; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.test.tsx index c2b51e29c230d..e8015f601cb18 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.test.tsx @@ -3,6 +3,8 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ + +import { get } from 'lodash/fp'; import sinon from 'sinon'; import moment from 'moment'; @@ -12,6 +14,7 @@ import { defaultTimelineProps, apolloClient, mockTimelineApolloResult, + mockTimelineDetailsApollo, } from '../../../common/mock/'; import { CreateTimeline, UpdateTimelineLoading } from './types'; import { Ecs } from '../../../graphql/types'; @@ -37,7 +40,13 @@ describe('alert actions', () => { createTimeline = jest.fn() as jest.Mocked; updateTimelineIsLoading = jest.fn() as jest.Mocked; - jest.spyOn(apolloClient, 'query').mockResolvedValue(mockTimelineApolloResult); + jest.spyOn(apolloClient, 'query').mockImplementation((obj) => { + const id = get('variables.id', obj); + if (id != null) { + return Promise.resolve(mockTimelineApolloResult); + } + return Promise.resolve(mockTimelineDetailsApollo); + }); clock = sinon.useFakeTimers(unix); }); @@ -71,6 +80,7 @@ describe('alert actions', () => { }); const expected = { from: '2018-11-05T18:58:25.937Z', + notes: null, timeline: { columns: [ { diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.tsx index 7bebc9efbee15..34c0537a6d7d2 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.tsx @@ -19,6 +19,8 @@ import { Ecs, TimelineStatus, TimelineType, + GetTimelineDetailsQuery, + DetailItem, } from '../../../graphql/types'; import { oneTimelineQuery } from '../../../timelines/containers/one/index.gql_query'; import { timelineDefaults } from '../../../timelines/store/timeline/defaults'; @@ -34,6 +36,7 @@ import { } from './helpers'; import { KueryFilterQueryKind } from '../../../common/store'; import { DataProvider } from '../../../timelines/components/timeline/data_providers/data_provider'; +import { timelineDetailsQuery } from '../../../timelines/containers/details/index.gql_query'; export const getUpdateAlertsQuery = (eventIds: Readonly) => { return { @@ -153,35 +156,45 @@ export const sendAlertToTimelineAction = async ({ if (timelineId !== '' && apolloClient != null) { try { updateTimelineIsLoading({ id: 'timeline-1', isLoading: true }); - const responseTimeline = await apolloClient.query< - GetOneTimeline.Query, - GetOneTimeline.Variables - >({ - query: oneTimelineQuery, - fetchPolicy: 'no-cache', - variables: { - id: timelineId, - }, - }); + const [responseTimeline, eventDataResp] = await Promise.all([ + apolloClient.query({ + query: oneTimelineQuery, + fetchPolicy: 'no-cache', + variables: { + id: timelineId, + }, + }), + apolloClient.query({ + query: timelineDetailsQuery, + fetchPolicy: 'no-cache', + variables: { + defaultIndex: [], + docValueFields: [], + eventId: ecsData._id, + indexName: ecsData._index ?? '', + sourceId: 'default', + }, + }), + ]); const resultingTimeline: TimelineResult = getOr({}, 'data.getOneTimeline', responseTimeline); - + const eventData: DetailItem[] = getOr([], 'data.source.TimelineDetails.data', eventDataResp); if (!isEmpty(resultingTimeline)) { const timelineTemplate: TimelineResult = omitTypenameInTimeline(resultingTimeline); openAlertInBasicTimeline = false; - const { timeline } = formatTimelineResultToModel( + const { timeline, notes } = formatTimelineResultToModel( timelineTemplate, true, timelineTemplate.timelineType ?? TimelineType.default ); const query = replaceTemplateFieldFromQuery( timeline.kqlQuery?.filterQuery?.kuery?.expression ?? '', - ecsData, + eventData, timeline.timelineType ); - const filters = replaceTemplateFieldFromMatchFilters(timeline.filters ?? [], ecsData); + const filters = replaceTemplateFieldFromMatchFilters(timeline.filters ?? [], eventData); const dataProviders = replaceTemplateFieldFromDataProviders( timeline.dataProviders ?? [], - ecsData, + eventData, timeline.timelineType ); @@ -213,10 +226,12 @@ export const sendAlertToTimelineAction = async ({ expression: query, }, }, + noteIds: notes?.map((n) => n.noteId) ?? [], show: true, }, to, ruleNote: noteContent, + notes: notes ?? null, }); } } catch { @@ -232,6 +247,7 @@ export const sendAlertToTimelineAction = async ({ ) { return createTimeline({ from, + notes: null, timeline: { ...timelineDefaults, dataProviders: [ @@ -282,6 +298,7 @@ export const sendAlertToTimelineAction = async ({ } else { return createTimeline({ from, + notes: null, timeline: { ...timelineDefaults, dataProviders: [ diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/helpers.test.ts b/x-pack/plugins/security_solution/public/detections/components/alerts_table/helpers.test.ts index 4decddd6b8886..7ac254f2e84f7 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/helpers.test.ts +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/helpers.test.ts @@ -3,10 +3,8 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { cloneDeep } from 'lodash/fp'; import { TimelineType } from '../../../../common/types/timeline'; -import { mockEcsData } from '../../../common/mock/mock_ecs'; import { Filter } from '../../../../../../../src/plugins/data/public'; import { DataProvider, @@ -20,31 +18,40 @@ import { replaceTemplateFieldFromMatchFilters, reformatDataProviderWithNewValue, } from './helpers'; +import { mockTimelineDetails } from '../../../common/mock'; describe('helpers', () => { - let mockEcsDataClone = cloneDeep(mockEcsData); - beforeEach(() => { - mockEcsDataClone = cloneDeep(mockEcsData); - }); describe('getStringOrStringArray', () => { test('it should correctly return a string array', () => { - const value = getStringArray('x', { - x: 'The nickname of the developer we all :heart:', - }); + const value = getStringArray('x', [ + { + field: 'x', + values: ['The nickname of the developer we all :heart:'], + originalValue: 'The nickname of the developer we all :heart:', + }, + ]); expect(value).toEqual(['The nickname of the developer we all :heart:']); }); test('it should correctly return a string array with a single element', () => { - const value = getStringArray('x', { - x: ['The nickname of the developer we all :heart:'], - }); + const value = getStringArray('x', [ + { + field: 'x', + values: ['The nickname of the developer we all :heart:'], + originalValue: 'The nickname of the developer we all :heart:', + }, + ]); expect(value).toEqual(['The nickname of the developer we all :heart:']); }); test('it should correctly return a string array with two elements of strings', () => { - const value = getStringArray('x', { - x: ['The nickname of the developer we all :heart:', 'We are all made of stars'], - }); + const value = getStringArray('x', [ + { + field: 'x', + values: ['The nickname of the developer we all :heart:', 'We are all made of stars'], + originalValue: 'The nickname of the developer we all :heart:', + }, + ]); expect(value).toEqual([ 'The nickname of the developer we all :heart:', 'We are all made of stars', @@ -52,22 +59,40 @@ describe('helpers', () => { }); test('it should correctly return a string array with deep elements', () => { - const value = getStringArray('x.y.z', { - x: { y: { z: 'zed' } }, - }); + const value = getStringArray('x.y.z', [ + { + field: 'x.y.z', + values: ['zed'], + originalValue: 'zed', + }, + ]); expect(value).toEqual(['zed']); }); test('it should correctly return a string array with a non-existent value', () => { - const value = getStringArray('non.existent', { - x: { y: { z: 'zed' } }, - }); + const value = getStringArray('non.existent', [ + { + field: 'x.y.z', + values: ['zed'], + originalValue: 'zed', + }, + ]); expect(value).toEqual([]); }); test('it should trace an error if the value is not a string', () => { const mockConsole: Console = ({ trace: jest.fn() } as unknown) as Console; - const value = getStringArray('a', { a: 5 }, mockConsole); + const value = getStringArray( + 'a', + [ + { + field: 'a', + values: (5 as unknown) as string[], + originalValue: 'zed', + }, + ], + mockConsole + ); expect(value).toEqual([]); expect( mockConsole.trace @@ -77,13 +102,23 @@ describe('helpers', () => { 'when trying to access field:', 'a', 'from data object of:', - { a: 5 } + [{ field: 'a', originalValue: 'zed', values: 5 }] ); }); test('it should trace an error if the value is an array of mixed values', () => { const mockConsole: Console = ({ trace: jest.fn() } as unknown) as Console; - const value = getStringArray('a', { a: ['hi', 5] }, mockConsole); + const value = getStringArray( + 'a', + [ + { + field: 'a', + values: (['hi', 5] as unknown) as string[], + originalValue: 'zed', + }, + ], + mockConsole + ); expect(value).toEqual([]); expect( mockConsole.trace @@ -93,7 +128,7 @@ describe('helpers', () => { 'when trying to access field:', 'a', 'from data object of:', - { a: ['hi', 5] } + [{ field: 'a', originalValue: 'zed', values: ['hi', 5] }] ); }); }); @@ -103,7 +138,7 @@ describe('helpers', () => { test('given an empty query string this returns an empty query string', () => { const replacement = replaceTemplateFieldFromQuery( '', - mockEcsDataClone[0], + mockTimelineDetails, TimelineType.default ); expect(replacement).toEqual(''); @@ -112,7 +147,7 @@ describe('helpers', () => { test('given a query string with spaces this returns an empty query string', () => { const replacement = replaceTemplateFieldFromQuery( ' ', - mockEcsDataClone[0], + mockTimelineDetails, TimelineType.default ); expect(replacement).toEqual(''); @@ -121,17 +156,21 @@ describe('helpers', () => { test('it should replace a query with a template value such as apache from a mock template', () => { const replacement = replaceTemplateFieldFromQuery( 'host.name: placeholdertext', - mockEcsDataClone[0], + mockTimelineDetails, TimelineType.default ); expect(replacement).toEqual('host.name: apache'); }); test('it should replace a template field with an ECS value that is not an array', () => { - mockEcsDataClone[0].host!.name = ('apache' as unknown) as string[]; // very unsafe cast for this test case + const dupTimelineDetails = [...mockTimelineDetails]; + dupTimelineDetails[0] = { + ...dupTimelineDetails[0], + values: ('apache' as unknown) as string[], + }; // very unsafe cast for this test case const replacement = replaceTemplateFieldFromQuery( 'host.name: *', - mockEcsDataClone[0], + dupTimelineDetails, TimelineType.default ); expect(replacement).toEqual('host.name: *'); @@ -140,7 +179,7 @@ describe('helpers', () => { test('it should NOT replace a query with a template value that is not part of the template fields array', () => { const replacement = replaceTemplateFieldFromQuery( 'user.id: placeholdertext', - mockEcsDataClone[0], + mockTimelineDetails, TimelineType.default ); expect(replacement).toEqual('user.id: placeholdertext'); @@ -151,7 +190,7 @@ describe('helpers', () => { test('given an empty query string this returns an empty query string', () => { const replacement = replaceTemplateFieldFromQuery( '', - mockEcsDataClone[0], + mockTimelineDetails, TimelineType.template ); expect(replacement).toEqual(''); @@ -160,7 +199,7 @@ describe('helpers', () => { test('given a query string with spaces this returns an empty query string', () => { const replacement = replaceTemplateFieldFromQuery( ' ', - mockEcsDataClone[0], + mockTimelineDetails, TimelineType.template ); expect(replacement).toEqual(''); @@ -169,17 +208,21 @@ describe('helpers', () => { test('it should NOT replace a query with a template value such as apache from a mock template', () => { const replacement = replaceTemplateFieldFromQuery( 'host.name: placeholdertext', - mockEcsDataClone[0], + mockTimelineDetails, TimelineType.template ); expect(replacement).toEqual('host.name: placeholdertext'); }); test('it should NOT replace a template field with an ECS value that is not an array', () => { - mockEcsDataClone[0].host!.name = ('apache' as unknown) as string[]; // very unsafe cast for this test case + const dupTimelineDetails = [...mockTimelineDetails]; + dupTimelineDetails[0] = { + ...dupTimelineDetails[0], + values: ('apache' as unknown) as string[], + }; // very unsafe cast for this test case const replacement = replaceTemplateFieldFromQuery( 'host.name: *', - mockEcsDataClone[0], + dupTimelineDetails, TimelineType.default ); expect(replacement).toEqual('host.name: *'); @@ -188,7 +231,7 @@ describe('helpers', () => { test('it should NOT replace a query with a template value that is not part of the template fields array', () => { const replacement = replaceTemplateFieldFromQuery( 'user.id: placeholdertext', - mockEcsDataClone[0], + mockTimelineDetails, TimelineType.default ); expect(replacement).toEqual('user.id: placeholdertext'); @@ -198,7 +241,7 @@ describe('helpers', () => { describe('replaceTemplateFieldFromMatchFilters', () => { test('given an empty query filter this will return an empty filter', () => { - const replacement = replaceTemplateFieldFromMatchFilters([], mockEcsDataClone[0]); + const replacement = replaceTemplateFieldFromMatchFilters([], mockTimelineDetails); expect(replacement).toEqual([]); }); @@ -216,7 +259,7 @@ describe('helpers', () => { query: { match_phrase: { 'host.name': 'Braden' } }, }, ]; - const replacement = replaceTemplateFieldFromMatchFilters(filters, mockEcsDataClone[0]); + const replacement = replaceTemplateFieldFromMatchFilters(filters, mockTimelineDetails); const expected: Filter[] = [ { meta: { @@ -247,7 +290,7 @@ describe('helpers', () => { query: { match_phrase: { 'user.id': 'Evan' } }, }, ]; - const replacement = replaceTemplateFieldFromMatchFilters(filters, mockEcsDataClone[0]); + const replacement = replaceTemplateFieldFromMatchFilters(filters, mockTimelineDetails); const expected: Filter[] = [ { meta: { @@ -275,7 +318,7 @@ describe('helpers', () => { mockDataProvider.queryMatch.value = 'Braden'; const replacement = reformatDataProviderWithNewValue( mockDataProvider, - mockEcsDataClone[0], + mockTimelineDetails, TimelineType.default ); expect(replacement).toEqual({ @@ -297,7 +340,11 @@ describe('helpers', () => { }); test('it should replace a query with a template value such as apache from a mock data provider using a string in the data provider', () => { - mockEcsDataClone[0].host!.name = ('apache' as unknown) as string[]; // very unsafe cast for this test case + const dupTimelineDetails = [...mockTimelineDetails]; + dupTimelineDetails[0] = { + ...dupTimelineDetails[0], + values: ('apache' as unknown) as string[], + }; // very unsafe cast for this test case const mockDataProvider: DataProvider = mockDataProviders[0]; mockDataProvider.queryMatch.field = 'host.name'; mockDataProvider.id = 'Braden'; @@ -305,7 +352,7 @@ describe('helpers', () => { mockDataProvider.queryMatch.value = 'Braden'; const replacement = reformatDataProviderWithNewValue( mockDataProvider, - mockEcsDataClone[0], + dupTimelineDetails, TimelineType.default ); expect(replacement).toEqual({ @@ -334,7 +381,7 @@ describe('helpers', () => { mockDataProvider.queryMatch.value = 'Rebecca'; const replacement = reformatDataProviderWithNewValue( mockDataProvider, - mockEcsDataClone[0], + mockTimelineDetails, TimelineType.default ); expect(replacement).toEqual({ @@ -366,7 +413,7 @@ describe('helpers', () => { mockDataProvider.type = DataProviderType.template; const replacement = reformatDataProviderWithNewValue( mockDataProvider, - mockEcsDataClone[0], + mockTimelineDetails, TimelineType.template ); expect(replacement).toEqual({ @@ -396,7 +443,7 @@ describe('helpers', () => { mockDataProvider.type = DataProviderType.default; const replacement = reformatDataProviderWithNewValue( mockDataProvider, - mockEcsDataClone[0], + mockTimelineDetails, TimelineType.template ); expect(replacement).toEqual({ @@ -418,7 +465,11 @@ describe('helpers', () => { }); test('it should replace a query with a template value such as apache from a mock data provider using a string in the data provider', () => { - mockEcsDataClone[0].host!.name = ('apache' as unknown) as string[]; // very unsafe cast for this test case + const dupTimelineDetails = [...mockTimelineDetails]; + dupTimelineDetails[0] = { + ...dupTimelineDetails[0], + values: ('apache' as unknown) as string[], + }; // very unsafe cast for this test case const mockDataProvider: DataProvider = mockDataProviders[0]; mockDataProvider.queryMatch.field = 'host.name'; mockDataProvider.id = 'Braden'; @@ -427,7 +478,7 @@ describe('helpers', () => { mockDataProvider.type = DataProviderType.template; const replacement = reformatDataProviderWithNewValue( mockDataProvider, - mockEcsDataClone[0], + dupTimelineDetails, TimelineType.template ); expect(replacement).toEqual({ @@ -457,7 +508,7 @@ describe('helpers', () => { mockDataProvider.type = DataProviderType.default; const replacement = reformatDataProviderWithNewValue( mockDataProvider, - mockEcsDataClone[0], + mockTimelineDetails, TimelineType.template ); expect(replacement).toEqual({ diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/helpers.ts b/x-pack/plugins/security_solution/public/detections/components/alerts_table/helpers.ts index 084e4bff7e0ac..20c233a03a8cf 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/helpers.ts +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/helpers.ts @@ -4,14 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { get, isEmpty } from 'lodash/fp'; +import { isEmpty } from 'lodash/fp'; import { Filter, esKuery, KueryNode } from '../../../../../../../src/plugins/data/public'; import { DataProvider, DataProviderType, DataProvidersAnd, } from '../../../timelines/components/timeline/data_providers/data_provider'; -import { Ecs, TimelineType } from '../../../graphql/types'; +import { DetailItem, TimelineType } from '../../../graphql/types'; interface FindValueToChangeInQuery { field: string; @@ -47,8 +47,12 @@ const templateFields = [ * @param data The unknown data that is typically a ECS value to get the value * @param localConsole The local console which can be sent in to make this pure (for tests) or use the default console */ -export const getStringArray = (field: string, data: unknown, localConsole = console): string[] => { - const value: unknown | undefined = get(field, data); +export const getStringArray = ( + field: string, + data: DetailItem[], + localConsole = console +): string[] => { + const value: unknown | undefined = data.find((d) => d.field === field)?.values ?? null; if (value == null) { return []; } else if (typeof value === 'string') { @@ -104,14 +108,14 @@ export const findValueToChangeInQuery = ( export const replaceTemplateFieldFromQuery = ( query: string, - ecsData: Ecs, + eventData: DetailItem[], timelineType: TimelineType = TimelineType.default ): string => { if (timelineType === TimelineType.default) { if (query.trim() !== '') { const valueToChange = findValueToChangeInQuery(esKuery.fromKueryExpression(query)); return valueToChange.reduce((newQuery, vtc) => { - const newValue = getStringArray(vtc.field, ecsData); + const newValue = getStringArray(vtc.field, eventData); if (newValue.length) { return newQuery.replace(vtc.valueToChange, newValue[0]); } else { @@ -126,14 +130,17 @@ export const replaceTemplateFieldFromQuery = ( return query.trim(); }; -export const replaceTemplateFieldFromMatchFilters = (filters: Filter[], ecsData: Ecs): Filter[] => +export const replaceTemplateFieldFromMatchFilters = ( + filters: Filter[], + eventData: DetailItem[] +): Filter[] => filters.map((filter) => { if ( filter.meta.type === 'phrase' && filter.meta.key != null && templateFields.includes(filter.meta.key) ) { - const newValue = getStringArray(filter.meta.key, ecsData); + const newValue = getStringArray(filter.meta.key, eventData); if (newValue.length) { filter.meta.params = { query: newValue[0] }; filter.query = { match_phrase: { [filter.meta.key]: newValue[0] } }; @@ -144,13 +151,13 @@ export const replaceTemplateFieldFromMatchFilters = (filters: Filter[], ecsData: export const reformatDataProviderWithNewValue = ( dataProvider: T, - ecsData: Ecs, + eventData: DetailItem[], timelineType: TimelineType = TimelineType.default ): T => { // Support for legacy "template-like" timeline behavior that is using hardcoded list of templateFields if (timelineType !== TimelineType.template) { if (templateFields.includes(dataProvider.queryMatch.field)) { - const newValue = getStringArray(dataProvider.queryMatch.field, ecsData); + const newValue = getStringArray(dataProvider.queryMatch.field, eventData); if (newValue.length) { dataProvider.id = dataProvider.id.replace(dataProvider.name, newValue[0]); dataProvider.name = newValue[0]; @@ -168,7 +175,7 @@ export const reformatDataProviderWithNewValue = dataProviders.map((dataProvider) => { - const newDataProvider = reformatDataProviderWithNewValue(dataProvider, ecsData, timelineType); + const newDataProvider = reformatDataProviderWithNewValue(dataProvider, eventData, timelineType); if (newDataProvider.and != null && !isEmpty(newDataProvider.and)) { newDataProvider.and = newDataProvider.and.map((andDataProvider) => - reformatDataProviderWithNewValue(andDataProvider, ecsData, timelineType) + reformatDataProviderWithNewValue(andDataProvider, eventData, timelineType) ); } return newDataProvider; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx index d93bad29f3348..66423259ec155 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx @@ -147,13 +147,14 @@ export const AlertsTableComponent: React.FC = ({ // Callback for creating a new timeline -- utilized by row/batch actions const createTimelineCallback = useCallback( - ({ from: fromTimeline, timeline, to: toTimeline, ruleNote }: CreateTimelineProps) => { + ({ from: fromTimeline, timeline, to: toTimeline, ruleNote, notes }: CreateTimelineProps) => { updateTimelineIsLoading({ id: 'timeline-1', isLoading: false }); updateTimeline({ duplicate: true, + forceNotes: true, from: fromTimeline, id: 'timeline-1', - notes: [], + notes, timeline: { ...timeline, show: true, diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/types.ts b/x-pack/plugins/security_solution/public/detections/components/alerts_table/types.ts index ebf1a6d3ed533..2e77e77f6b3d5 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/types.ts +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/types.ts @@ -7,7 +7,7 @@ import ApolloClient from 'apollo-client'; import { Status } from '../../../../common/detection_engine/schemas/common/schemas'; -import { Ecs, TimelineNonEcsData } from '../../../graphql/types'; +import { Ecs, NoteResult, TimelineNonEcsData } from '../../../graphql/types'; import { TimelineModel } from '../../../timelines/store/timeline/model'; import { inputsModel } from '../../../common/store'; @@ -63,6 +63,7 @@ export interface CreateTimelineProps { from: string; timeline: TimelineModel; to: string; + notes: NoteResult[] | null; ruleNote?: string; } diff --git a/x-pack/plugins/security_solution/public/resolver/data_access_layer/mocks/one_ancestor_two_children.ts b/x-pack/plugins/security_solution/public/resolver/data_access_layer/mocks/no_ancestors_two_children.ts similarity index 62% rename from x-pack/plugins/security_solution/public/resolver/data_access_layer/mocks/one_ancestor_two_children.ts rename to x-pack/plugins/security_solution/public/resolver/data_access_layer/mocks/no_ancestors_two_children.ts index 94c176d343d17..b0407fa5d7c1d 100644 --- a/x-pack/plugins/security_solution/public/resolver/data_access_layer/mocks/one_ancestor_two_children.ts +++ b/x-pack/plugins/security_solution/public/resolver/data_access_layer/mocks/no_ancestors_two_children.ts @@ -9,11 +9,8 @@ import { ResolverTree, ResolverEntityIndex, } from '../../../../common/endpoint/types'; -import { mockEndpointEvent } from '../../store/mocks/endpoint_event'; -import { - mockTreeWithNoAncestorsAnd2Children, - withRelatedEventsOnOrigin, -} from '../../store/mocks/resolver_tree'; +import { mockEndpointEvent } from '../../mocks/endpoint_event'; +import { mockTreeWithNoAncestorsAnd2Children } from '../../mocks/resolver_tree'; import { DataAccessLayer } from '../../types'; interface Metadata { @@ -43,24 +40,11 @@ interface Metadata { /** * A simple mock dataAccessLayer possible that returns a tree with 0 ancestors and 2 direct children. 1 related event is returned. The parameter to `entities` is ignored. */ -export function oneAncestorTwoChildren( - { withRelatedEvents }: { withRelatedEvents: Iterable<[string, string]> | null } = { - withRelatedEvents: null, - } -): { dataAccessLayer: DataAccessLayer; metadata: Metadata } { +export function noAncestorsTwoChildren(): { dataAccessLayer: DataAccessLayer; metadata: Metadata } { const metadata: Metadata = { databaseDocumentID: '_id', entityIDs: { origin: 'origin', firstChild: 'firstChild', secondChild: 'secondChild' }, }; - const baseTree = mockTreeWithNoAncestorsAnd2Children({ - originID: metadata.entityIDs.origin, - firstChildID: metadata.entityIDs.firstChild, - secondChildID: metadata.entityIDs.secondChild, - }); - const composedTree = withRelatedEvents - ? withRelatedEventsOnOrigin(baseTree, withRelatedEvents) - : baseTree; - return { metadata, dataAccessLayer: { @@ -70,17 +54,13 @@ export function oneAncestorTwoChildren( relatedEvents(entityID: string): Promise { return Promise.resolve({ entityID, - events: - /* Respond with the mocked related events when the origin's related events are fetched*/ withRelatedEvents && - entityID === metadata.entityIDs.origin - ? composedTree.relatedEvents.events - : [ - mockEndpointEvent({ - entityID, - name: 'event', - timestamp: 0, - }), - ], + events: [ + mockEndpointEvent({ + entityID, + name: 'event', + timestamp: 0, + }), + ], nextEvent: null, }); }, @@ -89,7 +69,13 @@ export function oneAncestorTwoChildren( * Fetch a ResolverTree for a entityID */ resolverTree(): Promise { - return Promise.resolve(composedTree); + return Promise.resolve( + mockTreeWithNoAncestorsAnd2Children({ + originID: metadata.entityIDs.origin, + firstChildID: metadata.entityIDs.firstChild, + secondChildID: metadata.entityIDs.secondChild, + }) + ); }, /** diff --git a/x-pack/plugins/security_solution/public/resolver/data_access_layer/mocks/no_ancestors_two_children_with_related_events_on_origin.ts b/x-pack/plugins/security_solution/public/resolver/data_access_layer/mocks/no_ancestors_two_children_with_related_events_on_origin.ts new file mode 100644 index 0000000000000..01e75e3eefdbf --- /dev/null +++ b/x-pack/plugins/security_solution/public/resolver/data_access_layer/mocks/no_ancestors_two_children_with_related_events_on_origin.ts @@ -0,0 +1,94 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { DataAccessLayer } from '../../types'; +import { mockTreeWithNoAncestorsAndTwoChildrenAndRelatedEventsOnOrigin } from '../../mocks/resolver_tree'; +import { + ResolverRelatedEvents, + ResolverTree, + ResolverEntityIndex, +} from '../../../../common/endpoint/types'; + +interface Metadata { + /** + * The `_id` of the document being analyzed. + */ + databaseDocumentID: string; + /** + * A record of entityIDs to be used in tests assertions. + */ + entityIDs: { + /** + * The entityID of the node related to the document being analyzed. + */ + origin: 'origin'; + /** + * The entityID of the first child of the origin. + */ + firstChild: 'firstChild'; + /** + * The entityID of the second child of the origin. + */ + secondChild: 'secondChild'; + }; +} + +export function noAncestorsTwoChildrenWithRelatedEventsOnOrigin(): { + dataAccessLayer: DataAccessLayer; + metadata: Metadata; +} { + const metadata: Metadata = { + databaseDocumentID: '_id', + entityIDs: { origin: 'origin', firstChild: 'firstChild', secondChild: 'secondChild' }, + }; + const tree = mockTreeWithNoAncestorsAndTwoChildrenAndRelatedEventsOnOrigin({ + originID: metadata.entityIDs.origin, + firstChildID: metadata.entityIDs.firstChild, + secondChildID: metadata.entityIDs.secondChild, + }); + + return { + metadata, + dataAccessLayer: { + /** + * Fetch related events for an entity ID + */ + relatedEvents(entityID: string): Promise { + /** + * Respond with the mocked related events when the origin's related events are fetched. + **/ + const events = entityID === metadata.entityIDs.origin ? tree.relatedEvents.events : []; + + return Promise.resolve({ + entityID, + events, + nextEvent: null, + } as ResolverRelatedEvents); + }, + + /** + * Fetch a ResolverTree for a entityID + */ + resolverTree(): Promise { + return Promise.resolve(tree); + }, + + /** + * Get an array of index patterns that contain events. + */ + indexPatterns(): string[] { + return ['index pattern']; + }, + + /** + * Get entities matching a document. + */ + entities(): Promise { + return Promise.resolve([{ entity_id: metadata.entityIDs.origin }]); + }, + }, + }; +} diff --git a/x-pack/plugins/security_solution/public/resolver/store/mocks/endpoint_event.ts b/x-pack/plugins/security_solution/public/resolver/mocks/endpoint_event.ts similarity index 66% rename from x-pack/plugins/security_solution/public/resolver/store/mocks/endpoint_event.ts rename to x-pack/plugins/security_solution/public/resolver/mocks/endpoint_event.ts index 709f2faf13b00..c822fdf647c16 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/mocks/endpoint_event.ts +++ b/x-pack/plugins/security_solution/public/resolver/mocks/endpoint_event.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EndpointEvent } from '../../../../common/endpoint/types'; +import { EndpointEvent } from '../../../common/endpoint/types'; /** * Simple mock endpoint event that works for tree layouts. @@ -28,10 +28,29 @@ export function mockEndpointEvent({ type: lifecycleType ? lifecycleType : 'start', category: 'process', }, + agent: { + id: 'agent.id', + version: 'agent.version', + type: 'agent.type', + }, + ecs: { + version: 'ecs.version', + }, + user: { + name: 'user.name', + domain: 'user.domain', + }, process: { entity_id: entityID, + executable: 'executable', + args: 'args', name, + pid: 0, + hash: { + md5: 'hash.md5', + }, parent: { + pid: 0, entity_id: parentEntityId, }, }, diff --git a/x-pack/plugins/security_solution/public/resolver/store/mocks/resolver_tree.ts b/x-pack/plugins/security_solution/public/resolver/mocks/resolver_tree.ts similarity index 89% rename from x-pack/plugins/security_solution/public/resolver/store/mocks/resolver_tree.ts rename to x-pack/plugins/security_solution/public/resolver/mocks/resolver_tree.ts index 21d0309501aa8..5d2cbb2eab0dc 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/mocks/resolver_tree.ts +++ b/x-pack/plugins/security_solution/public/resolver/mocks/resolver_tree.ts @@ -5,8 +5,7 @@ */ import { mockEndpointEvent } from './endpoint_event'; -import { mockRelatedEvent } from './related_event'; -import { ResolverTree, ResolverEvent } from '../../../../common/endpoint/types'; +import { ResolverTree, ResolverEvent, SafeResolverEvent } from '../../../common/endpoint/types'; export function mockTreeWith2AncestorsAndNoChildren({ originID, @@ -125,11 +124,11 @@ type RelatedEventType = string; * @param treeToAddRelatedEventsTo the ResolverTree to modify * @param relatedEventsToAddByCategoryAndType Iterable of `[category, type]` pairs describing related events. e.g. [['dns','info'],['registry','access']] */ -export function withRelatedEventsOnOrigin( +function withRelatedEventsOnOrigin( treeToAddRelatedEventsTo: ResolverTree, relatedEventsToAddByCategoryAndType: Iterable<[RelatedEventCategory, RelatedEventType]> ): ResolverTree { - const events = []; + const events: SafeResolverEvent[] = []; const byCategory: Record = {}; const stats = { totalAlerts: 0, @@ -139,14 +138,18 @@ export function withRelatedEventsOnOrigin( }, }; for (const [category, type] of relatedEventsToAddByCategoryAndType) { - events.push( - mockRelatedEvent({ - entityID: treeToAddRelatedEventsTo.entityID, - timestamp: 1, - category, + events.push({ + '@timestamp': 1, + event: { + kind: 'event', type, - }) - ); + category, + id: 'xyz', + }, + process: { + entity_id: treeToAddRelatedEventsTo.entityID, + }, + }); stats.events.total++; stats.events.byCategory[category] = stats.events.byCategory[category] ? stats.events.byCategory[category] + 1 @@ -156,7 +159,7 @@ export function withRelatedEventsOnOrigin( ...treeToAddRelatedEventsTo, stats, relatedEvents: { - events, + events: events as ResolverEvent[], nextEvent: null, }, }; @@ -309,3 +312,24 @@ export function mockTreeWithNoProcessEvents(): ResolverTree { }, }; } + +export function mockTreeWithNoAncestorsAndTwoChildrenAndRelatedEventsOnOrigin({ + originID, + firstChildID, + secondChildID, +}: { + originID: string; + firstChildID: string; + secondChildID: string; +}) { + const baseTree = mockTreeWithNoAncestorsAnd2Children({ + originID, + firstChildID, + secondChildID, + }); + const withRelatedEvents: Array<[string, string]> = [ + ['registry', 'access'], + ['registry', 'access'], + ]; + return withRelatedEventsOnOrigin(baseTree, withRelatedEvents); +} diff --git a/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/__snapshots__/isometric_taxi_layout.test.ts.snap b/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/__snapshots__/isometric_taxi_layout.test.ts.snap index 6f26bfe063c05..db8d047c2ce86 100644 --- a/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/__snapshots__/isometric_taxi_layout.test.ts.snap +++ b/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/__snapshots__/isometric_taxi_layout.test.ts.snap @@ -182,7 +182,7 @@ Object { "edgeLineSegments": Array [ Object { "metadata": Object { - "uniqueId": "parentToMid", + "uniqueId": "parentToMidedge:0:1", }, "points": Array [ Array [ @@ -197,7 +197,7 @@ Object { }, Object { "metadata": Object { - "uniqueId": "midway", + "uniqueId": "midwayedge:0:1", }, "points": Array [ Array [ @@ -212,7 +212,7 @@ Object { }, Object { "metadata": Object { - "uniqueId": "", + "uniqueId": "edge:0:1", }, "points": Array [ Array [ @@ -227,7 +227,7 @@ Object { }, Object { "metadata": Object { - "uniqueId": "", + "uniqueId": "edge:0:2", }, "points": Array [ Array [ @@ -242,7 +242,7 @@ Object { }, Object { "metadata": Object { - "uniqueId": "", + "uniqueId": "edge:0:8", }, "points": Array [ Array [ @@ -257,7 +257,7 @@ Object { }, Object { "metadata": Object { - "uniqueId": "parentToMid13", + "uniqueId": "parentToMidedge:1:3", }, "points": Array [ Array [ @@ -272,7 +272,7 @@ Object { }, Object { "metadata": Object { - "uniqueId": "midway13", + "uniqueId": "midwayedge:1:3", }, "points": Array [ Array [ @@ -287,7 +287,7 @@ Object { }, Object { "metadata": Object { - "uniqueId": "13", + "uniqueId": "edge:1:3", }, "points": Array [ Array [ @@ -302,7 +302,7 @@ Object { }, Object { "metadata": Object { - "uniqueId": "14", + "uniqueId": "edge:1:4", }, "points": Array [ Array [ @@ -317,7 +317,7 @@ Object { }, Object { "metadata": Object { - "uniqueId": "parentToMid25", + "uniqueId": "parentToMidedge:2:5", }, "points": Array [ Array [ @@ -332,7 +332,7 @@ Object { }, Object { "metadata": Object { - "uniqueId": "midway25", + "uniqueId": "midwayedge:2:5", }, "points": Array [ Array [ @@ -347,7 +347,7 @@ Object { }, Object { "metadata": Object { - "uniqueId": "25", + "uniqueId": "edge:2:5", }, "points": Array [ Array [ @@ -362,7 +362,7 @@ Object { }, Object { "metadata": Object { - "uniqueId": "26", + "uniqueId": "edge:2:6", }, "points": Array [ Array [ @@ -377,7 +377,7 @@ Object { }, Object { "metadata": Object { - "uniqueId": "67", + "uniqueId": "edge:6:7", }, "points": Array [ Array [ @@ -584,7 +584,7 @@ Object { "edgeLineSegments": Array [ Object { "metadata": Object { - "uniqueId": "", + "uniqueId": "edge:0:1", }, "points": Array [ Array [ diff --git a/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/index.ts b/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/index.ts index 060a014b8730f..f6b893ba25b78 100644 --- a/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/index.ts +++ b/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/index.ts @@ -4,10 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { uniquePidForProcess, uniqueParentPidForProcess, orderByTime } from '../process_event'; +import { orderByTime } from '../process_event'; import { IndexedProcessTree } from '../../types'; -import { ResolverEvent } from '../../../../common/endpoint/types'; +import { SafeResolverEvent } from '../../../../common/endpoint/types'; import { levelOrder as baseLevelOrder } from '../../lib/tree_sequencers'; +import * as eventModel from '../../../../common/endpoint/models/event'; /** * Create a new IndexedProcessTree from an array of ProcessEvents. @@ -15,24 +16,25 @@ import { levelOrder as baseLevelOrder } from '../../lib/tree_sequencers'; */ export function factory( // Array of processes to index as a tree - processes: ResolverEvent[] + processes: SafeResolverEvent[] ): IndexedProcessTree { - const idToChildren = new Map(); - const idToValue = new Map(); + const idToChildren = new Map(); + const idToValue = new Map(); for (const process of processes) { - const uniqueProcessPid = uniquePidForProcess(process); - idToValue.set(uniqueProcessPid, process); + const entityID: string | undefined = eventModel.entityIDSafeVersion(process); + if (entityID !== undefined) { + idToValue.set(entityID, process); - // NB: If the value was null or undefined, use `undefined` - const uniqueParentPid: string | undefined = uniqueParentPidForProcess(process) ?? undefined; + const uniqueParentPid: string | undefined = eventModel.parentEntityIDSafeVersion(process); - let childrenWithTheSameParent = idToChildren.get(uniqueParentPid); - if (!childrenWithTheSameParent) { - childrenWithTheSameParent = []; - idToChildren.set(uniqueParentPid, childrenWithTheSameParent); + let childrenWithTheSameParent = idToChildren.get(uniqueParentPid); + if (!childrenWithTheSameParent) { + childrenWithTheSameParent = []; + idToChildren.set(uniqueParentPid, childrenWithTheSameParent); + } + childrenWithTheSameParent.push(process); } - childrenWithTheSameParent.push(process); } // sort the children of each node @@ -49,7 +51,10 @@ export function factory( /** * Returns an array with any children `ProcessEvent`s of the passed in `process` */ -export function children(tree: IndexedProcessTree, parentID: string | undefined): ResolverEvent[] { +export function children( + tree: IndexedProcessTree, + parentID: string | undefined +): SafeResolverEvent[] { const currentProcessSiblings = tree.idToChildren.get(parentID); return currentProcessSiblings === undefined ? [] : currentProcessSiblings; } @@ -57,7 +62,7 @@ export function children(tree: IndexedProcessTree, parentID: string | undefined) /** * Get the indexed process event for the ID */ -export function processEvent(tree: IndexedProcessTree, entityID: string): ResolverEvent | null { +export function processEvent(tree: IndexedProcessTree, entityID: string): SafeResolverEvent | null { return tree.idToProcess.get(entityID) ?? null; } @@ -66,9 +71,9 @@ export function processEvent(tree: IndexedProcessTree, entityID: string): Resolv */ export function parent( tree: IndexedProcessTree, - childProcess: ResolverEvent -): ResolverEvent | undefined { - const uniqueParentPid = uniqueParentPidForProcess(childProcess); + childProcess: SafeResolverEvent +): SafeResolverEvent | undefined { + const uniqueParentPid = eventModel.parentEntityIDSafeVersion(childProcess); if (uniqueParentPid === undefined) { return undefined; } else { @@ -91,7 +96,7 @@ export function root(tree: IndexedProcessTree) { return null; } // any node will do - let current: ResolverEvent = tree.idToProcess.values().next().value; + let current: SafeResolverEvent = tree.idToProcess.values().next().value; // iteratively swap current w/ its parent while (parent(tree, current) !== undefined) { @@ -106,8 +111,8 @@ export function root(tree: IndexedProcessTree) { export function* levelOrder(tree: IndexedProcessTree) { const rootNode = root(tree); if (rootNode !== null) { - yield* baseLevelOrder(rootNode, (parentNode: ResolverEvent): ResolverEvent[] => - children(tree, uniquePidForProcess(parentNode)) + yield* baseLevelOrder(rootNode, (parentNode: SafeResolverEvent): SafeResolverEvent[] => + children(tree, eventModel.entityIDSafeVersion(parentNode)) ); } } diff --git a/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/isometric_taxi_layout.ts b/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/isometric_taxi_layout.ts index 1fc2ea0150aee..f0880fa635a24 100644 --- a/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/isometric_taxi_layout.ts +++ b/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/isometric_taxi_layout.ts @@ -14,12 +14,11 @@ import { Matrix3, IsometricTaxiLayout, } from '../../types'; -import * as event from '../../../../common/endpoint/models/event'; -import { ResolverEvent } from '../../../../common/endpoint/types'; +import * as eventModel from '../../../../common/endpoint/models/event'; +import { SafeResolverEvent } from '../../../../common/endpoint/types'; import * as vector2 from '../vector2'; import * as indexedProcessTreeModel from './index'; import { getFriendlyElapsedTime as elapsedTime } from '../../lib/date'; -import { uniquePidForProcess } from '../process_event'; /** * Graph the process tree @@ -30,25 +29,29 @@ export function isometricTaxiLayoutFactory( /** * Walk the tree in reverse level order, calculating the 'width' of subtrees. */ - const widths = widthsOfProcessSubtrees(indexedProcessTree); + const widths: Map = widthsOfProcessSubtrees(indexedProcessTree); /** * Walk the tree in level order. Using the precalculated widths, calculate the position of nodes. * Nodes are positioned relative to their parents and preceding siblings. */ - const positions = processPositions(indexedProcessTree, widths); + const positions: Map = processPositions(indexedProcessTree, widths); /** * With the widths and positions precalculated, we calculate edge line segments (arrays of vector2s) * which connect them in a 'pitchfork' design. */ - const edgeLineSegments = processEdgeLineSegments(indexedProcessTree, widths, positions); + const edgeLineSegments: EdgeLineSegment[] = processEdgeLineSegments( + indexedProcessTree, + widths, + positions + ); /** * Transform the positions of nodes and edges so they seem like they are on an isometric grid. */ const transformedEdgeLineSegments: EdgeLineSegment[] = []; - const transformedPositions = new Map(); + const transformedPositions = new Map(); for (const [processEvent, position] of positions) { transformedPositions.set( @@ -83,8 +86,8 @@ export function isometricTaxiLayoutFactory( /** * Calculate a level (starting at 1) for each node. */ -function ariaLevels(indexedProcessTree: IndexedProcessTree): Map { - const map: Map = new Map(); +function ariaLevels(indexedProcessTree: IndexedProcessTree): Map { + const map: Map = new Map(); for (const node of indexedProcessTreeModel.levelOrder(indexedProcessTree)) { const parentNode = indexedProcessTreeModel.parent(indexedProcessTree, node); if (parentNode === undefined) { @@ -143,20 +146,20 @@ function ariaLevels(indexedProcessTree: IndexedProcessTree): Map(); + const widths = new Map(); if (indexedProcessTreeModel.size(indexedProcessTree) === 0) { return widths; } - const processesInReverseLevelOrder: ResolverEvent[] = [ + const processesInReverseLevelOrder: SafeResolverEvent[] = [ ...indexedProcessTreeModel.levelOrder(indexedProcessTree), ].reverse(); for (const process of processesInReverseLevelOrder) { const children = indexedProcessTreeModel.children( indexedProcessTree, - uniquePidForProcess(process) + eventModel.entityIDSafeVersion(process) ); const sumOfWidthOfChildren = function sumOfWidthOfChildren() { @@ -167,7 +170,7 @@ function widthsOfProcessSubtrees(indexedProcessTree: IndexedProcessTree): Proces * Therefore a parent can always find a width for its children, since all of its children * will have been handled already. */ - return currentValue + widths.get(child)!; + return currentValue + (widths.get(child) ?? 0); }, 0); }; @@ -178,6 +181,9 @@ function widthsOfProcessSubtrees(indexedProcessTree: IndexedProcessTree): Proces return widths; } +/** + * Layout the graph. Note: if any process events are missing the `entity_id`, this will throw an Error. + */ function processEdgeLineSegments( indexedProcessTree: IndexedProcessTree, widths: ProcessWidths, @@ -196,9 +202,13 @@ function processEdgeLineSegments( const { process, parent, parentWidth } = metadata; const position = positions.get(process); const parentPosition = positions.get(parent); - const parentId = event.entityId(parent); - const processEntityId = event.entityId(process); - const edgeLineId = parentId ? parentId + processEntityId : parentId; + const parentID = eventModel.entityIDSafeVersion(parent); + const processEntityID = eventModel.entityIDSafeVersion(process); + + if (processEntityID === undefined) { + throw new Error('tried to graph a Resolver that had a process with no `process.entity_id`'); + } + const edgeLineID = `edge:${parentID ?? 'undefined'}:${processEntityID}`; if (position === undefined || parentPosition === undefined) { /** @@ -207,12 +217,12 @@ function processEdgeLineSegments( throw new Error(); } - const parentTime = event.eventTimestamp(parent); - const processTime = event.eventTimestamp(process); + const parentTime = eventModel.timestampSafeVersion(parent); + const processTime = eventModel.timestampSafeVersion(process); if (parentTime && processTime) { edgeLineMetadata.elapsedTime = elapsedTime(parentTime, processTime) ?? undefined; } - edgeLineMetadata.uniqueId = edgeLineId; + edgeLineMetadata.uniqueId = edgeLineID; /** * The point halfway between the parent and child on the y axis, we sometimes have a hard angle here in the edge line @@ -236,7 +246,7 @@ function processEdgeLineSegments( const siblings = indexedProcessTreeModel.children( indexedProcessTree, - uniquePidForProcess(parent) + eventModel.entityIDSafeVersion(parent) ); const isFirstChild = process === siblings[0]; @@ -260,7 +270,7 @@ function processEdgeLineSegments( const lineFromParentToMidwayLine: EdgeLineSegment = { points: [parentPosition, [parentPosition[0], midwayY]], - metadata: { uniqueId: `parentToMid${edgeLineId}` }, + metadata: { uniqueId: `parentToMid${edgeLineID}` }, }; const widthOfMidline = parentWidth - firstChildWidth / 2 - lastChildWidth / 2; @@ -281,7 +291,7 @@ function processEdgeLineSegments( midwayY, ], ], - metadata: { uniqueId: `midway${edgeLineId}` }, + metadata: { uniqueId: `midway${edgeLineID}` }, }; edgeLineSegments.push( @@ -303,13 +313,13 @@ function processPositions( indexedProcessTree: IndexedProcessTree, widths: ProcessWidths ): ProcessPositions { - const positions = new Map(); + const positions = new Map(); /** * This algorithm iterates the tree in level order. It keeps counters that are reset for each parent. * By keeping track of the last parent node, we can know when we are dealing with a new set of siblings and * reset the counters. */ - let lastProcessedParentNode: ResolverEvent | undefined; + let lastProcessedParentNode: SafeResolverEvent | undefined; /** * Nodes are positioned relative to their siblings. We walk this in level order, so we handle * children left -> right. @@ -431,7 +441,10 @@ function* levelOrderWithWidths( parentWidth, }; - const siblings = indexedProcessTreeModel.children(tree, uniquePidForProcess(parent)); + const siblings = indexedProcessTreeModel.children( + tree, + eventModel.entityIDSafeVersion(parent) + ); if (siblings.length === 1) { metadata.isOnlyChild = true; metadata.lastChildWidth = width; @@ -488,7 +501,10 @@ const distanceBetweenNodesInUnits = 2; */ const distanceBetweenNodes = distanceBetweenNodesInUnits * unit; -export function nodePosition(model: IsometricTaxiLayout, node: ResolverEvent): Vector2 | undefined { +export function nodePosition( + model: IsometricTaxiLayout, + node: SafeResolverEvent +): Vector2 | undefined { return model.processNodePositions.get(node); } diff --git a/x-pack/plugins/security_solution/public/resolver/models/process_event.test.ts b/x-pack/plugins/security_solution/public/resolver/models/process_event.test.ts index 4b1d555d0a7c3..4d48b34fb2841 100644 --- a/x-pack/plugins/security_solution/public/resolver/models/process_event.test.ts +++ b/x-pack/plugins/security_solution/public/resolver/models/process_event.test.ts @@ -6,7 +6,11 @@ import { eventType, orderByTime, userInfoForProcess } from './process_event'; import { mockProcessEvent } from './process_event_test_helpers'; -import { LegacyEndpointEvent, ResolverEvent } from '../../../common/endpoint/types'; +import { + LegacyEndpointEvent, + ResolverEvent, + SafeResolverEvent, +} from '../../../common/endpoint/types'; describe('process event', () => { describe('eventType', () => { @@ -42,7 +46,7 @@ describe('process event', () => { }); describe('orderByTime', () => { let mock: (time: number, eventID: string) => ResolverEvent; - let events: ResolverEvent[]; + let events: SafeResolverEvent[]; beforeEach(() => { mock = (time, eventID) => { return { @@ -56,14 +60,14 @@ describe('process event', () => { // each event has a unique id, a through h // order is arbitrary events = [ - mock(-1, 'a'), - mock(0, 'c'), - mock(1, 'e'), - mock(NaN, 'g'), - mock(-1, 'b'), - mock(0, 'd'), - mock(1, 'f'), - mock(NaN, 'h'), + mock(-1, 'a') as SafeResolverEvent, + mock(0, 'c') as SafeResolverEvent, + mock(1, 'e') as SafeResolverEvent, + mock(NaN, 'g') as SafeResolverEvent, + mock(-1, 'b') as SafeResolverEvent, + mock(0, 'd') as SafeResolverEvent, + mock(1, 'f') as SafeResolverEvent, + mock(NaN, 'h') as SafeResolverEvent, ]; }); it('sorts events as expected', () => { diff --git a/x-pack/plugins/security_solution/public/resolver/models/process_event.ts b/x-pack/plugins/security_solution/public/resolver/models/process_event.ts index 1a5c67f6a6f2f..ea588731a55c8 100644 --- a/x-pack/plugins/security_solution/public/resolver/models/process_event.ts +++ b/x-pack/plugins/security_solution/public/resolver/models/process_event.ts @@ -5,7 +5,7 @@ */ import * as event from '../../../common/endpoint/models/event'; -import { ResolverEvent } from '../../../common/endpoint/types'; +import { ResolverEvent, SafeResolverEvent } from '../../../common/endpoint/types'; import { ResolverProcessType } from '../types'; /** @@ -32,8 +32,8 @@ export function isTerminatedProcess(passedEvent: ResolverEvent) { * ms since Unix epoc, based on timestamp. * may return NaN if the timestamp wasn't present or was invalid. */ -export function datetime(passedEvent: ResolverEvent): number | null { - const timestamp = event.eventTimestamp(passedEvent); +export function datetime(passedEvent: SafeResolverEvent): number | null { + const timestamp = event.timestampSafeVersion(passedEvent); const time = timestamp === undefined ? 0 : new Date(timestamp).getTime(); @@ -178,13 +178,15 @@ export function argsForProcess(passedEvent: ResolverEvent): string | undefined { /** * used to sort events */ -export function orderByTime(first: ResolverEvent, second: ResolverEvent): number { +export function orderByTime(first: SafeResolverEvent, second: SafeResolverEvent): number { const firstDatetime: number | null = datetime(first); const secondDatetime: number | null = datetime(second); if (firstDatetime === secondDatetime) { // break ties using an arbitrary (stable) comparison of `eventId` (which should be unique) - return String(event.eventId(first)).localeCompare(String(event.eventId(second))); + return String(event.eventIDSafeVersion(first)).localeCompare( + String(event.eventIDSafeVersion(second)) + ); } else if (firstDatetime === null || secondDatetime === null) { // sort `null`'s as higher than numbers return (firstDatetime === null ? 1 : 0) - (secondDatetime === null ? 1 : 0); diff --git a/x-pack/plugins/security_solution/public/resolver/store/actions.ts b/x-pack/plugins/security_solution/public/resolver/store/actions.ts index 418eb0d837276..29c03215e9ff4 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/actions.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/actions.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { CameraAction } from './camera'; -import { ResolverEvent } from '../../../common/endpoint/types'; +import { ResolverEvent, SafeResolverEvent } from '../../../common/endpoint/types'; import { DataAction } from './data/action'; /** @@ -96,7 +96,7 @@ interface UserSelectedResolverNode { interface UserSelectedRelatedEventCategory { readonly type: 'userSelectedRelatedEventCategory'; readonly payload: { - subject: ResolverEvent; + subject: SafeResolverEvent; category?: string; }; } diff --git a/x-pack/plugins/security_solution/public/resolver/store/data/selectors.test.ts b/x-pack/plugins/security_solution/public/resolver/store/data/selectors.test.ts index 6786a93f1d9ca..15a981d460730 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/data/selectors.test.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/data/selectors.test.ts @@ -15,7 +15,7 @@ import { mockTreeWith1AncestorAnd2ChildrenAndAllNodesHave2GraphableEvents, mockTreeWithAllProcessesTerminated, mockTreeWithNoProcessEvents, -} from '../mocks/resolver_tree'; +} from '../../mocks/resolver_tree'; import { uniquePidForProcess } from '../../models/process_event'; import { EndpointEvent } from '../../../../common/endpoint/types'; diff --git a/x-pack/plugins/security_solution/public/resolver/store/data/selectors.ts b/x-pack/plugins/security_solution/public/resolver/store/data/selectors.ts index 272d0aae7eef4..569a24bb8537e 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/data/selectors.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/data/selectors.ts @@ -28,10 +28,11 @@ import { ResolverTree, ResolverNodeStats, ResolverRelatedEvents, + SafeResolverEvent, } from '../../../../common/endpoint/types'; import * as resolverTreeModel from '../../models/resolver_tree'; import * as isometricTaxiLayoutModel from '../../models/indexed_process_tree/isometric_taxi_layout'; -import { allEventCategories } from '../../../../common/endpoint/models/event'; +import * as eventModel from '../../../../common/endpoint/models/event'; import * as vector2 from '../../models/vector2'; /** @@ -145,7 +146,7 @@ export const tree = createSelector(graphableProcesses, function indexedTree( graphableProcesses /* eslint-enable no-shadow */ ) { - return indexedProcessTreeModel.factory(graphableProcesses); + return indexedProcessTreeModel.factory(graphableProcesses as SafeResolverEvent[]); }); /** @@ -194,7 +195,9 @@ export const relatedEventsByCategory: ( } return relatedById.events.reduce( (eventsByCategory: ResolverEvent[], candidate: ResolverEvent) => { - if ([candidate && allEventCategories(candidate)].flat().includes(ecsCategory)) { + if ( + [candidate && eventModel.allEventCategories(candidate)].flat().includes(ecsCategory) + ) { eventsByCategory.push(candidate); } return eventsByCategory; @@ -280,7 +283,7 @@ export const relatedEventInfoByEntityId: ( return []; } return eventsResponseForThisEntry.events.filter((resolverEvent) => { - for (const category of [allEventCategories(resolverEvent)].flat()) { + for (const category of [eventModel.allEventCategories(resolverEvent)].flat()) { if (category === eventCategory) { return true; } @@ -404,7 +407,7 @@ export const processEventForID: ( ) => (nodeID: string) => ResolverEvent | null = createSelector( tree, (indexedProcessTree) => (nodeID: string) => - indexedProcessTreeModel.processEvent(indexedProcessTree, nodeID) + indexedProcessTreeModel.processEvent(indexedProcessTree, nodeID) as ResolverEvent ); /** @@ -415,7 +418,7 @@ export const ariaLevel: (state: DataState) => (nodeID: string) => number | null processEventForID, ({ ariaLevels }, processEventGetter) => (nodeID: string) => { const node = processEventGetter(nodeID); - return node ? ariaLevels.get(node) ?? null : null; + return node ? ariaLevels.get(node as SafeResolverEvent) ?? null : null; } ); @@ -468,10 +471,10 @@ export const ariaFlowtoCandidate: ( for (const child of children) { if (previousChild !== null) { // Set the `child` as the following sibling of `previousChild`. - memo.set(uniquePidForProcess(previousChild), uniquePidForProcess(child)); + memo.set(uniquePidForProcess(previousChild), uniquePidForProcess(child as ResolverEvent)); } // Set the child as the previous child. - previousChild = child; + previousChild = child as ResolverEvent; } if (previousChild) { @@ -553,7 +556,7 @@ export const nodesAndEdgelines: ( maxX, maxY, }); - const visibleProcessNodePositions = new Map( + const visibleProcessNodePositions = new Map( entities .filter((entity): entity is IndexedProcessNode => entity.type === 'processNode') .map((node) => [node.entity, node.position]) diff --git a/x-pack/plugins/security_solution/public/resolver/store/methods.ts b/x-pack/plugins/security_solution/public/resolver/store/methods.ts index ad06ddf36161a..8dd15b1a44d0c 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/methods.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/methods.ts @@ -7,7 +7,7 @@ import { animatePanning } from './camera/methods'; import { layout } from './selectors'; import { ResolverState } from '../types'; -import { ResolverEvent } from '../../../common/endpoint/types'; +import { ResolverEvent, SafeResolverEvent } from '../../../common/endpoint/types'; const animationDuration = 1000; @@ -20,7 +20,7 @@ export function animateProcessIntoView( process: ResolverEvent ): ResolverState { const { processNodePositions } = layout(state); - const position = processNodePositions.get(process); + const position = processNodePositions.get(process as SafeResolverEvent); if (position) { return { ...state, diff --git a/x-pack/plugins/security_solution/public/resolver/store/mocks/related_event.ts b/x-pack/plugins/security_solution/public/resolver/store/mocks/related_event.ts deleted file mode 100644 index 1e0c460a3a711..0000000000000 --- a/x-pack/plugins/security_solution/public/resolver/store/mocks/related_event.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import { EndpointEvent } from '../../../../common/endpoint/types'; - -/** - * Simple mock related event. - */ -export function mockRelatedEvent({ - entityID, - timestamp, - category, - type, - id, -}: { - entityID: string; - timestamp: number; - category: string; - type: string; - id?: string; -}): EndpointEvent { - return { - '@timestamp': timestamp, - event: { - kind: 'event', - type, - category, - id: id ?? 'xyz', - }, - process: { - entity_id: entityID, - }, - } as EndpointEvent; -} diff --git a/x-pack/plugins/security_solution/public/resolver/store/selectors.test.ts b/x-pack/plugins/security_solution/public/resolver/store/selectors.test.ts index df365a078b27f..f113e861d3ce9 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/selectors.test.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/selectors.test.ts @@ -12,7 +12,8 @@ import * as selectors from './selectors'; import { mockTreeWith2AncestorsAndNoChildren, mockTreeWithNoAncestorsAnd2Children, -} from './mocks/resolver_tree'; +} from '../mocks/resolver_tree'; +import { SafeResolverEvent } from '../../../common/endpoint/types'; describe('resolver selectors', () => { const actions: ResolverAction[] = []; @@ -114,7 +115,9 @@ describe('resolver selectors', () => { // find the position of the second child const secondChild = selectors.processEventForID(state())(secondChildID); - const positionOfSecondChild = layout.processNodePositions.get(secondChild!)!; + const positionOfSecondChild = layout.processNodePositions.get( + secondChild as SafeResolverEvent + )!; // the child is indexed by an AABB that extends -720/2 to the left const leftSideOfSecondChildAABB = positionOfSecondChild[0] - 720 / 2; @@ -130,19 +133,25 @@ describe('resolver selectors', () => { it('the origin should be in view', () => { const origin = selectors.processEventForID(state())(originID)!; expect( - selectors.visibleNodesAndEdgeLines(state())(0).processNodePositions.has(origin) + selectors + .visibleNodesAndEdgeLines(state())(0) + .processNodePositions.has(origin as SafeResolverEvent) ).toBe(true); }); it('the first child should be in view', () => { const firstChild = selectors.processEventForID(state())(firstChildID)!; expect( - selectors.visibleNodesAndEdgeLines(state())(0).processNodePositions.has(firstChild) + selectors + .visibleNodesAndEdgeLines(state())(0) + .processNodePositions.has(firstChild as SafeResolverEvent) ).toBe(true); }); it('the second child should not be in view', () => { const secondChild = selectors.processEventForID(state())(secondChildID)!; expect( - selectors.visibleNodesAndEdgeLines(state())(0).processNodePositions.has(secondChild) + selectors + .visibleNodesAndEdgeLines(state())(0) + .processNodePositions.has(secondChild as SafeResolverEvent) ).toBe(false); }); it('should return nothing as the flowto for the first child', () => { diff --git a/x-pack/plugins/security_solution/public/resolver/store/selectors.ts b/x-pack/plugins/security_solution/public/resolver/store/selectors.ts index 87ef8d5d095ef..70a461909a99b 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/selectors.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/selectors.ts @@ -9,8 +9,8 @@ import * as cameraSelectors from './camera/selectors'; import * as dataSelectors from './data/selectors'; import * as uiSelectors from './ui/selectors'; import { ResolverState, IsometricTaxiLayout } from '../types'; -import { uniquePidForProcess } from '../models/process_event'; import { ResolverEvent, ResolverNodeStats } from '../../../common/endpoint/types'; +import { entityIDSafeVersion } from '../../../common/endpoint/models/event'; /** * A matrix that when applied to a Vector2 will convert it from world coordinates to screen coordinates. @@ -271,9 +271,14 @@ export const ariaFlowtoNodeID: ( const { processNodePositions } = visibleNodesAndEdgeLinesAtTime(time); // get a `Set` containing their node IDs - const nodesVisibleAtTime: Set = new Set( - [...processNodePositions.keys()].map(uniquePidForProcess) - ); + const nodesVisibleAtTime: Set = new Set(); + // NB: in practice, any event that has been graphed is guaranteed to have an entity_id + for (const visibleEvent of processNodePositions.keys()) { + const nodeID = entityIDSafeVersion(visibleEvent); + if (nodeID !== undefined) { + nodesVisibleAtTime.add(nodeID); + } + } // return the ID of `nodeID`'s following sibling, if it is visible return (nodeID: string): string | null => { diff --git a/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx b/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx index ed30643ed871e..6f44c5aee7cac 100644 --- a/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx +++ b/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx @@ -113,83 +113,21 @@ export class Simulator { } /** - * Return a promise that resolves after the `store`'s next state transition. - * Used by `mapStateTransitions` + * Yield the result of `mapper` over and over, once per event-loop cycle. + * After 10 times, quit. + * Use this to continually check a value. See `toYieldEqualTo`. */ - private stateTransitioned(): Promise { - // keep track of the resolve function of the promise that has been returned. - let resolveState: (() => void) | null = null; - - const promise: Promise = new Promise((resolve) => { - // Immediately expose the resolve function in the outer scope. It will be resolved when the next state transition occurs. - resolveState = resolve; - }); - - // Subscribe to the store - const unsubscribe = this.store.subscribe(() => { - // Once a state transition occurs, unsubscribe. - unsubscribe(); - // Resolve the promise. The null assertion is safe here as Promise initializers run immediately (according to spec and node/browser implementations.) - // NB: the state is not resolved here. Code using the simulator should not rely on state or selectors of state. - resolveState!(); - }); - - // Return the promise that will be resolved on the next state transition, allowing code to `await` for the next state transition. - return promise; - } - - /** - * This will yield the return value of `mapper` after each state transition. If no state transition occurs for 10 event loops in a row, this will give up. - */ - public async *mapStateTransitions(mapper: () => R): AsyncIterable { - // Yield the value before any state transitions have occurred. - yield mapper(); - - /** Increment this each time an event loop completes without a state transition. - * If this value hits `10`, end the loop. - * - * Code will test assertions after each state transition. If the assertion hasn't passed and no further state transitions occur, - * then the jest timeout will happen. The timeout doesn't give a useful message about the assertion. - * By short-circuiting this function, code that uses it can short circuit the test timeout and print a useful error message. - * - * NB: the logic to short-circuit the loop is here because knowledge of state is a concern of the simulator, not tests. - */ + public async *map(mapper: () => R): AsyncIterable { let timeoutCount = 0; - while (true) { - /** - * `await` a race between the next state transition and a timeout that happens after `0`ms. - * If the timeout wins, no `dispatch` call caused a state transition in the last loop. - * If this keeps happening, assume that Resolver isn't going to do anything else. - * - * If Resolver adds intentional delay logic (e.g. waiting before making a request), this code might have to change. - * In that case, Resolver should use the side effect context to schedule future work. This code could then subscribe to some event published by the side effect context. That way, this code will be aware of Resolver's intention to do work. - */ - const timedOut: boolean = await Promise.race([ - (async (): Promise => { - await this.stateTransitioned(); - // If a state transition occurs, return false for `timedOut` - return false; - })(), - new Promise((resolve) => { - setTimeout(() => { - // If a timeout occurs, resolve `timedOut` as true - return resolve(true); - }, 0); - }), - ]); - - if (timedOut) { - // If a timout occurred, note it. - timeoutCount++; - if (timeoutCount === 10) { - // if 10 timeouts happen in a row, end the loop early - return; - } - } else { - // If a state transition occurs, reset the timeout count and yield the value - timeoutCount = 0; - yield mapper(); - } + while (timeoutCount < 10) { + timeoutCount++; + yield mapper(); + await new Promise((resolve) => { + setTimeout(() => { + this.wrapper.update(); + resolve(); + }, 0); + }); } } @@ -198,25 +136,22 @@ export class Simulator { * returns a `ReactWrapper` even if nothing is found, as that is how `enzyme` does things. */ public processNodeElements(options: ProcessNodeElementSelectorOptions = {}): ReactWrapper { - return this.findInDOM(processNodeElementSelector(options)); + return this.domNodes(processNodeElementSelector(options)); } /** - * true if a process node element is found for the entityID and if it has an [aria-selected] attribute. + * Return the node element with the given `entityID`. */ - public processNodeElementLooksSelected(entityID: string): boolean { - return this.processNodeElements({ entityID, selected: true }).length === 1; + public selectedProcessNode(entityID: string): ReactWrapper { + return this.processNodeElements({ entityID, selected: true }); } /** - * true if a process node element is found for the entityID and if it *does not have* an [aria-selected] attribute. + * Return the node element with the given `entityID`. It will only be returned if it is not selected. */ - public processNodeElementLooksUnselected(entityID: string): boolean { - // find the process node, then exclude it if its selected. - return ( - this.processNodeElements({ entityID }).not( - processNodeElementSelector({ entityID, selected: true }) - ).length === 1 + public unselectedProcessNode(entityID: string): ReactWrapper { + return this.processNodeElements({ entityID }).not( + processNodeElementSelector({ entityID, selected: true }) ); } @@ -234,11 +169,8 @@ export class Simulator { * @param entityID The entity ID of the proocess node to select in */ public processNodeRelatedEventButton(entityID: string): ReactWrapper { - return this.processNodeElements({ entityID }).findWhere( - (wrapper) => - // Filter out React components - typeof wrapper.type() === 'string' && - wrapper.prop('data-test-subj') === 'resolver:submenu:button' + return this.domNodes( + `${processNodeElementSelector({ entityID })} [data-test-subj="resolver:submenu:button"]` ); } @@ -256,42 +188,98 @@ export class Simulator { * The element that shows when Resolver is waiting for the graph data. */ public graphLoadingElement(): ReactWrapper { - return this.findInDOM('[data-test-subj="resolver:graph:loading"]'); + return this.domNodes('[data-test-subj="resolver:graph:loading"]'); } /** * The element that shows if Resolver couldn't draw the graph. */ public graphErrorElement(): ReactWrapper { - return this.findInDOM('[data-test-subj="resolver:graph:error"]'); + return this.domNodes('[data-test-subj="resolver:graph:error"]'); } /** * The element where nodes get drawn. */ public graphElement(): ReactWrapper { - return this.findInDOM('[data-test-subj="resolver:graph"]'); + return this.domNodes('[data-test-subj="resolver:graph"]'); + } + + /** + * An element with a list of all nodes. + */ + public nodeListElement(): ReactWrapper { + return this.domNodes('[data-test-subj="resolver:node-list"]'); + } + + /** + * Return the items in the node list (the default panel view.) + */ + public nodeListItems(): ReactWrapper { + return this.domNodes('[data-test-subj="resolver:node-list:item"]'); + } + + /** + * The element containing the details for the selected node. + */ + public nodeDetailElement(): ReactWrapper { + return this.domNodes('[data-test-subj="resolver:node-detail"]'); + } + + /** + * The details of the selected node are shown in a description list. This returns the title elements of the description list. + */ + private nodeDetailEntryTitle(): ReactWrapper { + return this.domNodes('[data-test-subj="resolver:node-detail:entry-title"]'); } /** - * The outer panel container. + * The details of the selected node are shown in a description list. This returns the description elements of the description list. */ - public panelElement(): ReactWrapper { - return this.findInDOM('[data-test-subj="resolver:panel"]'); + private nodeDetailEntryDescription(): ReactWrapper { + return this.domNodes('[data-test-subj="resolver:node-detail:entry-description"]'); } /** - * The panel content element (which may include tables, lists, other data depending on the view). + * Return DOM nodes that match `enzymeSelector`. */ - public panelContentElement(): ReactWrapper { - return this.findInDOM('[data-test-subj^="resolver:panel:"]'); + private domNodes(enzymeSelector: string): ReactWrapper { + return this.wrapper + .find(enzymeSelector) + .filterWhere((wrapper) => typeof wrapper.type() === 'string'); } /** - * Like `this.wrapper.find` but only returns DOM nodes. + * The titles and descriptions (as text) from the node detail panel. */ - private findInDOM(selector: string): ReactWrapper { - return this.wrapper.find(selector).filterWhere((wrapper) => typeof wrapper.type() === 'string'); + public nodeDetailDescriptionListEntries(): Array<[string, string]> { + const titles = this.nodeDetailEntryTitle(); + const descriptions = this.nodeDetailEntryDescription(); + const entries: Array<[string, string]> = []; + for (let index = 0; index < Math.min(titles.length, descriptions.length); index++) { + const title = titles.at(index).text(); + const description = descriptions.at(index).text(); + + // Exclude timestamp since we can't currently calculate the expected description for it from tests + if (title !== '@timestamp') { + entries.push([title, description]); + } + } + return entries; + } + + /** + * Resolve the wrapper returned by `wrapperFactory` only once it has at least 1 element in it. + */ + public async resolveWrapper( + wrapperFactory: () => ReactWrapper, + predicate: (wrapper: ReactWrapper) => boolean = (wrapper) => wrapper.length > 0 + ): Promise { + for await (const wrapper of this.map(wrapperFactory)) { + if (predicate(wrapper)) { + return wrapper; + } + } } } diff --git a/x-pack/plugins/security_solution/public/resolver/types.ts b/x-pack/plugins/security_solution/public/resolver/types.ts index c2871fdceb20a..30634e722050f 100644 --- a/x-pack/plugins/security_solution/public/resolver/types.ts +++ b/x-pack/plugins/security_solution/public/resolver/types.ts @@ -11,10 +11,10 @@ import { Middleware, Dispatch } from 'redux'; import { BBox } from 'rbush'; import { ResolverAction } from './store/actions'; import { - ResolverEvent, ResolverRelatedEvents, ResolverTree, ResolverEntityIndex, + SafeResolverEvent, } from '../../common/endpoint/types'; /** @@ -155,7 +155,7 @@ export interface IndexedEdgeLineSegment extends BBox { */ export interface IndexedProcessNode extends BBox { type: 'processNode'; - entity: ResolverEvent; + entity: SafeResolverEvent; position: Vector2; } @@ -280,21 +280,21 @@ export interface IndexedProcessTree { /** * Map of ID to a process's ordered children */ - idToChildren: Map; + idToChildren: Map; /** * Map of ID to process */ - idToProcess: Map; + idToProcess: Map; } /** * A map of `ProcessEvents` (representing process nodes) to the 'width' of their subtrees as calculated by `widthsOfProcessSubtrees` */ -export type ProcessWidths = Map; +export type ProcessWidths = Map; /** * Map of ProcessEvents (representing process nodes) to their positions. Calculated by `processPositions` */ -export type ProcessPositions = Map; +export type ProcessPositions = Map; export type DurationTypes = | 'millisecond' @@ -346,11 +346,11 @@ export interface EdgeLineSegment { * Used to provide pre-calculated info from `widthsOfProcessSubtrees`. These 'width' values are used in the layout of the graph. */ export type ProcessWithWidthMetadata = { - process: ResolverEvent; + process: SafeResolverEvent; width: number; } & ( | { - parent: ResolverEvent; + parent: SafeResolverEvent; parentWidth: number; isOnlyChild: boolean; firstChildWidth: number; @@ -433,7 +433,7 @@ export interface IsometricTaxiLayout { /** * A map of events to position. Each event represents its own node. */ - processNodePositions: Map; + processNodePositions: Map; /** * A map of edge-line segments, which graphically connect nodes. */ @@ -442,7 +442,7 @@ export interface IsometricTaxiLayout { /** * defines the aria levels for nodes. */ - ariaLevels: Map; + ariaLevels: Map; } /** diff --git a/x-pack/plugins/security_solution/public/resolver/view/clickthrough.test.tsx b/x-pack/plugins/security_solution/public/resolver/view/clickthrough.test.tsx index c819491dd28f0..98ea235d3524f 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/clickthrough.test.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/clickthrough.test.tsx @@ -4,10 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { oneAncestorTwoChildren } from '../data_access_layer/mocks/one_ancestor_two_children'; +import { noAncestorsTwoChildren } from '../data_access_layer/mocks/no_ancestors_two_children'; import { Simulator } from '../test_utilities/simulator'; // Extend jest with a custom matcher import '../test_utilities/extend_jest'; +import { noAncestorsTwoChildrenWithRelatedEventsOnOrigin } from '../data_access_layer/mocks/no_ancestors_two_children_with_related_events_on_origin'; let simulator: Simulator; let databaseDocumentID: string; @@ -16,10 +17,10 @@ let entityIDs: { origin: string; firstChild: string; secondChild: string }; // the resolver component instance ID, used by the react code to distinguish piece of global state from those used by other resolver instances const resolverComponentInstanceID = 'resolverComponentInstanceID'; -describe('Resolver, when analyzing a tree that has 1 ancestor and 2 children', () => { +describe('Resolver, when analyzing a tree that has no ancestors and 2 children', () => { beforeEach(async () => { // create a mock data access layer - const { metadata: dataAccessLayerMetadata, dataAccessLayer } = oneAncestorTwoChildren(); + const { metadata: dataAccessLayerMetadata, dataAccessLayer } = noAncestorsTwoChildren(); // save a reference to the entity IDs exposed by the mock data layer entityIDs = dataAccessLayerMetadata.entityIDs; @@ -40,7 +41,7 @@ describe('Resolver, when analyzing a tree that has 1 ancestor and 2 children', ( * * For example, there might be no loading element at one point, and 1 graph element at one point, but never a single time when there is both 1 graph element and 0 loading elements. */ - simulator.mapStateTransitions(() => ({ + simulator.map(() => ({ graphElements: simulator.graphElement().length, graphLoadingElements: simulator.graphLoadingElement().length, graphErrorElements: simulator.graphErrorElement().length, @@ -55,22 +56,23 @@ describe('Resolver, when analyzing a tree that has 1 ancestor and 2 children', ( // Combining assertions here for performance. Unfortunately, Enzyme + jsdom + React is slow. it(`should have 3 nodes, with the entityID's 'origin', 'firstChild', and 'secondChild'. 'origin' should be selected.`, async () => { - expect(simulator.processNodeElementLooksSelected(entityIDs.origin)).toBe(true); - - expect(simulator.processNodeElementLooksUnselected(entityIDs.firstChild)).toBe(true); - expect(simulator.processNodeElementLooksUnselected(entityIDs.secondChild)).toBe(true); - - expect(simulator.processNodeElements().length).toBe(3); + await expect( + simulator.map(() => ({ + selectedOriginCount: simulator.selectedProcessNode(entityIDs.origin).length, + unselectedFirstChildCount: simulator.unselectedProcessNode(entityIDs.firstChild).length, + unselectedSecondChildCount: simulator.unselectedProcessNode(entityIDs.secondChild).length, + processNodeCount: simulator.processNodeElements().length, + })) + ).toYieldEqualTo({ + selectedOriginCount: 1, + unselectedFirstChildCount: 1, + unselectedSecondChildCount: 1, + processNodeCount: 3, + }); }); - it(`should have the default "process list" panel present`, async () => { - expect(simulator.panelElement().length).toBe(1); - expect(simulator.panelContentElement().length).toBe(1); - const testSubjectName = simulator - .panelContentElement() - .getDOMNode() - .getAttribute('data-test-subj'); - expect(testSubjectName).toMatch(/process-list/g); + it(`should show the node list`, async () => { + await expect(simulator.map(() => simulator.nodeListElement().length)).toYieldEqualTo(1); }); describe("when the second child node's first button has been clicked", () => { @@ -82,42 +84,37 @@ describe('Resolver, when analyzing a tree that has 1 ancestor and 2 children', ( .first() .simulate('click'); }); - it('should render the second child node as selected, and the first child not as not selected, and the query string should indicate that the second child is selected', async () => { + it('should render the second child node as selected, and the origin as not selected, and the query string should indicate that the second child is selected', async () => { await expect( - simulator.mapStateTransitions(function value() { - return { - // the query string has a key showing that the second child is selected - queryStringSelectedNode: simulator.queryStringValues().selectedNode, - // the second child is rendered in the DOM, and shows up as selected - secondChildLooksSelected: simulator.processNodeElementLooksSelected( - entityIDs.secondChild - ), - // the origin is in the DOM, but shows up as unselected - originLooksUnselected: simulator.processNodeElementLooksUnselected(entityIDs.origin), - }; - }) + simulator.map(() => ({ + // the query string has a key showing that the second child is selected + queryStringSelectedNode: simulator.queryStringValues().selectedNode, + // the second child is rendered in the DOM, and shows up as selected + selectedSecondChildNodeCount: simulator.selectedProcessNode(entityIDs.secondChild) + .length, + // the origin is in the DOM, but shows up as unselected + unselectedOriginNodeCount: simulator.unselectedProcessNode(entityIDs.origin).length, + })) ).toYieldEqualTo({ // Just the second child should be marked as selected in the query string queryStringSelectedNode: [entityIDs.secondChild], // The second child is rendered and has `[aria-selected]` - secondChildLooksSelected: true, + selectedSecondChildNodeCount: 1, // The origin child is rendered and doesn't have `[aria-selected]` - originLooksUnselected: true, + unselectedOriginNodeCount: 1, }); }); }); }); }); -describe('Resolver, when analyzing a tree that has some related events', () => { +describe('Resolver, when analyzing a tree that has two related events for the origin', () => { beforeEach(async () => { // create a mock data access layer with related events - const { metadata: dataAccessLayerMetadata, dataAccessLayer } = oneAncestorTwoChildren({ - withRelatedEvents: [ - ['registry', 'access'], - ['registry', 'access'], - ], - }); + const { + metadata: dataAccessLayerMetadata, + dataAccessLayer, + } = noAncestorsTwoChildrenWithRelatedEventsOnOrigin(); // save a reference to the entity IDs exposed by the mock data layer entityIDs = dataAccessLayerMetadata.entityIDs; @@ -132,7 +129,7 @@ describe('Resolver, when analyzing a tree that has some related events', () => { describe('when it has loaded', () => { beforeEach(async () => { await expect( - simulator.mapStateTransitions(() => ({ + simulator.map(() => ({ graphElements: simulator.graphElement().length, graphLoadingElements: simulator.graphLoadingElement().length, graphErrorElements: simulator.graphErrorElement().length, @@ -148,7 +145,7 @@ describe('Resolver, when analyzing a tree that has some related events', () => { it('should render a related events button', async () => { await expect( - simulator.mapStateTransitions(() => ({ + simulator.map(() => ({ relatedEventButtons: simulator.processNodeRelatedEventButton(entityIDs.origin).length, })) ).toYieldEqualTo({ diff --git a/x-pack/plugins/security_solution/public/resolver/view/map.tsx b/x-pack/plugins/security_solution/public/resolver/view/map.tsx index a965f06c04926..bbff2388af8b7 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/map.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/map.tsx @@ -20,7 +20,7 @@ import { SymbolDefinitions, useResolverTheme } from './assets'; import { useStateSyncingActions } from './use_state_syncing_actions'; import { useResolverQueryParams } from './use_resolver_query_params'; import { StyledMapContainer, StyledPanel, GraphContainer } from './styles'; -import { entityId } from '../../../common/endpoint/models/event'; +import { entityIDSafeVersion } from '../../../common/endpoint/models/event'; import { SideEffectContext } from './side_effect_context'; /** @@ -107,7 +107,7 @@ export const ResolverMap = React.memo(function ({ /> ))} {[...processNodePositions].map(([processEvent, position]) => { - const processEntityId = entityId(processEvent); + const processEntityId = entityIDSafeVersion(processEvent); return ( { + let simulator: Simulator; + let databaseDocumentID: string; + + // the resolver component instance ID, used by the react code to distinguish piece of global state from those used by other resolver instances + const resolverComponentInstanceID = 'resolverComponentInstanceID'; + + beforeEach(async () => { + // create a mock data access layer + const { metadata: dataAccessLayerMetadata, dataAccessLayer } = noAncestorsTwoChildren(); + + // save a reference to the `_id` supported by the mock data layer + databaseDocumentID = dataAccessLayerMetadata.databaseDocumentID; + + // create a resolver simulator, using the data access layer and an arbitrary component instance ID + simulator = new Simulator({ databaseDocumentID, dataAccessLayer, resolverComponentInstanceID }); + }); + + it('should show the node list', async () => { + await expect(simulator.map(() => simulator.nodeListElement().length)).toYieldEqualTo(1); + }); + + it('should have 3 nodes in the node list', async () => { + await expect(simulator.map(() => simulator.nodeListItems().length)).toYieldEqualTo(3); + }); + describe('when there is an item in the node list and it has been clicked', () => { + beforeEach(async () => { + const nodeListItems = await simulator.resolveWrapper(() => simulator.nodeListItems()); + expect(nodeListItems && nodeListItems.length).toBeTruthy(); + if (nodeListItems) { + nodeListItems.first().find('button').simulate('click'); + } + }); + it('should show the details for the first node', async () => { + await expect( + simulator.map(() => simulator.nodeDetailDescriptionListEntries()) + ).toYieldEqualTo([ + ['process.executable', 'executable'], + ['process.pid', '0'], + ['user.name', 'user.name'], + ['user.domain', 'user.domain'], + ['process.parent.pid', '0'], + ['process.hash.md5', 'hash.md5'], + ['process.args', 'args'], + ]); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/resolver/view/panels/process_cube_icon.tsx b/x-pack/plugins/security_solution/public/resolver/view/panels/cube_for_process.tsx similarity index 96% rename from x-pack/plugins/security_solution/public/resolver/view/panels/process_cube_icon.tsx rename to x-pack/plugins/security_solution/public/resolver/view/panels/cube_for_process.tsx index b073324b27f9b..0d8f65b4e39e6 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/panels/process_cube_icon.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/panels/cube_for_process.tsx @@ -1,45 +1,45 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { memo } from 'react'; -import { useResolverTheme } from '../assets'; - -/** - * During user testing, one user indicated they wanted to see stronger visual relationships between - * Nodes on the graph and what's in the table. Using the same symbol in both places (as below) could help with that. - */ -export const CubeForProcess = memo(function CubeForProcess({ - isProcessTerminated, -}: { - isProcessTerminated: boolean; -}) { - const { cubeAssetsForNode } = useResolverTheme(); - const { cubeSymbol, descriptionText } = cubeAssetsForNode(isProcessTerminated, false); - - return ( - <> - - {descriptionText} - - - - ); -}); +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { memo } from 'react'; +import { useResolverTheme } from '../assets'; + +/** + * During user testing, one user indicated they wanted to see stronger visual relationships between + * Nodes on the graph and what's in the table. Using the same symbol in both places (as below) could help with that. + */ +export const CubeForProcess = memo(function CubeForProcess({ + isProcessTerminated, +}: { + isProcessTerminated: boolean; +}) { + const { cubeAssetsForNode } = useResolverTheme(); + const { cubeSymbol, descriptionText } = cubeAssetsForNode(isProcessTerminated, false); + + return ( + <> + + {descriptionText} + + + + ); +}); diff --git a/x-pack/plugins/security_solution/public/resolver/view/panels/panel_content_related_counts.tsx b/x-pack/plugins/security_solution/public/resolver/view/panels/event_counts_for_process.tsx similarity index 97% rename from x-pack/plugins/security_solution/public/resolver/view/panels/panel_content_related_counts.tsx rename to x-pack/plugins/security_solution/public/resolver/view/panels/event_counts_for_process.tsx index 880ee1dc7a10a..129aff776808a 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/panels/panel_content_related_counts.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/panels/event_counts_for_process.tsx @@ -1,144 +1,144 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { memo, useMemo } from 'react'; -import { i18n } from '@kbn/i18n'; -import { EuiBasicTableColumn, EuiButtonEmpty, EuiSpacer, EuiInMemoryTable } from '@elastic/eui'; -import { FormattedMessage } from 'react-intl'; -import { CrumbInfo, StyledBreadcrumbs } from './panel_content_utilities'; - -import * as event from '../../../../common/endpoint/models/event'; -import { ResolverEvent, ResolverNodeStats } from '../../../../common/endpoint/types'; - -/** - * This view gives counts for all the related events of a process grouped by related event type. - * It should look something like: - * - * | Count | Event Type | - * | :--------------------- | :------------------------- | - * | 5 | DNS | - * | 12 | Registry | - * | 2 | Network | - * - */ -export const EventCountsForProcess = memo(function EventCountsForProcess({ - processEvent, - pushToQueryParams, - relatedStats, -}: { - processEvent: ResolverEvent; - pushToQueryParams: (queryStringKeyValuePair: CrumbInfo) => unknown; - relatedStats: ResolverNodeStats; -}) { - interface EventCountsTableView { - name: string; - count: number; - } - - const relatedEventsState = { stats: relatedStats.events.byCategory }; - const processName = processEvent && event.eventName(processEvent); - const processEntityId = event.entityId(processEvent); - /** - * totalCount: This will reflect the aggregated total by category for all related events - * e.g. [dns,file],[dns,file],[registry] will have an aggregate total of 5. This is to keep the - * total number consistent with the "broken out" totals we see elsewhere in the app. - * E.g. on the rleated list by type, the above would show as: - * 2 dns - * 2 file - * 1 registry - * So it would be extremely disorienting to show the user a "3" above that as a total. - */ - const totalCount = Object.values(relatedStats.events.byCategory).reduce( - (sum, val) => sum + val, - 0 - ); - const eventsString = i18n.translate( - 'xpack.securitySolution.endpoint.resolver.panel.processEventCounts.events', - { - defaultMessage: 'Events', - } - ); - const crumbs = useMemo(() => { - return [ - { - text: eventsString, - onClick: () => { - pushToQueryParams({ crumbId: '', crumbEvent: '' }); - }, - }, - { - text: processName, - onClick: () => { - pushToQueryParams({ crumbId: processEntityId, crumbEvent: '' }); - }, - }, - { - text: ( - <> - - - ), - onClick: () => { - pushToQueryParams({ crumbId: processEntityId, crumbEvent: '' }); - }, - }, - ]; - }, [processName, totalCount, processEntityId, pushToQueryParams, eventsString]); - const rows = useMemo(() => { - return Object.entries(relatedEventsState.stats).map( - ([eventType, count]): EventCountsTableView => { - return { - name: eventType, - count, - }; - } - ); - }, [relatedEventsState]); - const columns = useMemo>>( - () => [ - { - field: 'count', - name: i18n.translate('xpack.securitySolution.endpoint.resolver.panel.table.row.count', { - defaultMessage: 'Count', - }), - width: '20%', - sortable: true, - }, - { - field: 'name', - name: i18n.translate('xpack.securitySolution.endpoint.resolver.panel.table.row.eventType', { - defaultMessage: 'Event Type', - }), - width: '80%', - sortable: true, - render(name: string) { - return ( - { - pushToQueryParams({ crumbId: event.entityId(processEvent), crumbEvent: name }); - }} - > - {name} - - ); - }, - }, - ], - [pushToQueryParams, processEvent] - ); - return ( - <> - - - items={rows} columns={columns} sorting /> - - ); -}); -EventCountsForProcess.displayName = 'EventCountsForProcess'; +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { memo, useMemo } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiBasicTableColumn, EuiButtonEmpty, EuiSpacer, EuiInMemoryTable } from '@elastic/eui'; +import { FormattedMessage } from 'react-intl'; +import { CrumbInfo, StyledBreadcrumbs } from './panel_content_utilities'; + +import * as event from '../../../../common/endpoint/models/event'; +import { ResolverEvent, ResolverNodeStats } from '../../../../common/endpoint/types'; + +/** + * This view gives counts for all the related events of a process grouped by related event type. + * It should look something like: + * + * | Count | Event Type | + * | :--------------------- | :------------------------- | + * | 5 | DNS | + * | 12 | Registry | + * | 2 | Network | + * + */ +export const EventCountsForProcess = memo(function EventCountsForProcess({ + processEvent, + pushToQueryParams, + relatedStats, +}: { + processEvent: ResolverEvent; + pushToQueryParams: (queryStringKeyValuePair: CrumbInfo) => unknown; + relatedStats: ResolverNodeStats; +}) { + interface EventCountsTableView { + name: string; + count: number; + } + + const relatedEventsState = { stats: relatedStats.events.byCategory }; + const processName = processEvent && event.eventName(processEvent); + const processEntityId = event.entityId(processEvent); + /** + * totalCount: This will reflect the aggregated total by category for all related events + * e.g. [dns,file],[dns,file],[registry] will have an aggregate total of 5. This is to keep the + * total number consistent with the "broken out" totals we see elsewhere in the app. + * E.g. on the rleated list by type, the above would show as: + * 2 dns + * 2 file + * 1 registry + * So it would be extremely disorienting to show the user a "3" above that as a total. + */ + const totalCount = Object.values(relatedStats.events.byCategory).reduce( + (sum, val) => sum + val, + 0 + ); + const eventsString = i18n.translate( + 'xpack.securitySolution.endpoint.resolver.panel.processEventCounts.events', + { + defaultMessage: 'Events', + } + ); + const crumbs = useMemo(() => { + return [ + { + text: eventsString, + onClick: () => { + pushToQueryParams({ crumbId: '', crumbEvent: '' }); + }, + }, + { + text: processName, + onClick: () => { + pushToQueryParams({ crumbId: processEntityId, crumbEvent: '' }); + }, + }, + { + text: ( + <> + + + ), + onClick: () => { + pushToQueryParams({ crumbId: processEntityId, crumbEvent: '' }); + }, + }, + ]; + }, [processName, totalCount, processEntityId, pushToQueryParams, eventsString]); + const rows = useMemo(() => { + return Object.entries(relatedEventsState.stats).map( + ([eventType, count]): EventCountsTableView => { + return { + name: eventType, + count, + }; + } + ); + }, [relatedEventsState]); + const columns = useMemo>>( + () => [ + { + field: 'count', + name: i18n.translate('xpack.securitySolution.endpoint.resolver.panel.table.row.count', { + defaultMessage: 'Count', + }), + width: '20%', + sortable: true, + }, + { + field: 'name', + name: i18n.translate('xpack.securitySolution.endpoint.resolver.panel.table.row.eventType', { + defaultMessage: 'Event Type', + }), + width: '80%', + sortable: true, + render(name: string) { + return ( + { + pushToQueryParams({ crumbId: event.entityId(processEvent), crumbEvent: name }); + }} + > + {name} + + ); + }, + }, + ], + [pushToQueryParams, processEvent] + ); + return ( + <> + + + items={rows} columns={columns} sorting /> + + ); +}); +EventCountsForProcess.displayName = 'EventCountsForProcess'; diff --git a/x-pack/plugins/security_solution/public/resolver/view/panel.tsx b/x-pack/plugins/security_solution/public/resolver/view/panels/index.tsx similarity index 90% rename from x-pack/plugins/security_solution/public/resolver/view/panel.tsx rename to x-pack/plugins/security_solution/public/resolver/view/panels/index.tsx index f378ab36bac94..7e7e8b757baf7 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/panel.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/panels/index.tsx @@ -7,17 +7,17 @@ import React, { memo, useMemo, useContext, useLayoutEffect, useState } from 'react'; import { useSelector } from 'react-redux'; import { EuiPanel } from '@elastic/eui'; -import * as selectors from '../store/selectors'; -import { useResolverDispatch } from './use_resolver_dispatch'; -import * as event from '../../../common/endpoint/models/event'; -import { ResolverEvent, ResolverNodeStats } from '../../../common/endpoint/types'; -import { SideEffectContext } from './side_effect_context'; -import { ProcessEventListNarrowedByType } from './panels/panel_content_related_list'; -import { EventCountsForProcess } from './panels/panel_content_related_counts'; -import { ProcessDetails } from './panels/panel_content_process_detail'; -import { ProcessListWithCounts } from './panels/panel_content_process_list'; -import { RelatedEventDetail } from './panels/panel_content_related_detail'; -import { useResolverQueryParams } from './use_resolver_query_params'; +import * as selectors from '../../store/selectors'; +import { useResolverDispatch } from '../use_resolver_dispatch'; +import * as event from '../../../../common/endpoint/models/event'; +import { ResolverEvent, ResolverNodeStats } from '../../../../common/endpoint/types'; +import { SideEffectContext } from '../side_effect_context'; +import { ProcessEventList } from './process_event_list'; +import { EventCountsForProcess } from './event_counts_for_process'; +import { ProcessDetails } from './process_details'; +import { ProcessListWithCounts } from './process_list_with_counts'; +import { RelatedEventDetail } from './related_event_detail'; +import { useResolverQueryParams } from '../use_resolver_query_params'; /** * The team decided to use this table to determine which breadcrumbs/view to display: @@ -145,7 +145,7 @@ const PanelContent = memo(function PanelContent() { */ if (crumbEvent && crumbEvent.length && uiSelectedEvent) { - return 'processEventListNarrowedByType'; + return 'processEventList'; } } @@ -179,9 +179,9 @@ const PanelContent = memo(function PanelContent() { ); } - if (panelToShow === 'processEventListNarrowedByType') { + if (panelToShow === 'processEventList') { return ( - { + const processInfoEntry: EuiDescriptionListProps['listItems'] = useMemo(() => { const eventTime = event.eventTimestamp(processEvent); - const dateTime = eventTime ? formatDate(eventTime) : ''; + const dateTime = eventTime === undefined ? null : formatDate(eventTime); const createdEntry = { title: '@timestamp', @@ -95,7 +96,7 @@ export const ProcessDetails = memo(function ProcessDetails({ description: argsForProcess(processEvent), }; - // This is the data in {title, description} form for the EUIDescriptionList to display + // This is the data in {title, description} form for the EuiDescriptionList to display const processDescriptionListData = [ createdEntry, pathEntry, @@ -107,7 +108,7 @@ export const ProcessDetails = memo(function ProcessDetails({ commandLineEntry, ] .filter((entry) => { - return entry.description; + return entry.description !== undefined; }) .map((entry) => { return { @@ -172,13 +173,24 @@ export const ProcessDetails = memo(function ProcessDetails({ + } + descriptionProps={ + { 'data-test-subj': 'resolver:node-detail:entry-description' } as HTMLAttributes< + HTMLElement + > + } compressed listItems={processInfoEntry} /> ); }); -ProcessDetails.displayName = 'ProcessDetails'; diff --git a/x-pack/plugins/security_solution/public/resolver/view/panels/panel_content_related_list.tsx b/x-pack/plugins/security_solution/public/resolver/view/panels/process_event_list.tsx similarity index 95% rename from x-pack/plugins/security_solution/public/resolver/view/panels/panel_content_related_list.tsx rename to x-pack/plugins/security_solution/public/resolver/view/panels/process_event_list.tsx index 9a477fd998bb3..101711475c938 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/panels/panel_content_related_list.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/panels/process_event_list.tsx @@ -1,290 +1,290 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { memo, useMemo, useEffect, Fragment } from 'react'; -import { i18n } from '@kbn/i18n'; -import { EuiTitle, EuiSpacer, EuiText, EuiButtonEmpty, EuiHorizontalRule } from '@elastic/eui'; -import { useSelector } from 'react-redux'; -import { FormattedMessage } from 'react-intl'; -import styled from 'styled-components'; -import { - CrumbInfo, - formatDate, - StyledBreadcrumbs, - BoldCode, - StyledTime, -} from './panel_content_utilities'; -import * as event from '../../../../common/endpoint/models/event'; -import { ResolverEvent, ResolverNodeStats } from '../../../../common/endpoint/types'; -import * as selectors from '../../store/selectors'; -import { useResolverDispatch } from '../use_resolver_dispatch'; -import { RelatedEventLimitWarning } from '../limit_warnings'; - -/** - * This view presents a list of related events of a given type for a given process. - * It will appear like: - * - * | | - * | :----------------------------------------------------- | - * | **registry deletion** @ *3:32PM..* *HKLM/software...* | - * | **file creation** @ *3:34PM..* *C:/directory/file.exe* | - */ - -interface MatchingEventEntry { - formattedDate: string; - eventType: string; - eventCategory: string; - name: { subject: string; descriptor?: string }; - setQueryParams: () => void; -} - -const StyledRelatedLimitWarning = styled(RelatedEventLimitWarning)` - flex-flow: row wrap; - display: block; - align-items: baseline; - margin-top: 1em; - - & .euiCallOutHeader { - display: inline; - margin-right: 0.25em; - } - - & .euiText { - display: inline; - } - - & .euiText p { - display: inline; - } -`; - -const DisplayList = memo(function DisplayList({ - crumbs, - matchingEventEntries, - eventType, - processEntityId, -}: { - crumbs: Array<{ text: string | JSX.Element; onClick: () => void }>; - matchingEventEntries: MatchingEventEntry[]; - eventType: string; - processEntityId: string; -}) { - const relatedLookupsByCategory = useSelector(selectors.relatedEventInfoByEntityId); - const lookupsForThisNode = relatedLookupsByCategory(processEntityId); - const shouldShowLimitWarning = lookupsForThisNode?.shouldShowLimitForCategory(eventType); - const numberDisplayed = lookupsForThisNode?.numberActuallyDisplayedForCategory(eventType); - const numberMissing = lookupsForThisNode?.numberNotDisplayedForCategory(eventType); - - return ( - <> - - {shouldShowLimitWarning && typeof numberDisplayed !== 'undefined' && numberMissing ? ( - - ) : null} - - <> - {matchingEventEntries.map((eventView, index) => { - const { subject, descriptor = '' } = eventView.name; - return ( - - - - - - - - - - - - - - {index === matchingEventEntries.length - 1 ? null : } - - ); - })} - - - ); -}); - -export const ProcessEventListNarrowedByType = memo(function ProcessEventListNarrowedByType({ - processEvent, - eventType, - relatedStats, - pushToQueryParams, -}: { - processEvent: ResolverEvent; - pushToQueryParams: (arg0: CrumbInfo) => unknown; - eventType: string; - relatedStats: ResolverNodeStats; -}) { - const processName = processEvent && event.eventName(processEvent); - const processEntityId = event.entityId(processEvent); - const totalCount = Object.values(relatedStats.events.byCategory).reduce( - (sum, val) => sum + val, - 0 - ); - const eventsString = i18n.translate( - 'xpack.securitySolution.endpoint.resolver.panel.processEventListByType.events', - { - defaultMessage: 'Events', - } - ); - const waitingString = i18n.translate( - 'xpack.securitySolution.endpoint.resolver.panel.processEventListByType.wait', - { - defaultMessage: 'Waiting For Events...', - } - ); - - const relatedsReadyMap = useSelector(selectors.relatedEventsReady); - const relatedsReady = relatedsReadyMap.get(processEntityId); - - const dispatch = useResolverDispatch(); - - useEffect(() => { - if (typeof relatedsReady === 'undefined') { - dispatch({ - type: 'appDetectedMissingEventData', - payload: processEntityId, - }); - } - }, [relatedsReady, dispatch, processEntityId]); - - const waitCrumbs = useMemo(() => { - return [ - { - text: eventsString, - onClick: () => { - pushToQueryParams({ crumbId: '', crumbEvent: '' }); - }, - }, - ]; - }, [pushToQueryParams, eventsString]); - - const relatedByCategory = useSelector(selectors.relatedEventsByCategory); - - /** - * A list entry will be displayed for each of these - */ - const matchingEventEntries: MatchingEventEntry[] = useMemo(() => { - const relateds = relatedByCategory(processEntityId)(eventType).map((resolverEvent) => { - const eventTime = event.eventTimestamp(resolverEvent); - const formattedDate = typeof eventTime === 'undefined' ? '' : formatDate(eventTime); - const entityId = event.eventId(resolverEvent); - - return { - formattedDate, - eventCategory: `${eventType}`, - eventType: `${event.ecsEventType(resolverEvent)}`, - name: event.descriptiveName(resolverEvent), - setQueryParams: () => { - pushToQueryParams({ - crumbId: entityId === undefined ? '' : String(entityId), - crumbEvent: processEntityId, - }); - }, - }; - }); - return relateds; - }, [relatedByCategory, eventType, processEntityId, pushToQueryParams]); - - const crumbs = useMemo(() => { - return [ - { - text: eventsString, - onClick: () => { - pushToQueryParams({ crumbId: '', crumbEvent: '' }); - }, - }, - { - text: processName, - onClick: () => { - pushToQueryParams({ crumbId: processEntityId, crumbEvent: '' }); - }, - }, - { - text: ( - <> - - - ), - onClick: () => { - pushToQueryParams({ crumbId: processEntityId, crumbEvent: 'all' }); - }, - }, - { - text: ( - <> - - - ), - onClick: () => {}, - }, - ]; - }, [ - eventType, - eventsString, - matchingEventEntries.length, - processEntityId, - processName, - pushToQueryParams, - totalCount, - ]); - - /** - * Wait here until the effect resolves... - */ - if (!relatedsReady) { - return ( - <> - - - -

{waitingString}

-
- - ); - } - - return ( - - ); -}); -ProcessEventListNarrowedByType.displayName = 'ProcessEventListNarrowedByType'; +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { memo, useMemo, useEffect, Fragment } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiTitle, EuiSpacer, EuiText, EuiButtonEmpty, EuiHorizontalRule } from '@elastic/eui'; +import { useSelector } from 'react-redux'; +import { FormattedMessage } from 'react-intl'; +import styled from 'styled-components'; +import { + CrumbInfo, + formatDate, + StyledBreadcrumbs, + BoldCode, + StyledTime, +} from './panel_content_utilities'; +import * as event from '../../../../common/endpoint/models/event'; +import { ResolverEvent, ResolverNodeStats } from '../../../../common/endpoint/types'; +import * as selectors from '../../store/selectors'; +import { useResolverDispatch } from '../use_resolver_dispatch'; +import { RelatedEventLimitWarning } from '../limit_warnings'; + +/** + * This view presents a list of related events of a given type for a given process. + * It will appear like: + * + * | | + * | :----------------------------------------------------- | + * | **registry deletion** @ *3:32PM..* *HKLM/software...* | + * | **file creation** @ *3:34PM..* *C:/directory/file.exe* | + */ + +interface MatchingEventEntry { + formattedDate: string; + eventType: string; + eventCategory: string; + name: { subject: string; descriptor?: string }; + setQueryParams: () => void; +} + +const StyledRelatedLimitWarning = styled(RelatedEventLimitWarning)` + flex-flow: row wrap; + display: block; + align-items: baseline; + margin-top: 1em; + + & .euiCallOutHeader { + display: inline; + margin-right: 0.25em; + } + + & .euiText { + display: inline; + } + + & .euiText p { + display: inline; + } +`; + +const DisplayList = memo(function DisplayList({ + crumbs, + matchingEventEntries, + eventType, + processEntityId, +}: { + crumbs: Array<{ text: string | JSX.Element; onClick: () => void }>; + matchingEventEntries: MatchingEventEntry[]; + eventType: string; + processEntityId: string; +}) { + const relatedLookupsByCategory = useSelector(selectors.relatedEventInfoByEntityId); + const lookupsForThisNode = relatedLookupsByCategory(processEntityId); + const shouldShowLimitWarning = lookupsForThisNode?.shouldShowLimitForCategory(eventType); + const numberDisplayed = lookupsForThisNode?.numberActuallyDisplayedForCategory(eventType); + const numberMissing = lookupsForThisNode?.numberNotDisplayedForCategory(eventType); + + return ( + <> + + {shouldShowLimitWarning && typeof numberDisplayed !== 'undefined' && numberMissing ? ( + + ) : null} + + <> + {matchingEventEntries.map((eventView, index) => { + const { subject, descriptor = '' } = eventView.name; + return ( + + + + + + + + + + + + + + {index === matchingEventEntries.length - 1 ? null : } + + ); + })} + + + ); +}); + +export const ProcessEventList = memo(function ProcessEventList({ + processEvent, + eventType, + relatedStats, + pushToQueryParams, +}: { + processEvent: ResolverEvent; + pushToQueryParams: (arg0: CrumbInfo) => unknown; + eventType: string; + relatedStats: ResolverNodeStats; +}) { + const processName = processEvent && event.eventName(processEvent); + const processEntityId = event.entityId(processEvent); + const totalCount = Object.values(relatedStats.events.byCategory).reduce( + (sum, val) => sum + val, + 0 + ); + const eventsString = i18n.translate( + 'xpack.securitySolution.endpoint.resolver.panel.processEventListByType.events', + { + defaultMessage: 'Events', + } + ); + const waitingString = i18n.translate( + 'xpack.securitySolution.endpoint.resolver.panel.processEventListByType.wait', + { + defaultMessage: 'Waiting For Events...', + } + ); + + const relatedsReadyMap = useSelector(selectors.relatedEventsReady); + const relatedsReady = relatedsReadyMap.get(processEntityId); + + const dispatch = useResolverDispatch(); + + useEffect(() => { + if (typeof relatedsReady === 'undefined') { + dispatch({ + type: 'appDetectedMissingEventData', + payload: processEntityId, + }); + } + }, [relatedsReady, dispatch, processEntityId]); + + const waitCrumbs = useMemo(() => { + return [ + { + text: eventsString, + onClick: () => { + pushToQueryParams({ crumbId: '', crumbEvent: '' }); + }, + }, + ]; + }, [pushToQueryParams, eventsString]); + + const relatedByCategory = useSelector(selectors.relatedEventsByCategory); + + /** + * A list entry will be displayed for each of these + */ + const matchingEventEntries: MatchingEventEntry[] = useMemo(() => { + const relateds = relatedByCategory(processEntityId)(eventType).map((resolverEvent) => { + const eventTime = event.eventTimestamp(resolverEvent); + const formattedDate = typeof eventTime === 'undefined' ? '' : formatDate(eventTime); + const entityId = event.eventId(resolverEvent); + + return { + formattedDate, + eventCategory: `${eventType}`, + eventType: `${event.ecsEventType(resolverEvent)}`, + name: event.descriptiveName(resolverEvent), + setQueryParams: () => { + pushToQueryParams({ + crumbId: entityId === undefined ? '' : String(entityId), + crumbEvent: processEntityId, + }); + }, + }; + }); + return relateds; + }, [relatedByCategory, eventType, processEntityId, pushToQueryParams]); + + const crumbs = useMemo(() => { + return [ + { + text: eventsString, + onClick: () => { + pushToQueryParams({ crumbId: '', crumbEvent: '' }); + }, + }, + { + text: processName, + onClick: () => { + pushToQueryParams({ crumbId: processEntityId, crumbEvent: '' }); + }, + }, + { + text: ( + <> + + + ), + onClick: () => { + pushToQueryParams({ crumbId: processEntityId, crumbEvent: 'all' }); + }, + }, + { + text: ( + <> + + + ), + onClick: () => {}, + }, + ]; + }, [ + eventType, + eventsString, + matchingEventEntries.length, + processEntityId, + processName, + pushToQueryParams, + totalCount, + ]); + + /** + * Wait here until the effect resolves... + */ + if (!relatedsReady) { + return ( + <> + + + +

{waitingString}

+
+ + ); + } + + return ( + + ); +}); +ProcessEventList.displayName = 'ProcessEventList'; diff --git a/x-pack/plugins/security_solution/public/resolver/view/panels/panel_content_process_list.tsx b/x-pack/plugins/security_solution/public/resolver/view/panels/process_list_with_counts.tsx similarity index 85% rename from x-pack/plugins/security_solution/public/resolver/view/panels/panel_content_process_list.tsx rename to x-pack/plugins/security_solution/public/resolver/view/panels/process_list_with_counts.tsx index 8ca002ace26fe..11f005f8acbcd 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/panels/panel_content_process_list.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/panels/process_list_with_counts.tsx @@ -1,199 +1,204 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import React, { memo, useContext, useCallback, useMemo } from 'react'; -import { - EuiBasicTableColumn, - EuiBadge, - EuiButtonEmpty, - EuiSpacer, - EuiInMemoryTable, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { useSelector } from 'react-redux'; -import styled from 'styled-components'; -import * as event from '../../../../common/endpoint/models/event'; -import * as selectors from '../../store/selectors'; -import { CrumbInfo, formatter, StyledBreadcrumbs } from './panel_content_utilities'; -import { useResolverDispatch } from '../use_resolver_dispatch'; -import { SideEffectContext } from '../side_effect_context'; -import { CubeForProcess } from './process_cube_icon'; -import { ResolverEvent } from '../../../../common/endpoint/types'; -import { LimitWarning } from '../limit_warnings'; - -const StyledLimitWarning = styled(LimitWarning)` - flex-flow: row wrap; - display: block; - align-items: baseline; - margin-top: 1em; - - & .euiCallOutHeader { - display: inline; - margin-right: 0.25em; - } - - & .euiText { - display: inline; - } - - & .euiText p { - display: inline; - } -`; - -/** - * The "default" view for the panel: A list of all the processes currently in the graph. - * - * @param {function} pushToQueryparams A function to update the hash value in the URL to control panel state - */ -export const ProcessListWithCounts = memo(function ProcessListWithCounts({ - pushToQueryParams, -}: { - pushToQueryParams: (queryStringKeyValuePair: CrumbInfo) => unknown; -}) { - interface ProcessTableView { - name: string; - timestamp?: Date; - event: ResolverEvent; - } - - const dispatch = useResolverDispatch(); - const { timestamp } = useContext(SideEffectContext); - const isProcessTerminated = useSelector(selectors.isProcessTerminated); - const handleBringIntoViewClick = useCallback( - (processTableViewItem) => { - dispatch({ - type: 'userBroughtProcessIntoView', - payload: { - time: timestamp(), - process: processTableViewItem.event, - }, - }); - pushToQueryParams({ crumbId: event.entityId(processTableViewItem.event), crumbEvent: '' }); - }, - [dispatch, timestamp, pushToQueryParams] - ); - - const columns = useMemo>>( - () => [ - { - field: 'name', - name: i18n.translate( - 'xpack.securitySolution.endpoint.resolver.panel.table.row.processNameTitle', - { - defaultMessage: 'Process Name', - } - ), - sortable: true, - truncateText: true, - render(name: string, item: ProcessTableView) { - const entityId = event.entityId(item.event); - const isTerminated = isProcessTerminated(entityId); - return name === '' ? ( - - {i18n.translate( - 'xpack.securitySolution.endpoint.resolver.panel.table.row.valueMissingDescription', - { - defaultMessage: 'Value is missing', - } - )} - - ) : ( - { - handleBringIntoViewClick(item); - pushToQueryParams({ crumbId: event.entityId(item.event), crumbEvent: '' }); - }} - > - - {name} - - ); - }, - }, - { - field: 'timestamp', - name: i18n.translate( - 'xpack.securitySolution.endpoint.resolver.panel.table.row.timestampTitle', - { - defaultMessage: 'Timestamp', - } - ), - dataType: 'date', - sortable: true, - render(eventDate?: Date) { - return eventDate ? ( - formatter.format(eventDate) - ) : ( - - {i18n.translate( - 'xpack.securitySolution.endpoint.resolver.panel.table.row.timestampInvalidLabel', - { - defaultMessage: 'invalid', - } - )} - - ); - }, - }, - ], - [pushToQueryParams, handleBringIntoViewClick, isProcessTerminated] - ); - - const { processNodePositions } = useSelector(selectors.layout); - const processTableView: ProcessTableView[] = useMemo( - () => - [...processNodePositions.keys()].map((processEvent) => { - let dateTime; - const eventTime = event.eventTimestamp(processEvent); - const name = event.eventName(processEvent); - if (eventTime) { - const date = new Date(eventTime); - if (isFinite(date.getTime())) { - dateTime = date; - } - } - return { - name, - timestamp: dateTime, - event: processEvent, - }; - }), - [processNodePositions] - ); - const numberOfProcesses = processTableView.length; - - const crumbs = useMemo(() => { - return [ - { - text: i18n.translate( - 'xpack.securitySolution.endpoint.resolver.panel.processListWithCounts.events', - { - defaultMessage: 'All Process Events', - } - ), - onClick: () => {}, - }, - ]; - }, []); - - const children = useSelector(selectors.hasMoreChildren); - const ancestors = useSelector(selectors.hasMoreAncestors); - const showWarning = children === true || ancestors === true; - return ( - <> - - {showWarning && } - - - data-test-subj="resolver:panel:process-list" - items={processTableView} - columns={columns} - sorting - /> - - ); -}); -ProcessListWithCounts.displayName = 'ProcessListWithCounts'; +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React, { memo, useContext, useCallback, useMemo } from 'react'; +import { + EuiBasicTableColumn, + EuiBadge, + EuiButtonEmpty, + EuiSpacer, + EuiInMemoryTable, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { useSelector } from 'react-redux'; +import styled from 'styled-components'; +import * as event from '../../../../common/endpoint/models/event'; +import * as selectors from '../../store/selectors'; +import { CrumbInfo, formatter, StyledBreadcrumbs } from './panel_content_utilities'; +import { useResolverDispatch } from '../use_resolver_dispatch'; +import { SideEffectContext } from '../side_effect_context'; +import { CubeForProcess } from './cube_for_process'; +import { SafeResolverEvent } from '../../../../common/endpoint/types'; +import { LimitWarning } from '../limit_warnings'; + +const StyledLimitWarning = styled(LimitWarning)` + flex-flow: row wrap; + display: block; + align-items: baseline; + margin-top: 1em; + + & .euiCallOutHeader { + display: inline; + margin-right: 0.25em; + } + + & .euiText { + display: inline; + } + + & .euiText p { + display: inline; + } +`; + +/** + * The "default" view for the panel: A list of all the processes currently in the graph. + * + * @param {function} pushToQueryparams A function to update the hash value in the URL to control panel state + */ +export const ProcessListWithCounts = memo(function ProcessListWithCounts({ + pushToQueryParams, +}: { + pushToQueryParams: (queryStringKeyValuePair: CrumbInfo) => unknown; +}) { + interface ProcessTableView { + name?: string; + timestamp?: Date; + event: SafeResolverEvent; + } + + const dispatch = useResolverDispatch(); + const { timestamp } = useContext(SideEffectContext); + const isProcessTerminated = useSelector(selectors.isProcessTerminated); + const handleBringIntoViewClick = useCallback( + (processTableViewItem) => { + dispatch({ + type: 'userBroughtProcessIntoView', + payload: { + time: timestamp(), + process: processTableViewItem.event, + }, + }); + pushToQueryParams({ crumbId: event.entityId(processTableViewItem.event), crumbEvent: '' }); + }, + [dispatch, timestamp, pushToQueryParams] + ); + + const columns = useMemo>>( + () => [ + { + field: 'name', + name: i18n.translate( + 'xpack.securitySolution.endpoint.resolver.panel.table.row.processNameTitle', + { + defaultMessage: 'Process Name', + } + ), + sortable: true, + truncateText: true, + render(name: string, item: ProcessTableView) { + const entityID = event.entityIDSafeVersion(item.event); + const isTerminated = entityID === undefined ? false : isProcessTerminated(entityID); + return name === '' ? ( + + {i18n.translate( + 'xpack.securitySolution.endpoint.resolver.panel.table.row.valueMissingDescription', + { + defaultMessage: 'Value is missing', + } + )} + + ) : ( + { + handleBringIntoViewClick(item); + pushToQueryParams({ + // Take the user back to the list of nodes if this node has no ID + crumbId: event.entityIDSafeVersion(item.event) ?? '', + crumbEvent: '', + }); + }} + > + + {name} + + ); + }, + }, + { + field: 'timestamp', + name: i18n.translate( + 'xpack.securitySolution.endpoint.resolver.panel.table.row.timestampTitle', + { + defaultMessage: 'Timestamp', + } + ), + dataType: 'date', + sortable: true, + render(eventDate?: Date) { + return eventDate ? ( + formatter.format(eventDate) + ) : ( + + {i18n.translate( + 'xpack.securitySolution.endpoint.resolver.panel.table.row.timestampInvalidLabel', + { + defaultMessage: 'invalid', + } + )} + + ); + }, + }, + ], + [pushToQueryParams, handleBringIntoViewClick, isProcessTerminated] + ); + + const { processNodePositions } = useSelector(selectors.layout); + const processTableView: ProcessTableView[] = useMemo( + () => + [...processNodePositions.keys()].map((processEvent) => { + let dateTime: Date | undefined; + const eventTime = event.timestampSafeVersion(processEvent); + const name = event.processNameSafeVersion(processEvent); + if (eventTime) { + const date = new Date(eventTime); + if (isFinite(date.getTime())) { + dateTime = date; + } + } + return { + name, + timestamp: dateTime, + event: processEvent, + }; + }), + [processNodePositions] + ); + const numberOfProcesses = processTableView.length; + + const crumbs = useMemo(() => { + return [ + { + text: i18n.translate( + 'xpack.securitySolution.endpoint.resolver.panel.processListWithCounts.events', + { + defaultMessage: 'All Process Events', + } + ), + onClick: () => {}, + }, + ]; + }, []); + + const children = useSelector(selectors.hasMoreChildren); + const ancestors = useSelector(selectors.hasMoreAncestors); + const showWarning = children === true || ancestors === true; + const rowProps = useMemo(() => ({ 'data-test-subj': 'resolver:node-list:item' }), []); + return ( + <> + + {showWarning && } + + + rowProps={rowProps} + data-test-subj="resolver:node-list" + items={processTableView} + columns={columns} + sorting + /> + + ); +}); diff --git a/x-pack/plugins/security_solution/public/resolver/view/panels/panel_content_related_detail.tsx b/x-pack/plugins/security_solution/public/resolver/view/panels/related_event_detail.tsx similarity index 97% rename from x-pack/plugins/security_solution/public/resolver/view/panels/panel_content_related_detail.tsx rename to x-pack/plugins/security_solution/public/resolver/view/panels/related_event_detail.tsx index 10e57a09b5da4..3579b1b2f69b8 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/panels/panel_content_related_detail.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/panels/related_event_detail.tsx @@ -1,375 +1,375 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { memo, useMemo, useEffect, Fragment } from 'react'; -import { i18n } from '@kbn/i18n'; -import { EuiSpacer, EuiText, EuiDescriptionList, EuiTextColor, EuiTitle } from '@elastic/eui'; -import styled from 'styled-components'; -import { useSelector } from 'react-redux'; -import { FormattedMessage } from 'react-intl'; -import { - CrumbInfo, - formatDate, - StyledBreadcrumbs, - BoldCode, - StyledTime, -} from './panel_content_utilities'; -import * as event from '../../../../common/endpoint/models/event'; -import { ResolverEvent } from '../../../../common/endpoint/types'; -import * as selectors from '../../store/selectors'; -import { useResolverDispatch } from '../use_resolver_dispatch'; -import { PanelContentError } from './panel_content_error'; - -/** - * A helper function to turn objects into EuiDescriptionList entries. - * This reflects the strategy of more or less "dumping" metadata for related processes - * in description lists with little/no 'prettification'. This has the obvious drawback of - * data perhaps appearing inscrutable/daunting, but the benefit of presenting these fields - * to the user "as they occur" in ECS, which may help them with e.g. EQL queries. - * - * Given an object like: {a:{b: 1}, c: 'd'} it will yield title/description entries like so: - * {title: "a.b", description: "1"}, {title: "c", description: "d"} - * - * @param {object} obj The object to turn into `
` entries - */ -const objectToDescriptionListEntries = function* ( - obj: object, - prefix = '' -): Generator<{ title: string; description: string }> { - const nextPrefix = prefix.length ? `${prefix}.` : ''; - for (const [metaKey, metaValue] of Object.entries(obj)) { - if (typeof metaValue === 'number' || typeof metaValue === 'string') { - yield { title: nextPrefix + metaKey, description: `${metaValue}` }; - } else if (metaValue instanceof Array) { - yield { - title: nextPrefix + metaKey, - description: metaValue - .filter((arrayEntry) => { - return typeof arrayEntry === 'number' || typeof arrayEntry === 'string'; - }) - .join(','), - }; - } else if (typeof metaValue === 'object') { - yield* objectToDescriptionListEntries(metaValue, nextPrefix + metaKey); - } - } -}; - -// Adding some styles to prevent horizontal scrollbars, per request from UX review -const StyledDescriptionList = memo(styled(EuiDescriptionList)` - &.euiDescriptionList.euiDescriptionList--column dt.euiDescriptionList__title.desc-title { - max-width: 8em; - } - &.euiDescriptionList.euiDescriptionList--column dd.euiDescriptionList__description { - max-width: calc(100% - 8.5em); - overflow-wrap: break-word; - } -`); - -// Styling subtitles, per UX review: -const StyledFlexTitle = memo(styled('h3')` - display: flex; - flex-flow: row; - font-size: 1.2em; -`); -const StyledTitleRule = memo(styled('hr')` - &.euiHorizontalRule.euiHorizontalRule--full.euiHorizontalRule--marginSmall.override { - display: block; - flex: 1; - margin-left: 0.5em; - } -`); - -const TitleHr = memo(() => { - return ( - - ); -}); -TitleHr.displayName = 'TitleHR'; - -/** - * This view presents a detailed view of all the available data for a related event, split and titled by the "section" - * it appears in the underlying ResolverEvent - */ -export const RelatedEventDetail = memo(function RelatedEventDetail({ - relatedEventId, - parentEvent, - pushToQueryParams, - countForParent, -}: { - relatedEventId: string; - parentEvent: ResolverEvent; - pushToQueryParams: (queryStringKeyValuePair: CrumbInfo) => unknown; - countForParent: number | undefined; -}) { - const processName = (parentEvent && event.eventName(parentEvent)) || '*'; - const processEntityId = parentEvent && event.entityId(parentEvent); - const totalCount = countForParent || 0; - const eventsString = i18n.translate( - 'xpack.securitySolution.endpoint.resolver.panel.relatedEventDetail.events', - { - defaultMessage: 'Events', - } - ); - const naString = i18n.translate( - 'xpack.securitySolution.endpoint.resolver.panel.relatedEventDetail.NA', - { - defaultMessage: 'N/A', - } - ); - - const relatedsReadyMap = useSelector(selectors.relatedEventsReady); - const relatedsReady = relatedsReadyMap.get(processEntityId!); - const dispatch = useResolverDispatch(); - - /** - * If we don't have the related events for the parent yet, use this effect - * to request them. - */ - useEffect(() => { - if (typeof relatedsReady === 'undefined') { - dispatch({ - type: 'appDetectedMissingEventData', - payload: processEntityId, - }); - } - }, [relatedsReady, dispatch, processEntityId]); - - const relatedEventsForThisProcess = useSelector(selectors.relatedEventsByEntityId).get( - processEntityId! - ); - - const [relatedEventToShowDetailsFor, countBySameCategory, relatedEventCategory] = useMemo(() => { - if (!relatedEventsForThisProcess) { - return [undefined, 0]; - } - const specificEvent = relatedEventsForThisProcess.events.find( - (evt) => event.eventId(evt) === relatedEventId - ); - // For breadcrumbs: - const specificCategory = specificEvent && event.primaryEventCategory(specificEvent); - const countOfCategory = relatedEventsForThisProcess.events.reduce((sumtotal, evt) => { - return event.primaryEventCategory(evt) === specificCategory ? sumtotal + 1 : sumtotal; - }, 0); - return [specificEvent, countOfCategory, specificCategory || naString]; - }, [relatedEventsForThisProcess, naString, relatedEventId]); - - const [sections, formattedDate] = useMemo(() => { - if (!relatedEventToShowDetailsFor) { - // This could happen if user relaods from URL param and requests an eventId that no longer exists - return [[], naString]; - } - // Assuming these details (agent, ecs, process) aren't as helpful, can revisit - const { - agent, - ecs, - process, - ...relevantData - } = relatedEventToShowDetailsFor as ResolverEvent & { - // Type this with various unknown keys so that ts will let us delete those keys - ecs: unknown; - process: unknown; - }; - let displayDate = ''; - const sectionData: Array<{ - sectionTitle: string; - entries: Array<{ title: string; description: string }>; - }> = Object.entries(relevantData) - .map(([sectionTitle, val]) => { - if (sectionTitle === '@timestamp') { - displayDate = formatDate(val); - return { sectionTitle: '', entries: [] }; - } - if (typeof val !== 'object') { - return { sectionTitle, entries: [{ title: sectionTitle, description: `${val}` }] }; - } - return { sectionTitle, entries: [...objectToDescriptionListEntries(val)] }; - }) - .filter((v) => v.sectionTitle !== '' && v.entries.length); - return [sectionData, displayDate]; - }, [relatedEventToShowDetailsFor, naString]); - - const waitCrumbs = useMemo(() => { - return [ - { - text: eventsString, - onClick: () => { - pushToQueryParams({ crumbId: '', crumbEvent: '' }); - }, - }, - ]; - }, [pushToQueryParams, eventsString]); - - const { subject = '', descriptor = '' } = relatedEventToShowDetailsFor - ? event.descriptiveName(relatedEventToShowDetailsFor) - : {}; - const crumbs = useMemo(() => { - return [ - { - text: eventsString, - onClick: () => { - pushToQueryParams({ crumbId: '', crumbEvent: '' }); - }, - }, - { - text: processName, - onClick: () => { - pushToQueryParams({ crumbId: processEntityId!, crumbEvent: '' }); - }, - }, - { - text: ( - <> - - - ), - onClick: () => { - pushToQueryParams({ crumbId: processEntityId!, crumbEvent: 'all' }); - }, - }, - { - text: ( - <> - - - ), - onClick: () => { - pushToQueryParams({ - crumbId: processEntityId!, - crumbEvent: relatedEventCategory || 'all', - }); - }, - }, - { - text: relatedEventToShowDetailsFor ? ( - - ) : ( - naString - ), - onClick: () => {}, - }, - ]; - }, [ - processName, - processEntityId, - eventsString, - pushToQueryParams, - totalCount, - countBySameCategory, - naString, - relatedEventCategory, - relatedEventToShowDetailsFor, - subject, - descriptor, - ]); - - /** - * If the ship hasn't come in yet, wait on the dock - */ - if (!relatedsReady) { - const waitingString = i18n.translate( - 'xpack.securitySolution.endpoint.resolver.panel.relatedDetail.wait', - { - defaultMessage: 'Waiting For Events...', - } - ); - return ( - <> - - - -

{waitingString}

-
- - ); - } - - /** - * Could happen if user e.g. loads a URL with a bad crumbEvent - */ - if (!relatedEventToShowDetailsFor) { - const errString = i18n.translate( - 'xpack.securitySolution.endpoint.resolver.panel.relatedDetail.missing', - { - defaultMessage: 'Related event not found.', - } - ); - return ( - - ); - } - - return ( - <> - - - - - - - - - - - - - - - - {sections.map(({ sectionTitle, entries }, index) => { - return ( - - {index === 0 ? null : } - - - - {sectionTitle} - - - - - - - {index === sections.length - 1 ? null : } - - ); - })} - - ); -}); +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { memo, useMemo, useEffect, Fragment } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiSpacer, EuiText, EuiDescriptionList, EuiTextColor, EuiTitle } from '@elastic/eui'; +import styled from 'styled-components'; +import { useSelector } from 'react-redux'; +import { FormattedMessage } from 'react-intl'; +import { + CrumbInfo, + formatDate, + StyledBreadcrumbs, + BoldCode, + StyledTime, +} from './panel_content_utilities'; +import * as event from '../../../../common/endpoint/models/event'; +import { ResolverEvent } from '../../../../common/endpoint/types'; +import * as selectors from '../../store/selectors'; +import { useResolverDispatch } from '../use_resolver_dispatch'; +import { PanelContentError } from './panel_content_error'; + +/** + * A helper function to turn objects into EuiDescriptionList entries. + * This reflects the strategy of more or less "dumping" metadata for related processes + * in description lists with little/no 'prettification'. This has the obvious drawback of + * data perhaps appearing inscrutable/daunting, but the benefit of presenting these fields + * to the user "as they occur" in ECS, which may help them with e.g. EQL queries. + * + * Given an object like: {a:{b: 1}, c: 'd'} it will yield title/description entries like so: + * {title: "a.b", description: "1"}, {title: "c", description: "d"} + * + * @param {object} obj The object to turn into `
` entries + */ +const objectToDescriptionListEntries = function* ( + obj: object, + prefix = '' +): Generator<{ title: string; description: string }> { + const nextPrefix = prefix.length ? `${prefix}.` : ''; + for (const [metaKey, metaValue] of Object.entries(obj)) { + if (typeof metaValue === 'number' || typeof metaValue === 'string') { + yield { title: nextPrefix + metaKey, description: `${metaValue}` }; + } else if (metaValue instanceof Array) { + yield { + title: nextPrefix + metaKey, + description: metaValue + .filter((arrayEntry) => { + return typeof arrayEntry === 'number' || typeof arrayEntry === 'string'; + }) + .join(','), + }; + } else if (typeof metaValue === 'object') { + yield* objectToDescriptionListEntries(metaValue, nextPrefix + metaKey); + } + } +}; + +// Adding some styles to prevent horizontal scrollbars, per request from UX review +const StyledDescriptionList = memo(styled(EuiDescriptionList)` + &.euiDescriptionList.euiDescriptionList--column dt.euiDescriptionList__title.desc-title { + max-width: 8em; + } + &.euiDescriptionList.euiDescriptionList--column dd.euiDescriptionList__description { + max-width: calc(100% - 8.5em); + overflow-wrap: break-word; + } +`); + +// Styling subtitles, per UX review: +const StyledFlexTitle = memo(styled('h3')` + display: flex; + flex-flow: row; + font-size: 1.2em; +`); +const StyledTitleRule = memo(styled('hr')` + &.euiHorizontalRule.euiHorizontalRule--full.euiHorizontalRule--marginSmall.override { + display: block; + flex: 1; + margin-left: 0.5em; + } +`); + +const TitleHr = memo(() => { + return ( + + ); +}); +TitleHr.displayName = 'TitleHR'; + +/** + * This view presents a detailed view of all the available data for a related event, split and titled by the "section" + * it appears in the underlying ResolverEvent + */ +export const RelatedEventDetail = memo(function RelatedEventDetail({ + relatedEventId, + parentEvent, + pushToQueryParams, + countForParent, +}: { + relatedEventId: string; + parentEvent: ResolverEvent; + pushToQueryParams: (queryStringKeyValuePair: CrumbInfo) => unknown; + countForParent: number | undefined; +}) { + const processName = (parentEvent && event.eventName(parentEvent)) || '*'; + const processEntityId = parentEvent && event.entityId(parentEvent); + const totalCount = countForParent || 0; + const eventsString = i18n.translate( + 'xpack.securitySolution.endpoint.resolver.panel.relatedEventDetail.events', + { + defaultMessage: 'Events', + } + ); + const naString = i18n.translate( + 'xpack.securitySolution.endpoint.resolver.panel.relatedEventDetail.NA', + { + defaultMessage: 'N/A', + } + ); + + const relatedsReadyMap = useSelector(selectors.relatedEventsReady); + const relatedsReady = relatedsReadyMap.get(processEntityId!); + const dispatch = useResolverDispatch(); + + /** + * If we don't have the related events for the parent yet, use this effect + * to request them. + */ + useEffect(() => { + if (typeof relatedsReady === 'undefined') { + dispatch({ + type: 'appDetectedMissingEventData', + payload: processEntityId, + }); + } + }, [relatedsReady, dispatch, processEntityId]); + + const relatedEventsForThisProcess = useSelector(selectors.relatedEventsByEntityId).get( + processEntityId! + ); + + const [relatedEventToShowDetailsFor, countBySameCategory, relatedEventCategory] = useMemo(() => { + if (!relatedEventsForThisProcess) { + return [undefined, 0]; + } + const specificEvent = relatedEventsForThisProcess.events.find( + (evt) => event.eventId(evt) === relatedEventId + ); + // For breadcrumbs: + const specificCategory = specificEvent && event.primaryEventCategory(specificEvent); + const countOfCategory = relatedEventsForThisProcess.events.reduce((sumtotal, evt) => { + return event.primaryEventCategory(evt) === specificCategory ? sumtotal + 1 : sumtotal; + }, 0); + return [specificEvent, countOfCategory, specificCategory || naString]; + }, [relatedEventsForThisProcess, naString, relatedEventId]); + + const [sections, formattedDate] = useMemo(() => { + if (!relatedEventToShowDetailsFor) { + // This could happen if user relaods from URL param and requests an eventId that no longer exists + return [[], naString]; + } + // Assuming these details (agent, ecs, process) aren't as helpful, can revisit + const { + agent, + ecs, + process, + ...relevantData + } = relatedEventToShowDetailsFor as ResolverEvent & { + // Type this with various unknown keys so that ts will let us delete those keys + ecs: unknown; + process: unknown; + }; + let displayDate = ''; + const sectionData: Array<{ + sectionTitle: string; + entries: Array<{ title: string; description: string }>; + }> = Object.entries(relevantData) + .map(([sectionTitle, val]) => { + if (sectionTitle === '@timestamp') { + displayDate = formatDate(val); + return { sectionTitle: '', entries: [] }; + } + if (typeof val !== 'object') { + return { sectionTitle, entries: [{ title: sectionTitle, description: `${val}` }] }; + } + return { sectionTitle, entries: [...objectToDescriptionListEntries(val)] }; + }) + .filter((v) => v.sectionTitle !== '' && v.entries.length); + return [sectionData, displayDate]; + }, [relatedEventToShowDetailsFor, naString]); + + const waitCrumbs = useMemo(() => { + return [ + { + text: eventsString, + onClick: () => { + pushToQueryParams({ crumbId: '', crumbEvent: '' }); + }, + }, + ]; + }, [pushToQueryParams, eventsString]); + + const { subject = '', descriptor = '' } = relatedEventToShowDetailsFor + ? event.descriptiveName(relatedEventToShowDetailsFor) + : {}; + const crumbs = useMemo(() => { + return [ + { + text: eventsString, + onClick: () => { + pushToQueryParams({ crumbId: '', crumbEvent: '' }); + }, + }, + { + text: processName, + onClick: () => { + pushToQueryParams({ crumbId: processEntityId!, crumbEvent: '' }); + }, + }, + { + text: ( + <> + + + ), + onClick: () => { + pushToQueryParams({ crumbId: processEntityId!, crumbEvent: 'all' }); + }, + }, + { + text: ( + <> + + + ), + onClick: () => { + pushToQueryParams({ + crumbId: processEntityId!, + crumbEvent: relatedEventCategory || 'all', + }); + }, + }, + { + text: relatedEventToShowDetailsFor ? ( + + ) : ( + naString + ), + onClick: () => {}, + }, + ]; + }, [ + processName, + processEntityId, + eventsString, + pushToQueryParams, + totalCount, + countBySameCategory, + naString, + relatedEventCategory, + relatedEventToShowDetailsFor, + subject, + descriptor, + ]); + + /** + * If the ship hasn't come in yet, wait on the dock + */ + if (!relatedsReady) { + const waitingString = i18n.translate( + 'xpack.securitySolution.endpoint.resolver.panel.relatedDetail.wait', + { + defaultMessage: 'Waiting For Events...', + } + ); + return ( + <> + + + +

{waitingString}

+
+ + ); + } + + /** + * Could happen if user e.g. loads a URL with a bad crumbEvent + */ + if (!relatedEventToShowDetailsFor) { + const errString = i18n.translate( + 'xpack.securitySolution.endpoint.resolver.panel.relatedDetail.missing', + { + defaultMessage: 'Related event not found.', + } + ); + return ( + + ); + } + + return ( + <> + + + + + + + + + + + + + + + + {sections.map(({ sectionTitle, entries }, index) => { + return ( + + {index === 0 ? null : } + + + + {sectionTitle} + + + + + + + {index === sections.length - 1 ? null : } + + ); + })} + + ); +}); diff --git a/x-pack/plugins/security_solution/public/resolver/view/process_event_dot.tsx b/x-pack/plugins/security_solution/public/resolver/view/process_event_dot.tsx index 24de45ee894dc..2a5d91028d9f5 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/process_event_dot.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/process_event_dot.tsx @@ -14,10 +14,9 @@ import { NodeSubMenu, subMenuAssets } from './submenu'; import { applyMatrix3 } from '../models/vector2'; import { Vector2, Matrix3 } from '../types'; import { SymbolIds, useResolverTheme, calculateResolverFontSize } from './assets'; -import { ResolverEvent } from '../../../common/endpoint/types'; +import { ResolverEvent, SafeResolverEvent } from '../../../common/endpoint/types'; import { useResolverDispatch } from './use_resolver_dispatch'; import * as eventModel from '../../../common/endpoint/models/event'; -import * as processEventModel from '../models/process_event'; import * as selectors from '../store/selectors'; import { useResolverQueryParams } from './use_resolver_query_params'; @@ -85,7 +84,7 @@ const UnstyledProcessEventDot = React.memo( /** * An event which contains details about the process node. */ - event: ResolverEvent; + event: SafeResolverEvent; /** * projectionMatrix which can be used to convert `position` to screen coordinates. */ @@ -114,7 +113,11 @@ const UnstyledProcessEventDot = React.memo( // Node (html id=) IDs const ariaActiveDescendant = useSelector(selectors.ariaActiveDescendant); const selectedNode = useSelector(selectors.selectedNode); - const nodeID = processEventModel.uniquePidForProcess(event); + const nodeID: string | undefined = eventModel.entityIDSafeVersion(event); + if (nodeID === undefined) { + // NB: this component should be taking nodeID as a `string` instead of handling this logic here + throw new Error('Tried to render a node with no ID'); + } const relatedEventStats = useSelector(selectors.relatedEventsStats)(nodeID); // define a standard way of giving HTML IDs to nodes based on their entity_id/nodeID. @@ -287,7 +290,9 @@ const UnstyledProcessEventDot = React.memo( ? subMenuAssets.initialMenuStatus : relatedEventOptions; - const grandTotal: number | null = useSelector(selectors.relatedEventTotalForProcess)(event); + const grandTotal: number | null = useSelector(selectors.relatedEventTotalForProcess)( + event as ResolverEvent + ); /* eslint-disable jsx-a11y/click-events-have-key-events */ /** @@ -398,11 +403,11 @@ const UnstyledProcessEventDot = React.memo( maxWidth: `${isShowingEventActions ? 400 : 210 * xScale}px`, }} tabIndex={-1} - title={eventModel.eventName(event)} + title={eventModel.processNameSafeVersion(event)} > - {eventModel.eventName(event)} + {eventModel.processNameSafeVersion(event)} diff --git a/x-pack/plugins/security_solution/public/resolver/view/resolver_without_providers.tsx b/x-pack/plugins/security_solution/public/resolver/view/resolver_without_providers.tsx index e74502243ffc8..5f1e5f18e575d 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/resolver_without_providers.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/resolver_without_providers.tsx @@ -20,7 +20,7 @@ import { SymbolDefinitions, useResolverTheme } from './assets'; import { useStateSyncingActions } from './use_state_syncing_actions'; import { useResolverQueryParams } from './use_resolver_query_params'; import { StyledMapContainer, StyledPanel, GraphContainer } from './styles'; -import { entityId } from '../../../common/endpoint/models/event'; +import { entityIDSafeVersion } from '../../../common/endpoint/models/event'; import { SideEffectContext } from './side_effect_context'; import { ResolverProps } from '../types'; @@ -114,7 +114,7 @@ export const ResolverWithoutProviders = React.memo( ) )} {[...processNodePositions].map(([processEvent, position]) => { - const processEntityId = entityId(processEvent); + const processEntityId = entityIDSafeVersion(processEvent); return ( { } const processes: ResolverEvent[] = [ ...selectors.layout(store.getState()).processNodePositions.keys(), - ]; + ] as ResolverEvent[]; process = processes[processes.length - 1]; if (!process) { throw new Error('missing the process to bring into view'); diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.ts b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.ts index 0a08e45324b89..c2e23cc19d89e 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.ts +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.ts @@ -363,6 +363,7 @@ export const queryTimelineById = ({ export const dispatchUpdateTimeline = (dispatch: Dispatch): DispatchUpdateTimeline => ({ duplicate, id, + forceNotes = false, from, notes, timeline, @@ -407,7 +408,7 @@ export const dispatchUpdateTimeline = (dispatch: Dispatch): DispatchUpdateTimeli dispatch(dispatchAddGlobalTimelineNote({ noteId: newNote.id, id })); } - if (!duplicate) { + if (!duplicate || forceNotes) { dispatch( dispatchAddNotes({ notes: diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/types.ts b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/types.ts index 8950f814d6965..769a0a1658a46 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/types.ts +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/types.ts @@ -192,6 +192,7 @@ export interface OpenTimelineProps { export interface UpdateTimeline { duplicate: boolean; id: string; + forceNotes?: boolean; from: string; notes: NoteResult[] | null | undefined; timeline: TimelineModel; diff --git a/x-pack/plugins/security_solution/public/timelines/containers/helpers.test.ts b/x-pack/plugins/security_solution/public/timelines/containers/helpers.test.ts new file mode 100644 index 0000000000000..043b5fe39a8bf --- /dev/null +++ b/x-pack/plugins/security_solution/public/timelines/containers/helpers.test.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { TimelineId } from '../../../common/types/timeline'; +import { skipQueryForDetectionsPage } from './helpers'; + +describe('skipQueryForDetectionsPage', () => { + test('Make sure to NOT skip the query when it is not a timeline from a detection pages', () => { + expect(skipQueryForDetectionsPage(TimelineId.active, ['auditbeat-*', 'filebeat-*'])).toBe( + false + ); + expect( + skipQueryForDetectionsPage(TimelineId.hostsPageEvents, ['auditbeat-*', 'filebeat-*']) + ).toBe(false); + expect( + skipQueryForDetectionsPage(TimelineId.hostsPageExternalAlerts, ['auditbeat-*', 'filebeat-*']) + ).toBe(false); + expect( + skipQueryForDetectionsPage(TimelineId.networkPageExternalAlerts, [ + 'auditbeat-*', + 'filebeat-*', + ]) + ).toBe(false); + }); + + test('Make sure to SKIP the query when it is a timeline from a detection pages without the siem-signals', () => { + expect( + skipQueryForDetectionsPage(TimelineId.detectionsPage, ['auditbeat-*', 'filebeat-*']) + ).toBe(true); + expect( + skipQueryForDetectionsPage(TimelineId.detectionsRulesDetailsPage, [ + 'auditbeat-*', + 'filebeat-*', + ]) + ).toBe(true); + }); + + test('Make sure to NOT skip the query when it is a timeline from a detection pages with the siem-signals', () => { + expect( + skipQueryForDetectionsPage(TimelineId.detectionsPage, [ + 'auditbeat-*', + '.siem-signals-rainbow-butterfly', + ]) + ).toBe(false); + expect( + skipQueryForDetectionsPage(TimelineId.detectionsRulesDetailsPage, [ + '.siem-signals-rainbow-butterfly', + ]) + ).toBe(false); + }); +}); diff --git a/x-pack/plugins/security_solution/public/timelines/containers/helpers.ts b/x-pack/plugins/security_solution/public/timelines/containers/helpers.ts new file mode 100644 index 0000000000000..aef6f4df6f41b --- /dev/null +++ b/x-pack/plugins/security_solution/public/timelines/containers/helpers.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { TimelineId } from '../../../common/types/timeline'; + +export const detectionsTimelineIds = [ + TimelineId.detectionsPage, + TimelineId.detectionsRulesDetailsPage, +]; + +export const skipQueryForDetectionsPage = (id: string, defaultIndex: string[]) => + id != null && + detectionsTimelineIds.some((timelineId) => timelineId === id) && + !defaultIndex.some((di) => di.toLowerCase().startsWith('.siem-signals')); diff --git a/x-pack/plugins/security_solution/public/timelines/containers/index.tsx b/x-pack/plugins/security_solution/public/timelines/containers/index.tsx index 562999108b4b0..de7175f0a7f97 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/containers/index.tsx @@ -11,7 +11,6 @@ import { Query } from 'react-apollo'; import { compose, Dispatch } from 'redux'; import { connect, ConnectedProps } from 'react-redux'; -import { TimelineId } from '../../../common/types/timeline'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { IIndexPattern } from '../../../../../../src/plugins/data/common/index_patterns'; import { @@ -28,8 +27,7 @@ import { QueryTemplate, QueryTemplateProps } from '../../common/containers/query import { EventType } from '../../timelines/store/timeline/model'; import { timelineQuery } from './index.gql_query'; import { timelineActions } from '../../timelines/store/timeline'; - -const timelineIds = [TimelineId.detectionsPage, TimelineId.detectionsRulesDetailsPage]; +import { detectionsTimelineIds, skipQueryForDetectionsPage } from './helpers'; export interface TimelineArgs { events: TimelineItem[]; @@ -130,6 +128,7 @@ class TimelineQueryComponent extends QueryTemplate< query={timelineQuery} fetchPolicy="network-only" notifyOnNetworkStatusChange + skip={skipQueryForDetectionsPage(id, defaultIndex)} variables={variables} > {({ data, loading, fetchMore, refetch }) => { @@ -202,7 +201,7 @@ const makeMapStateToProps = () => { const mapDispatchToProps = (dispatch: Dispatch) => ({ clearSignalsState: ({ id }: { id?: string }) => { - if (id != null && timelineIds.some((timelineId) => timelineId === id)) { + if (id != null && detectionsTimelineIds.some((timelineId) => timelineId === id)) { dispatch(timelineActions.clearEventsLoading({ id })); dispatch(timelineActions.clearEventsDeleted({ id })); } diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/children.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/children.test.ts index 8175764b3a0a2..4e210e0237fcd 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/children.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/children.test.ts @@ -4,12 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ import { ChildrenQuery } from './children'; -import { PaginationBuilder } from '../utils/pagination'; +import { ChildrenPaginationBuilder } from '../utils/children_pagination'; import { legacyEventIndexPattern } from './legacy_event_index_pattern'; describe('Children query', () => { it('constructs a legacy multi search query', () => { - const query = new ChildrenQuery(new PaginationBuilder(1), 'index-pattern', 'endpointID'); + const query = new ChildrenQuery( + new ChildrenPaginationBuilder(1), + 'index-pattern', + 'endpointID' + ); // using any here because otherwise ts complains that it doesn't know what bool and filter are // eslint-disable-next-line @typescript-eslint/no-explicit-any const msearch: any = query.buildMSearch('1234'); @@ -20,7 +24,7 @@ describe('Children query', () => { }); it('constructs a non-legacy multi search query', () => { - const query = new ChildrenQuery(new PaginationBuilder(1), 'index-pattern'); + const query = new ChildrenQuery(new ChildrenPaginationBuilder(1), 'index-pattern'); // using any here because otherwise ts complains that it doesn't know what bool and filter are // eslint-disable-next-line @typescript-eslint/no-explicit-any const msearch: any = query.buildMSearch(['1234', '5678']); diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/children.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/children.ts index 902d287a09e42..6fb38a32f9581 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/children.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/children.ts @@ -6,7 +6,7 @@ import { SearchResponse } from 'elasticsearch'; import { ResolverEvent } from '../../../../../common/endpoint/types'; import { ResolverQuery } from './base'; -import { PaginationBuilder } from '../utils/pagination'; +import { ChildrenPaginationBuilder } from '../utils/children_pagination'; import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/common'; /** @@ -14,7 +14,7 @@ import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/com */ export class ChildrenQuery extends ResolverQuery { constructor( - private readonly pagination: PaginationBuilder, + private readonly pagination: ChildrenPaginationBuilder, indexPattern: string | string[], endpointID?: string ) { @@ -32,6 +32,7 @@ export class ChildrenQuery extends ResolverQuery { query: { bool: { filter: [ + ...paginationFields.filters, { terms: { 'endgame.unique_ppid': uniquePIDs }, }, @@ -63,7 +64,7 @@ export class ChildrenQuery extends ResolverQuery { } protected query(entityIDs: string[]): JsonObject { - const paginationFields = this.pagination.buildQueryFieldsAsInterface('event.id'); + const paginationFields = this.pagination.buildQueryFields('event.id'); return { /** * Using collapse here will only return a single event per occurrence of a process.entity_id. The events are sorted @@ -80,12 +81,12 @@ export class ChildrenQuery extends ResolverQuery { collapse: { field: 'process.entity_id', }, - // do not set the search_after field because collapse does not work with it size: paginationFields.size, sort: paginationFields.sort, query: { bool: { filter: [ + ...paginationFields.filters, { bool: { should: [ diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/children_helper.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/children_helper.ts index ef487897e3b4e..b82b972b887b5 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/children_helper.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/children_helper.ts @@ -16,7 +16,7 @@ import { ResolverChildren, } from '../../../../../common/endpoint/types'; import { createChild } from './node'; -import { PaginationBuilder } from './pagination'; +import { ChildrenPaginationBuilder } from './children_pagination'; /** * This class helps construct the children structure when building a resolver tree. @@ -162,7 +162,7 @@ export class ChildrenNodesHelper { for (const nodeEntityID of nodes.values()) { const cachedNode = this.entityToNodeCache.get(nodeEntityID); if (cachedNode) { - cachedNode.nextChild = PaginationBuilder.buildCursor(startEvents); + cachedNode.nextChild = ChildrenPaginationBuilder.buildCursor(startEvents); } } } diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/children_pagination.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/children_pagination.ts new file mode 100644 index 0000000000000..1e154caf70c48 --- /dev/null +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/children_pagination.ts @@ -0,0 +1,129 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ResolverEvent } from '../../../../../common/endpoint/types'; +import { eventSequence } from '../../../../../common/endpoint/models/event'; +import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/common'; +import { urlEncodeCursor, SortFields, urlDecodeCursor } from './pagination'; + +/** + * Pagination information for the children class. + */ +export interface ChildrenPaginationCursor { + timestamp: number; + sequence: number; +} + +/** + * Interface for defining the returned pagination information. + */ +export interface ChildrenPaginationFields { + sort: SortFields; + size: number; + filters: JsonObject[]; +} + +/** + * This class handles constructing pagination cursors that resolver can use to return additional events in subsequent + * queries. + */ +export class ChildrenPaginationBuilder { + constructor( + /** + * upper limit of how many results should be returned by the parent query. + */ + private readonly size: number, + /** + * timestamp that will be used in the search_after section + */ + private readonly timestamp?: number, + /** + * unique sequence number for the event + */ + private readonly sequence?: number + ) {} + + /** + * This function validates that the parsed cursor is a ChildrenPaginationCursor. + * + * @param parsed an object parsed from an encoded cursor. + */ + static decode( + parsed: ChildrenPaginationCursor | undefined + ): ChildrenPaginationCursor | undefined { + if (parsed && parsed.timestamp && parsed.sequence) { + const { timestamp, sequence } = parsed; + return { timestamp, sequence }; + } + } + + /** + * Construct a cursor to use in subsequent queries. + * + * @param results the events that were returned by the ES query + */ + static buildCursor(results: ResolverEvent[]): string | null { + const lastResult = results[results.length - 1]; + const sequence = eventSequence(lastResult); + const cursor = { + timestamp: lastResult['@timestamp'], + sequence: sequence === undefined ? 0 : sequence, + }; + return urlEncodeCursor(cursor); + } + + /** + * Creates a PaginationBuilder with an upper bound limit of results and a specific cursor to use to retrieve the next + * set of results. + * + * @param limit upper bound for the number of results to return within this query + * @param after a cursor to retrieve the next set of results + */ + static createBuilder(limit: number, after?: string): ChildrenPaginationBuilder { + if (after) { + try { + const cursor = urlDecodeCursor(after, ChildrenPaginationBuilder.decode); + if (cursor && cursor.timestamp && cursor.sequence) { + return new ChildrenPaginationBuilder(limit, cursor.timestamp, cursor.sequence); + } + } catch (err) { + /* tslint:disable:no-empty */ + } // ignore invalid cursor values + } + return new ChildrenPaginationBuilder(limit); + } + + /** + * Helper for creates an object for adding the pagination fields to a query + * + * @param tiebreaker a unique field to use as the tiebreaker for the search_after + * @returns an object containing the pagination information + */ + buildQueryFields(tiebreaker: string): ChildrenPaginationFields { + const sort: SortFields = [{ '@timestamp': 'asc' }, { [tiebreaker]: 'asc' }]; + const filters: JsonObject[] = []; + if (this.timestamp && this.sequence) { + filters.push( + { + range: { + '@timestamp': { + gte: this.timestamp, + }, + }, + }, + { + range: { + 'event.sequence': { + gt: this.sequence, + }, + }, + } + ); + } + + return { sort, size: this.size, filters }; + } +} diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/children_start_query_handler.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/children_start_query_handler.ts index 1c74184720793..30d46d12afbe5 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/children_start_query_handler.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/children_start_query_handler.ts @@ -11,7 +11,7 @@ import { ChildrenQuery } from '../queries/children'; import { QueryInfo } from '../queries/multi_searcher'; import { QueryHandler } from './fetch'; import { ChildrenNodesHelper } from './children_helper'; -import { PaginationBuilder } from './pagination'; +import { ChildrenPaginationBuilder } from './children_pagination'; /** * Retrieve the start lifecycle events for the children of a resolver tree. @@ -32,7 +32,7 @@ export class ChildrenStartQueryHandler implements QueryHandler = (parsed: T | undefined) => T | undefined; + /** * Interface for defining the returned pagination information. */ @@ -31,10 +41,42 @@ export interface PaginationFields { searchAfter?: SearchAfterFields; } +/** + * A function to encode a cursor from a pagination object. + * + * @param data Transforms a pagination cursor into a base64 encoded string + */ +export function urlEncodeCursor(data: PaginationCursor | ChildrenPaginationCursor): string { + const value = JSON.stringify(data); + return Buffer.from(value, 'utf8') + .toString('base64') + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=+$/g, ''); +} + +/** + * A function to decode a cursor. + * + * @param cursor a cursor encoded by the `urlEncodeCursor` function + * @param decode a function to transform the parsed data into an actual type + */ +export function urlDecodeCursor(cursor: string, decode: Decoder): T | undefined { + const fixedCursor = cursor.replace(/\-/g, '+').replace(/_/g, '/'); + const data = Buffer.from(fixedCursor, 'base64').toString('utf8'); + let parsed: T; + try { + parsed = JSON.parse(data); + } catch (e) { + return; + } + + return decode(parsed); +} + /** * This class handles constructing pagination cursors that resolver can use to return additional events in subsequent - * queries. It also constructs an aggregation query to determine the totals for other queries. This class should be used - * with a query to build cursors for paginated results. + * queries. */ export class PaginationBuilder { constructor( @@ -52,22 +94,16 @@ export class PaginationBuilder { private readonly eventID?: string ) {} - private static urlEncodeCursor(data: PaginationCursor): string { - const value = JSON.stringify(data); - return Buffer.from(value, 'utf8') - .toString('base64') - .replace(/\+/g, '-') - .replace(/\//g, '_') - .replace(/=+$/g, ''); - } - - private static urlDecodeCursor(cursor: string): PaginationCursor { - const fixedCursor = cursor.replace(/\-/g, '+').replace(/_/g, '/'); - const data = Buffer.from(fixedCursor, 'base64').toString('utf8'); - const { timestamp, eventID } = JSON.parse(data); - // take some extra care to only grab the things we want - // convert the timestamp string to date object - return { timestamp, eventID }; + /** + * Validates that the parsed object is actually a PaginationCursor. + * + * @param parsed an object parsed from an encoded cursor. + */ + static decode(parsed: PaginationCursor | undefined): PaginationCursor | undefined { + if (parsed && parsed.timestamp && parsed.eventID) { + const { timestamp, eventID } = parsed; + return { timestamp, eventID }; + } } /** @@ -81,7 +117,7 @@ export class PaginationBuilder { timestamp: lastResult['@timestamp'], eventID: eventId(lastResult) === undefined ? '' : String(eventId(lastResult)), }; - return PaginationBuilder.urlEncodeCursor(cursor); + return urlEncodeCursor(cursor); } /** @@ -107,8 +143,8 @@ export class PaginationBuilder { static createBuilder(limit: number, after?: string): PaginationBuilder { if (after) { try { - const cursor = PaginationBuilder.urlDecodeCursor(after); - if (cursor.timestamp && cursor.eventID) { + const cursor = urlDecodeCursor(after, PaginationBuilder.decode); + if (cursor && cursor.timestamp && cursor.eventID) { return new PaginationBuilder(limit, cursor.timestamp, cursor.eventID); } } catch (err) { diff --git a/x-pack/plugins/security_solution/server/lib/hosts/mock.ts b/x-pack/plugins/security_solution/server/lib/hosts/mock.ts index 44767563c6b75..97aa68c0f9bbf 100644 --- a/x-pack/plugins/security_solution/server/lib/hosts/mock.ts +++ b/x-pack/plugins/security_solution/server/lib/hosts/mock.ts @@ -588,7 +588,7 @@ export const mockEndpointMetadata = { type: 'endpoint', version: '7.9.0-SNAPSHOT', }, - dataset: { name: 'endpoint.metadata', namespace: 'default', type: 'metrics' }, + data_stream: { dataset: 'endpoint.metadata', namespace: 'default', type: 'metrics' }, ecs: { version: '1.5.0' }, elastic: { agent: { id: '' } }, event: { diff --git a/x-pack/plugins/security_solution/server/lib/timeline/routes/export_timelines_route.test.ts b/x-pack/plugins/security_solution/server/lib/timeline/routes/export_timelines_route.test.ts index a6f0ce232fa7b..5a976ee7521af 100644 --- a/x-pack/plugins/security_solution/server/lib/timeline/routes/export_timelines_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/timeline/routes/export_timelines_route.test.ts @@ -110,7 +110,7 @@ describe('export timelines', () => { const result = server.validate(request); expect(result.badRequest.mock.calls[0][0]).toEqual( - 'Invalid value "someId" supplied to "ids",Invalid value "someId" supplied to "ids",Invalid value "{"ids":"someId"}" supplied to "(Partial<{ ids: (Array | null) }> | null)"' + 'Invalid value "someId" supplied to "ids",Invalid value "{"ids":"someId"}" supplied to "(Partial<{ ids: (Array | null) }> | null)"' ); }); }); diff --git a/x-pack/plugins/security_solution/server/lib/timeline/routes/import_timelines_route.test.ts b/x-pack/plugins/security_solution/server/lib/timeline/routes/import_timelines_route.test.ts index 2ad6c5d6fff60..ff76045db90cb 100644 --- a/x-pack/plugins/security_solution/server/lib/timeline/routes/import_timelines_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/timeline/routes/import_timelines_route.test.ts @@ -494,10 +494,7 @@ describe('import timelines', () => { const result = server.validate(request); expect(result.badRequest).toHaveBeenCalledWith( - [ - 'Invalid value "undefined" supplied to "file"', - 'Invalid value "undefined" supplied to "file"', - ].join(',') + 'Invalid value "undefined" supplied to "file"' ); }); }); @@ -923,10 +920,7 @@ describe('import timeline templates', () => { const result = server.validate(request); expect(result.badRequest).toHaveBeenCalledWith( - [ - 'Invalid value "undefined" supplied to "file"', - 'Invalid value "undefined" supplied to "file"', - ].join(',') + 'Invalid value "undefined" supplied to "file"' ); }); }); diff --git a/x-pack/plugins/security_solution/server/usage/endpoints/index.ts b/x-pack/plugins/security_solution/server/usage/endpoints/index.ts index 19beda4554d93..f1ce9d3ad6ff3 100644 --- a/x-pack/plugins/security_solution/server/usage/endpoints/index.ts +++ b/x-pack/plugins/security_solution/server/usage/endpoints/index.ts @@ -33,7 +33,7 @@ export interface EndpointUsage { policies: PoliciesTelemetry; } -type EndpointOSNames = 'Linux' | 'Windows' | 'macOs'; +type EndpointOSNames = 'Linux' | 'Windows' | 'macOS'; export interface AgentLocalMetadata extends AgentMetadata { elastic: { @@ -129,7 +129,7 @@ export const updateEndpointPolicyTelemetry = ( ): PoliciesTelemetry => { const policyHostTypeToPolicyType = { Linux: 'linux', - macOs: 'mac', + macOS: 'mac', Windows: 'windows', }; const enabledMalwarePolicyTypes = ['prevent', 'detect']; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 8218904f77df9..c796aacda10a0 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -8206,8 +8206,6 @@ "xpack.indexLifecycleMgmt.editPolicy.nodeAllocationLabel": "シャードの割当をコントロールするノード属性を選択", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesMissingDescription": "ノード属性なしではシャードの割り当てをコントロールできません。", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesMissingLabel": "elasticsearch.yml でノード属性が構成されていません", - "xpack.indexLifecycleMgmt.editPolicy.nodeDetailErrorMessage": "ノード属性の詳細の読み込み中にエラーが発生しました", - "xpack.indexLifecycleMgmt.editPolicy.nodeInfoErrorMessage": "ノード属性の情報の読み込み中にエラーが発生しました", "xpack.indexLifecycleMgmt.editPolicy.numberRequiredError": "数字が必要です。", "xpack.indexLifecycleMgmt.editPolicy.phaseCold.minimumAgeLabel": "コールドフェーズのタイミング", "xpack.indexLifecycleMgmt.editPolicy.phaseCold.minimumAgeUnitsAriaLabel": "コールドフェーズのタイミングの単位", @@ -8831,7 +8829,8 @@ "xpack.infra.metrics.alertFlyout.alertPreviewErrorResult": "一部のデータを評価するときにエラーが発生しました。", "xpack.infra.metrics.alertFlyout.alertPreviewGroups": "{numberOfGroups} {groupName}", "xpack.infra.metrics.alertFlyout.alertPreviewGroupsAcross": "すべてを対象にする", - "xpack.infra.metrics.alertFlyout.alertPreviewNoDataResult": "データがない {noData}結果がありました。", + "xpack.infra.metrics.alertFlyout.alertPreviewNoDataResult": "データがない {boldedResultsNumber}結果がありました。", + "xpack.infra.metrics.alertFlyout.alertPreviewNoDataResultNumber": "{noData}", "xpack.infra.metrics.alertFlyout.alertPreviewResult": "このアラートは{firedTimes}回発生しました", "xpack.infra.metrics.alertFlyout.alertPreviewResultLookback": "過去{lookback}", "xpack.infra.metrics.alertFlyout.conditions": "条件", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 21a42362bcdd3..4c48a66b3c3c8 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -8208,8 +8208,6 @@ "xpack.indexLifecycleMgmt.editPolicy.nodeAllocationLabel": "选择节点属性来控制分片分配", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesMissingDescription": "没有节点属性,将无法控制分片分配。", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesMissingLabel": "elasticsearch.yml 中未配置任何节点属性", - "xpack.indexLifecycleMgmt.editPolicy.nodeDetailErrorMessage": "加载节点属性详细信息时出错", - "xpack.indexLifecycleMgmt.editPolicy.nodeInfoErrorMessage": "加载节点属性信息时出错", "xpack.indexLifecycleMgmt.editPolicy.numberRequiredError": "数字必填。", "xpack.indexLifecycleMgmt.editPolicy.phaseCold.minimumAgeLabel": "冷阶段计时", "xpack.indexLifecycleMgmt.editPolicy.phaseCold.minimumAgeUnitsAriaLabel": "冷阶段计时单位", @@ -8833,7 +8831,8 @@ "xpack.infra.metrics.alertFlyout.alertPreviewErrorResult": "尝试评估部分数据时发生错误。", "xpack.infra.metrics.alertFlyout.alertPreviewGroups": "{numberOfGroups} 个{groupName}", "xpack.infra.metrics.alertFlyout.alertPreviewGroupsAcross": "在", - "xpack.infra.metrics.alertFlyout.alertPreviewNoDataResult": "存在 {noData} 个无数据结果。", + "xpack.infra.metrics.alertFlyout.alertPreviewNoDataResult": "存在 {boldedResultsNumber} 个无数据结果。", + "xpack.infra.metrics.alertFlyout.alertPreviewNoDataResultNumber": "{noData}", "xpack.infra.metrics.alertFlyout.alertPreviewResult": "此告警将发生 {firedTimes}", "xpack.infra.metrics.alertFlyout.alertPreviewResultLookback": "在过去 {lookback}。", "xpack.infra.metrics.alertFlyout.conditions": "条件", diff --git a/x-pack/plugins/uptime/common/runtime_types/ping/ping.ts b/x-pack/plugins/uptime/common/runtime_types/ping/ping.ts index 5ed71acaf7739..0a4d6310927c4 100644 --- a/x-pack/plugins/uptime/common/runtime_types/ping/ping.ts +++ b/x-pack/plugins/uptime/common/runtime_types/ping/ping.ts @@ -143,7 +143,7 @@ export const PingType = t.intersection([ response: t.partial({ body: HttpResponseBodyType, bytes: t.number, - redirects: t.string, + redirects: t.array(t.string), status_code: t.number, }), version: t.string, diff --git a/x-pack/plugins/uptime/public/apps/uptime_app.tsx b/x-pack/plugins/uptime/public/apps/uptime_app.tsx index 41370f9fff492..1dc34b44b7c64 100644 --- a/x-pack/plugins/uptime/public/apps/uptime_app.tsx +++ b/x-pack/plugins/uptime/public/apps/uptime_app.tsx @@ -10,7 +10,10 @@ import React, { useEffect } from 'react'; import { Provider as ReduxProvider } from 'react-redux'; import { BrowserRouter as Router } from 'react-router-dom'; import { I18nStart, ChromeBreadcrumb, CoreStart } from 'kibana/public'; -import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; +import { + KibanaContextProvider, + RedirectAppLinks, +} from '../../../../../src/plugins/kibana_react/public'; import { ClientPluginsSetup, ClientPluginsStart } from './plugin'; import { UMUpdateBadge } from '../lib/lib'; import { @@ -103,10 +106,12 @@ const Application = (props: UptimeAppProps) => { -
- - -
+ +
+ + +
+
diff --git a/x-pack/plugins/uptime/public/components/common/react_router_helpers/__tests__/link_events.test.ts b/x-pack/plugins/uptime/public/components/common/react_router_helpers/__tests__/link_events.test.ts new file mode 100644 index 0000000000000..3e857c7c20904 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/common/react_router_helpers/__tests__/link_events.test.ts @@ -0,0 +1,102 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { letBrowserHandleEvent } from '../index'; + +describe('letBrowserHandleEvent', () => { + const event = { + defaultPrevented: false, + metaKey: false, + altKey: false, + ctrlKey: false, + shiftKey: false, + button: 0, + target: { + getAttribute: () => '_self', + }, + } as any; + + describe('the browser should handle the link when', () => { + it('default is prevented', () => { + expect(letBrowserHandleEvent({ ...event, defaultPrevented: true })).toBe(true); + }); + + it('is modified with metaKey', () => { + expect(letBrowserHandleEvent({ ...event, metaKey: true })).toBe(true); + }); + + it('is modified with altKey', () => { + expect(letBrowserHandleEvent({ ...event, altKey: true })).toBe(true); + }); + + it('is modified with ctrlKey', () => { + expect(letBrowserHandleEvent({ ...event, ctrlKey: true })).toBe(true); + }); + + it('is modified with shiftKey', () => { + expect(letBrowserHandleEvent({ ...event, shiftKey: true })).toBe(true); + }); + + it('it is not a left click event', () => { + expect(letBrowserHandleEvent({ ...event, button: 2 })).toBe(true); + }); + + it('the target is anything value other than _self', () => { + expect( + letBrowserHandleEvent({ + ...event, + target: targetValue('_blank'), + }) + ).toBe(true); + }); + }); + + describe('the browser should NOT handle the link when', () => { + it('default is not prevented', () => { + expect(letBrowserHandleEvent({ ...event, defaultPrevented: false })).toBe(false); + }); + + it('is not modified', () => { + expect( + letBrowserHandleEvent({ + ...event, + metaKey: false, + altKey: false, + ctrlKey: false, + shiftKey: false, + }) + ).toBe(false); + }); + + it('it is a left click event', () => { + expect(letBrowserHandleEvent({ ...event, button: 0 })).toBe(false); + }); + + it('the target is a value of _self', () => { + expect( + letBrowserHandleEvent({ + ...event, + target: targetValue('_self'), + }) + ).toBe(false); + }); + + it('the target has no value', () => { + expect( + letBrowserHandleEvent({ + ...event, + target: targetValue(null), + }) + ).toBe(false); + }); + }); +}); + +const targetValue = (value: string | null) => { + return { + getAttribute: () => value, + }; +}; diff --git a/x-pack/plugins/uptime/public/components/common/react_router_helpers/__tests__/link_for_eui.test.tsx b/x-pack/plugins/uptime/public/components/common/react_router_helpers/__tests__/link_for_eui.test.tsx new file mode 100644 index 0000000000000..4a681f6fa60bf --- /dev/null +++ b/x-pack/plugins/uptime/public/components/common/react_router_helpers/__tests__/link_for_eui.test.tsx @@ -0,0 +1,77 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { shallow, mount } from 'enzyme'; +import { EuiLink, EuiButton } from '@elastic/eui'; + +import '../../../../lib/__mocks__/react_router_history.mock'; + +import { ReactRouterEuiLink, ReactRouterEuiButton } from '../link_for_eui'; +import { mockHistory } from '../../../../lib/__mocks__'; + +describe('EUI & React Router Component Helpers', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders', () => { + const wrapper = shallow(); + + expect(wrapper.find(EuiLink)).toHaveLength(1); + }); + + it('renders an EuiButton', () => { + const wrapper = shallow(); + + expect(wrapper.find(EuiButton)).toHaveLength(1); + }); + + it('passes down all ...rest props', () => { + const wrapper = shallow(); + const link = wrapper.find(EuiLink); + + expect(link.prop('external')).toEqual(true); + expect(link.prop('data-test-subj')).toEqual('foo'); + }); + + it('renders with the correct href and onClick props', () => { + const wrapper = mount(); + const link = wrapper.find(EuiLink); + + expect(link.prop('onClick')).toBeInstanceOf(Function); + expect(link.prop('href')).toEqual('/enterprise_search/foo/bar'); + expect(mockHistory.createHref).toHaveBeenCalled(); + }); + + describe('onClick', () => { + it('prevents default navigation and uses React Router history', () => { + const wrapper = mount(); + + const simulatedEvent = { + button: 0, + target: { getAttribute: () => '_self' }, + preventDefault: jest.fn(), + }; + wrapper.find(EuiLink).simulate('click', simulatedEvent); + + expect(simulatedEvent.preventDefault).toHaveBeenCalled(); + expect(mockHistory.push).toHaveBeenCalled(); + }); + + it('does not prevent default browser behavior on new tab/window clicks', () => { + const wrapper = mount(); + + const simulatedEvent = { + shiftKey: true, + target: { getAttribute: () => '_blank' }, + }; + wrapper.find(EuiLink).simulate('click', simulatedEvent); + + expect(mockHistory.push).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/x-pack/plugins/uptime/public/components/common/react_router_helpers/index.ts b/x-pack/plugins/uptime/public/components/common/react_router_helpers/index.ts new file mode 100644 index 0000000000000..a1885eaee4cbe --- /dev/null +++ b/x-pack/plugins/uptime/public/components/common/react_router_helpers/index.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { letBrowserHandleEvent } from './link_events'; +export { + ReactRouterEuiLink, + ReactRouterEuiButton, + ReactRouterEuiButtonEmpty, +} from './link_for_eui'; diff --git a/x-pack/plugins/uptime/public/components/common/react_router_helpers/link_events.ts b/x-pack/plugins/uptime/public/components/common/react_router_helpers/link_events.ts new file mode 100644 index 0000000000000..93da2ab71d952 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/common/react_router_helpers/link_events.ts @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { MouseEvent } from 'react'; + +/** + * Helper functions for determining which events we should + * let browsers handle natively, e.g. new tabs/windows + */ + +type THandleEvent = (event: MouseEvent) => boolean; + +export const letBrowserHandleEvent: THandleEvent = (event) => + event.defaultPrevented || + isModifiedEvent(event) || + !isLeftClickEvent(event) || + isTargetBlank(event); + +const isModifiedEvent: THandleEvent = (event) => + !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); + +const isLeftClickEvent: THandleEvent = (event) => event.button === 0; + +const isTargetBlank: THandleEvent = (event) => { + const element = event.target as HTMLElement; + const target = element.getAttribute('target'); + return !!target && target !== '_self'; +}; diff --git a/x-pack/plugins/uptime/public/components/common/react_router_helpers/link_for_eui.tsx b/x-pack/plugins/uptime/public/components/common/react_router_helpers/link_for_eui.tsx new file mode 100644 index 0000000000000..7adc8be4533bc --- /dev/null +++ b/x-pack/plugins/uptime/public/components/common/react_router_helpers/link_for_eui.tsx @@ -0,0 +1,74 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { useHistory } from 'react-router-dom'; +import { + EuiLink, + EuiButton, + EuiButtonProps, + EuiButtonEmptyProps, + EuiLinkAnchorProps, + EuiButtonEmpty, +} from '@elastic/eui'; + +import { letBrowserHandleEvent } from './link_events'; + +/** + * Generates either an EuiLink or EuiButton with a React-Router-ified link + * + * Based off of EUI's recommendations for handling React Router: + * https://github.com/elastic/eui/blob/master/wiki/react-router.md#react-router-51 + */ + +interface IEuiReactRouterProps { + to: string; +} + +export const ReactRouterHelperForEui: React.FC = ({ to, children }) => { + const history = useHistory(); + + const onClick = (event: React.MouseEvent) => { + if (letBrowserHandleEvent(event)) return; + + // Prevent regular link behavior, which causes a browser refresh. + event.preventDefault(); + + // Push the route to the history. + history.push(to); + }; + + // Generate the correct link href (with basename etc. accounted for) + const href = history.createHref({ pathname: to }); + + const reactRouterProps = { href, onClick }; + return React.cloneElement(children as React.ReactElement, reactRouterProps); +}; + +type TEuiReactRouterLinkProps = EuiLinkAnchorProps & IEuiReactRouterProps; +type TEuiReactRouterButtonProps = EuiButtonProps & IEuiReactRouterProps; +type TEuiReactRouterButtonEmptyProps = EuiButtonEmptyProps & IEuiReactRouterProps; + +export const ReactRouterEuiLink: React.FC = ({ to, ...rest }) => ( + + + +); + +export const ReactRouterEuiButton: React.FC = ({ to, ...rest }) => ( + + + +); + +export const ReactRouterEuiButtonEmpty: React.FC = ({ + to, + ...rest +}) => ( + + + +); diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap index 15f5c03512bf1..e7ad86f72dab6 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap @@ -8,6 +8,7 @@ exports[`ML Integrations renders without errors 1`] = ` class="euiPopover__anchor" >
diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap index fabe94763e07d..cc3417e09987e 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap @@ -8,6 +8,7 @@ exports[`Manage ML Job renders without errors 1`] = ` class="euiPopover__anchor" >
diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/manage_ml_job.tsx b/x-pack/plugins/uptime/public/components/monitor/ml/manage_ml_job.tsx index 7a2899558891d..f4382b37b3d30 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ml/manage_ml_job.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ml/manage_ml_job.tsx @@ -54,6 +54,10 @@ export const ManageMLJobComponent = ({ hasMLJob, onEnableJob, onJobDelete }: Pro const deleteAnomalyAlert = () => dispatch(deleteAlertAction.get({ alertId: anomalyAlert?.id as string })); + const showLoading = isMLJobCreating || isMLJobLoading; + + const btnText = hasMLJob ? labels.ANOMALY_DETECTION : labels.ENABLE_ANOMALY_DETECTION; + const button = ( - {hasMLJob ? labels.ANOMALY_DETECTION : labels.ENABLE_ANOMALY_DETECTION} + {showLoading ? '' : btnText} ); @@ -79,7 +84,6 @@ export const ManageMLJobComponent = ({ hasMLJob, onEnableJob, onJobDelete }: Pro monitorId, dateRange: { from: dateRangeStart, to: dateRangeEnd }, }), - target: '_blank', }, { name: anomalyAlert ? labels.DISABLE_ANOMALY_ALERT : labels.ENABLE_ANOMALY_ALERT, diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/translations.tsx b/x-pack/plugins/uptime/public/components/monitor/ml/translations.tsx index 90ebdf10a73f5..dfc912e6be9ee 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ml/translations.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ml/translations.tsx @@ -162,3 +162,11 @@ export const START_TRAIL_DESC = i18n.translate( 'In order to access duration anomaly detection, you have to be subscribed to an Elastic Platinum license.', } ); + +export const ENABLE_MANAGE_JOB = i18n.translate( + 'xpack.uptime.ml.enableAnomalyDetectionPanel.enable_or_manage_job', + { + defaultMessage: + 'You can enable anomaly detection job or if job is already there you can manage the job or alert.', + } +); diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/__tests__/__snapshots__/expanded_row.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/ping_list/__tests__/__snapshots__/expanded_row.test.tsx.snap index 004de391a51a4..11bdf134bd0e8 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/__tests__/__snapshots__/expanded_row.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/__tests__/__snapshots__/expanded_row.test.tsx.snap @@ -1,7 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`PingListExpandedRow doesn't render list items if the body field is undefined 1`] = ` - + + + + +
+ { }); } return ( - + + {ping?.http?.response?.redirects && ( + + + + )} diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/ping_list.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/ping_list.tsx index 576810bba24fd..09782c1b76edb 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/ping_list.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/ping_list.tsx @@ -237,6 +237,7 @@ export const PingListComponent = (props: Props) => { render: (item: Ping) => { return ( toggleDetails(item, expandedRows, setExpandedRows)} disabled={!item.error && !(item.http?.response?.body?.bytes ?? 0 > 0)} aria-label={ diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/ping_redirects.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/ping_redirects.tsx new file mode 100644 index 0000000000000..b3e59615cbce5 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/ping_redirects.tsx @@ -0,0 +1,97 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import styled from 'styled-components'; +import { EuiListGroup, EuiListGroupItemProps, EuiPanel, EuiSpacer, EuiText } from '@elastic/eui'; +import { Ping } from '../../../../common/runtime_types/ping'; + +const ListGroup = styled(EuiListGroup)` + &&& { + a { + padding-left: 0; + } + } +`; + +interface Props { + monitorStatus: Ping | null; + showTitle?: boolean; +} + +export const PingRedirects: React.FC = ({ monitorStatus, showTitle }) => { + const monitorUrl = monitorStatus?.url?.full; + + const list = monitorStatus?.http?.response?.redirects; + + const listOfRedirects: EuiListGroupItemProps[] = [ + { + label: monitorUrl, + href: monitorUrl, + iconType: 'globe', + size: 's', + target: '_blank', + extraAction: { + color: 'subdued', + iconType: 'popout', + iconSize: 's', + alwaysShow: true, + 'aria-label': i18n.translate('xpack.uptime.monitorList.redirects.openWindow', { + defaultMessage: 'Link will open in new window.', + }), + }, + }, + ]; + + (list ?? []).forEach((url: string) => { + listOfRedirects.push({ + label: url, + href: url, + iconType: 'sortDown', + size: 's', + target: '_blank', + extraAction: { + color: 'subdued', + iconType: 'popout', + iconSize: 's', + 'aria-label': i18n.translate('xpack.uptime.monitorList.redirects.openWindow', { + defaultMessage: 'Link will open in new window.', + }), + alwaysShow: true, + }, + }); + }); + + const Panel = showTitle ? EuiPanel : 'div'; + + return list ? ( + + {showTitle && ( + +

+ {i18n.translate('xpack.uptime.monitorList.redirects.title', { + defaultMessage: 'Redirects', + })} +

+
+ )} + + { + + {i18n.translate('xpack.uptime.monitorList.redirects.description', { + defaultMessage: 'Heartbeat followed {number} redirects while executing ping.', + values: { + number: list?.length ?? 0, + }, + })} + + } + + +
+ ) : null; +}; diff --git a/x-pack/plugins/uptime/public/components/monitor/status_details/status_bar/monitor_redirects.tsx b/x-pack/plugins/uptime/public/components/monitor/status_details/status_bar/monitor_redirects.tsx new file mode 100644 index 0000000000000..5129db9c2135b --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/status_details/status_bar/monitor_redirects.tsx @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiPopover } from '@elastic/eui'; +import styled from 'styled-components'; +import { Ping } from '../../../../../common/runtime_types'; +import { PingRedirects } from '../../ping_list/ping_redirects'; +import { MonListDescription, MonListTitle } from './status_bar'; + +interface Props { + monitorStatus: Ping | null; +} + +const RedirectBtn = styled.span` + cursor: pointer; +`; + +export const MonitorRedirects: React.FC = ({ monitorStatus }) => { + const list = monitorStatus?.http?.response?.redirects; + + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + + const button = ( + + setIsPopoverOpen(!isPopoverOpen)} + data-test-subj="uptimeMonitorRedirectInfo" + > + {i18n.translate('xpack.uptime.monitorList.redirects.title.number', { + defaultMessage: '{number}', + values: { + number: list?.length ?? 0, + }, + })} + + + ); + + return list ? ( + <> + Redirects + setIsPopoverOpen(false)} + > + + + + ) : null; +}; diff --git a/x-pack/plugins/uptime/public/components/monitor/status_details/status_bar/status_bar.tsx b/x-pack/plugins/uptime/public/components/monitor/status_details/status_bar/status_bar.tsx index afcc8fae7a8ac..4ea383567d71c 100644 --- a/x-pack/plugins/uptime/public/components/monitor/status_details/status_bar/status_bar.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/status_details/status_bar/status_bar.tsx @@ -23,6 +23,7 @@ import { MonitorIDLabel, OverallAvailability } from '../translations'; import { URL_LABEL } from '../../../common/translations'; import { MonitorLocations } from '../../../../../common/runtime_types/monitor'; import { formatAvailabilityValue } from '../availability_reporting/availability_reporting'; +import { MonitorRedirects } from './monitor_redirects'; export const MonListTitle = styled(EuiDescriptionListTitle)` &&& { @@ -76,6 +77,7 @@ export const MonitorStatusBar: React.FC = () => { {MonitorIDLabel} {monitorId} +
); diff --git a/x-pack/plugins/canvas/public/apps/export/export/load_workpad.js b/x-pack/plugins/uptime/public/lib/__mocks__/index.ts similarity index 72% rename from x-pack/plugins/canvas/public/apps/export/export/load_workpad.js rename to x-pack/plugins/uptime/public/lib/__mocks__/index.ts index 388bf00723f82..45ef5787927e1 100644 --- a/x-pack/plugins/canvas/public/apps/export/export/load_workpad.js +++ b/x-pack/plugins/uptime/public/lib/__mocks__/index.ts @@ -4,6 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; - -export const LoadWorkpad = () =>
Load a workpad...
; +export { mockHistory } from './react_router_history.mock'; diff --git a/x-pack/plugins/uptime/public/lib/__mocks__/react_router_history.mock.ts b/x-pack/plugins/uptime/public/lib/__mocks__/react_router_history.mock.ts new file mode 100644 index 0000000000000..fd422465d87f1 --- /dev/null +++ b/x-pack/plugins/uptime/public/lib/__mocks__/react_router_history.mock.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +/** + * NOTE: This variable name MUST start with 'mock*' in order for + * Jest to accept its use within a jest.mock() + */ +export const mockHistory = { + createHref: jest.fn(({ pathname }) => `/enterprise_search${pathname}`), + push: jest.fn(), + location: { + pathname: '/current-path', + }, +}; + +jest.mock('react-router-dom', () => ({ + useHistory: jest.fn(() => mockHistory), +})); + +/** + * For example usage, @see public/applications/shared/react_router_helpers/eui_link.test.tsx + */ diff --git a/x-pack/plugins/uptime/public/pages/certificates.tsx b/x-pack/plugins/uptime/public/pages/certificates.tsx index e46d228c6d21f..a524ce6ba9b71 100644 --- a/x-pack/plugins/uptime/public/pages/certificates.tsx +++ b/x-pack/plugins/uptime/public/pages/certificates.tsx @@ -29,6 +29,7 @@ import { certificatesSelector, getCertificatesAction } from '../state/certificat import { CertificateList, CertificateSearch, CertSort } from '../components/certificates'; import { ToggleAlertFlyoutButton } from '../components/overview/alerts/alerts_containers'; import { CLIENT_ALERT_TYPES } from '../../common/constants/alerts'; +import { ReactRouterEuiButtonEmpty } from '../components/common/react_router_helpers'; const DEFAULT_PAGE_SIZE = 10; const LOCAL_STORAGE_KEY = 'xpack.uptime.certList.pageSize'; @@ -79,15 +80,16 @@ export const CertificatesPage: React.FC = () => { <> - {labels.RETURN_TO_OVERVIEW} - + diff --git a/x-pack/plugins/uptime/public/pages/page_header.tsx b/x-pack/plugins/uptime/public/pages/page_header.tsx index 16279a63b5f40..325d82696d47c 100644 --- a/x-pack/plugins/uptime/public/pages/page_header.tsx +++ b/x-pack/plugins/uptime/public/pages/page_header.tsx @@ -7,12 +7,12 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiTitle, EuiSpacer, EuiButtonEmpty } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { useHistory } from 'react-router-dom'; import styled from 'styled-components'; import { UptimeDatePicker } from '../components/common/uptime_date_picker'; import { SETTINGS_ROUTE } from '../../common/constants'; import { ToggleAlertFlyoutButton } from '../components/overview/alerts/alerts_containers'; import { useKibana } from '../../../../../src/plugins/kibana_react/public'; +import { ReactRouterEuiButtonEmpty } from '../components/common/react_router_helpers'; interface PageHeaderProps { headingText: string | JSX.Element; @@ -58,7 +58,6 @@ export const PageHeader = React.memo( ) : null; const kibana = useKibana(); - const history = useHistory(); const extraLinkComponents = !extraLinks ? null : ( @@ -66,13 +65,13 @@ export const PageHeader = React.memo( - {SETTINGS_LINK_TEXT} - + { ); - const history = useHistory(); - return ( <> - {Translations.settings.returnToOverviewLinkLabel} - + diff --git a/x-pack/plugins/uptime/server/lib/helper/__test__/get_histogram_interval.test.ts b/x-pack/plugins/uptime/server/lib/helper/__test__/get_histogram_interval.test.ts index bddca1b863ce4..09b857f37e1df 100644 --- a/x-pack/plugins/uptime/server/lib/helper/__test__/get_histogram_interval.test.ts +++ b/x-pack/plugins/uptime/server/lib/helper/__test__/get_histogram_interval.test.ts @@ -10,11 +10,11 @@ import { assertCloseTo } from '../assert_close_to'; describe('getHistogramInterval', () => { it('specifies the interval necessary to divide a given timespan into equal buckets, rounded to the nearest integer, expressed in ms', () => { const interval = getHistogramInterval('now-15m', 'now', 10); - assertCloseTo(interval, 90000, 10); + assertCloseTo(interval, 90000, 20); }); it('will supply a default constant value for bucketCount when none is provided', () => { const interval = getHistogramInterval('now-15m', 'now'); - assertCloseTo(interval, 36000, 10); + assertCloseTo(interval, 36000, 20); }); }); diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts index 01384ec145236..669033fc6524a 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts @@ -32,7 +32,7 @@ describe('getLatestMonitor', () => { }, }, size: 1, - _source: ['url', 'monitor', 'observer', '@timestamp', 'tls.*'], + _source: ['url', 'monitor', 'observer', '@timestamp', 'tls.*', 'http'], sort: { '@timestamp': { order: 'desc' }, }, diff --git a/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts b/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts index a58208fc2bb96..3b4aeaf92c508 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts @@ -45,7 +45,7 @@ export const getLatestMonitor: UMElasticsearchQueryFn { expect(results.saved_overall).to.eql({ lnsMetric: 1, bar_stacked: 1, + lnsPie: 1, }); - expect(results.saved_overall_total).to.eql(2); + expect(results.saved_overall_total).to.eql(3); await esArchiver.unload('lens/basic'); }); diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/monitor_latest_status.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/monitor_latest_status.json index 9a33be807670e..f2927af172062 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/fixtures/monitor_latest_status.json +++ b/x-pack/test/api_integration/apis/uptime/rest/fixtures/monitor_latest_status.json @@ -7,6 +7,32 @@ "hostname": "avc-x1x" }, "@timestamp": "2019-09-11T03:40:34.371Z", + "http": { + "rtt": { + "response_header": { + "us": 262 + }, + "total": { + "us": 20331 + }, + "write_request": { + "us": 82 + }, + "content": { + "us": 57 + }, + "validate": { + "us": 319 + } + }, + "response": { + "status_code": 200, + "body": { + "bytes": 3, + "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf" + } + } + }, "monitor": { "duration": { "us": 24627 @@ -28,4 +54,4 @@ }, "docId": "h5toHm0B0I9WX_CznN_V", "timestamp": "2019-09-11T03:40:34.371Z" -} \ No newline at end of file +} diff --git a/x-pack/test/functional/apps/dashboard/_async_dashboard.ts b/x-pack/test/functional/apps/dashboard/_async_dashboard.ts index cc30a7a7e640f..8851c83dea1ff 100644 --- a/x-pack/test/functional/apps/dashboard/_async_dashboard.ts +++ b/x-pack/test/functional/apps/dashboard/_async_dashboard.ts @@ -27,8 +27,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'timePicker', ]); - // Flakky: https://github.com/elastic/kibana/issues/65949 - describe.skip('sample data dashboard', function describeIndexTests() { + describe('sample data dashboard', function describeIndexTests() { before(async () => { await PageObjects.common.sleep(5000); await PageObjects.common.navigateToUrl('home', '/tutorial_directory/sampleData', { @@ -36,8 +35,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.home.addSampleDataSet('flights'); - const isInstalled = await PageObjects.home.isSampleDataSetInstalled('flights'); - expect(isInstalled).to.be(true); + await retry.tryForTime(10000, async () => { + const isInstalled = await PageObjects.home.isSampleDataSetInstalled('flights'); + expect(isInstalled).to.be(true); + }); + // add the range of the sample data so we can pick it in the quick pick list const SAMPLE_DATA_RANGE = `[ { diff --git a/x-pack/test/functional/apps/dashboard/drilldowns/index.ts b/x-pack/test/functional/apps/dashboard/drilldowns/index.ts index 4cdb33c06947f..ff604b18e1d51 100644 --- a/x-pack/test/functional/apps/dashboard/drilldowns/index.ts +++ b/x-pack/test/functional/apps/dashboard/drilldowns/index.ts @@ -24,6 +24,9 @@ export default function ({ loadTestFile, getService }: FtrProviderContext) { loadTestFile(require.resolve('./dashboard_drilldowns')); loadTestFile(require.resolve('./explore_data_panel_action')); - loadTestFile(require.resolve('./explore_data_chart_action')); + + // Disabled for now as it requires xpack.discoverEnhanced.actions.exploreDataInChart.enabled + // setting set in kibana.yml to work. Once that is enabled by default, we can re-enable this test suite. + // loadTestFile(require.resolve('./explore_data_chart_action')); }); } diff --git a/x-pack/test/functional/apps/dashboard_mode/dashboard_empty_screen.js b/x-pack/test/functional/apps/dashboard_mode/dashboard_empty_screen.js index 62e07a08d1762..bd35374643e9b 100644 --- a/x-pack/test/functional/apps/dashboard_mode/dashboard_empty_screen.js +++ b/x-pack/test/functional/apps/dashboard_mode/dashboard_empty_screen.js @@ -27,7 +27,7 @@ export default function ({ getPageObjects, getService }) { await PageObjects.dashboard.gotoDashboardLandingPage(); }); - async function createAndAddLens(title) { + async function createAndAddLens(title, saveAsNew = false, redirectToOrigin = true) { log.debug(`createAndAddLens(${title})`); const inViewMode = await PageObjects.dashboard.getIsInViewMode(); if (inViewMode) { @@ -52,7 +52,7 @@ export default function ({ getPageObjects, getService }) { operation: 'terms', field: 'ip', }); - await PageObjects.lens.save(title, false, true); + await PageObjects.lens.save(title, saveAsNew, redirectToOrigin); } it('adds Lens visualization to empty dashboard', async () => { @@ -100,6 +100,8 @@ export default function ({ getPageObjects, getService }) { }); it('loses originatingApp connection after save as when redirectToOrigin is false', async () => { + await PageObjects.dashboard.saveDashboard('empty dashboard test'); + await PageObjects.dashboard.switchToEditMode(); const newTitle = 'wowee, my title just got cooler again'; await PageObjects.dashboard.waitForRenderComplete(); await dashboardPanelActions.openContextMenu(); @@ -108,5 +110,17 @@ export default function ({ getPageObjects, getService }) { await PageObjects.lens.notLinkedToOriginatingApp(); await PageObjects.common.navigateToApp('dashboard'); }); + + it('loses originatingApp connection after first save when redirectToOrigin is false', async () => { + const title = 'non-dashboard Test Lens'; + await PageObjects.dashboard.loadSavedDashboard('empty dashboard test'); + await PageObjects.dashboard.switchToEditMode(); + await testSubjects.exists('dashboardAddNewPanelButton'); + await testSubjects.click('dashboardAddNewPanelButton'); + await dashboardVisualizations.ensureNewVisualizationDialogIsShowing(); + await createAndAddLens(title, false, false); + await PageObjects.lens.notLinkedToOriginatingApp(); + await PageObjects.common.navigateToApp('dashboard'); + }); }); } diff --git a/x-pack/test/functional/apps/lens/dashboard.ts b/x-pack/test/functional/apps/lens/dashboard.ts new file mode 100644 index 0000000000000..ccf2f88a9d0ed --- /dev/null +++ b/x-pack/test/functional/apps/lens/dashboard.ts @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const PageObjects = getPageObjects(['header', 'common', 'dashboard', 'timePicker', 'lens']); + + const find = getService('find'); + const dashboardAddPanel = getService('dashboardAddPanel'); + const elasticChart = getService('elasticChart'); + const browser = getService('browser'); + const retry = getService('retry'); + const testSubjects = getService('testSubjects'); + const filterBar = getService('filterBar'); + + async function clickInChart(x: number, y: number) { + const el = await elasticChart.getCanvas(); + await browser.getActions().move({ x, y, origin: el._webElement }).click().perform(); + } + + describe('lens dashboard tests', () => { + it('metric should be embeddable', async () => { + await PageObjects.common.navigateToApp('dashboard'); + await PageObjects.dashboard.clickNewDashboard(); + await dashboardAddPanel.clickOpenAddPanel(); + await dashboardAddPanel.filterEmbeddableNames('Artistpreviouslyknownaslens'); + await find.clickByButtonText('Artistpreviouslyknownaslens'); + await dashboardAddPanel.closeAddPanel(); + await PageObjects.lens.goToTimeRange(); + await PageObjects.lens.assertMetric('Maximum of bytes', '19,986'); + }); + + it('should be able to add filters/timerange by clicking in XYChart', async () => { + await PageObjects.common.navigateToApp('dashboard'); + await PageObjects.dashboard.clickNewDashboard(); + await dashboardAddPanel.clickOpenAddPanel(); + await dashboardAddPanel.filterEmbeddableNames('lnsXYvis'); + await find.clickByButtonText('lnsXYvis'); + await dashboardAddPanel.closeAddPanel(); + await PageObjects.lens.goToTimeRange(); + await clickInChart(5, 5); // hardcoded position of bar + + await retry.try(async () => { + await testSubjects.click('applyFiltersPopoverButton'); + await testSubjects.missingOrFail('applyFiltersPopoverButton'); + }); + + await PageObjects.lens.assertExactText( + '[data-test-subj="embeddablePanelHeading-lnsXYvis"]', + 'lnsXYvis' + ); + const time = await PageObjects.timePicker.getTimeConfig(); + expect(time.start).to.equal('Sep 21, 2015 @ 09:00:00.000'); + expect(time.end).to.equal('Sep 21, 2015 @ 12:00:00.000'); + const hasIpFilter = await filterBar.hasFilter('ip', '97.220.3.248'); + expect(hasIpFilter).to.be(true); + }); + }); +} diff --git a/x-pack/test/functional/apps/lens/index.ts b/x-pack/test/functional/apps/lens/index.ts index b17b7d856841c..f2dcf28c01743 100644 --- a/x-pack/test/functional/apps/lens/index.ts +++ b/x-pack/test/functional/apps/lens/index.ts @@ -28,6 +28,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { this.tags(['ciGroup4', 'skipFirefox']); loadTestFile(require.resolve('./smokescreen')); + loadTestFile(require.resolve('./dashboard')); loadTestFile(require.resolve('./persistent_context')); loadTestFile(require.resolve('./lens_reporting')); }); diff --git a/x-pack/test/functional/apps/lens/smokescreen.ts b/x-pack/test/functional/apps/lens/smokescreen.ts index 1e93636161067..77b9aa1e25edd 100644 --- a/x-pack/test/functional/apps/lens/smokescreen.ts +++ b/x-pack/test/functional/apps/lens/smokescreen.ts @@ -8,115 +8,20 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { - const PageObjects = getPageObjects([ - 'header', - 'common', - 'visualize', - 'dashboard', - 'header', - 'timePicker', - 'lens', - ]); + const PageObjects = getPageObjects(['visualize', 'lens']); const find = getService('find'); - const dashboardAddPanel = getService('dashboardAddPanel'); - const elasticChart = getService('elasticChart'); - const browser = getService('browser'); - const retry = getService('retry'); - const testSubjects = getService('testSubjects'); - const filterBar = getService('filterBar'); const listingTable = getService('listingTable'); - async function assertExpectedMetric(metricCount: string = '19,986') { - await PageObjects.lens.assertExactText( - '[data-test-subj="lns_metric_title"]', - 'Maximum of bytes' - ); - await PageObjects.lens.assertExactText('[data-test-subj="lns_metric_value"]', metricCount); - } - - async function assertExpectedTable() { - await PageObjects.lens.assertExactText( - '[data-test-subj="lnsDataTable"] thead .euiTableCellContent__text', - 'Maximum of bytes' - ); - await PageObjects.lens.assertExactText( - '[data-test-subj="lnsDataTable"] [data-test-subj="lnsDataTableCellValue"]', - '19,986' - ); - } - - async function assertExpectedChart() { - await PageObjects.lens.assertExactText( - '[data-test-subj="embeddablePanelHeading-lnsXYvis"]', - 'lnsXYvis' - ); - } - - async function assertExpectedTimerange() { - const time = await PageObjects.timePicker.getTimeConfig(); - expect(time.start).to.equal('Sep 21, 2015 @ 09:00:00.000'); - expect(time.end).to.equal('Sep 21, 2015 @ 12:00:00.000'); - } - - async function clickOnBarHistogram() { - const el = await elasticChart.getCanvas(); - await browser.getActions().move({ x: 5, y: 5, origin: el._webElement }).click().perform(); - } - describe('lens smokescreen tests', () => { it('should allow editing saved visualizations', async () => { await PageObjects.visualize.gotoVisualizationLandingPage(); await listingTable.searchForItemWithName('Artistpreviouslyknownaslens'); await PageObjects.lens.clickVisualizeListItemTitle('Artistpreviouslyknownaslens'); await PageObjects.lens.goToTimeRange(); - await assertExpectedMetric(); - }); - - it('metric should be embeddable in dashboards', async () => { - await PageObjects.common.navigateToApp('dashboard'); - await PageObjects.dashboard.clickNewDashboard(); - await dashboardAddPanel.clickOpenAddPanel(); - await dashboardAddPanel.filterEmbeddableNames('Artistpreviouslyknownaslens'); - await find.clickByButtonText('Artistpreviouslyknownaslens'); - await dashboardAddPanel.closeAddPanel(); - await PageObjects.lens.goToTimeRange(); - await assertExpectedMetric(); + await PageObjects.lens.assertMetric('Maximum of bytes', '19,986'); }); - it('click on the bar in XYChart adds proper filters/timerange in dashboard', async () => { - await PageObjects.common.navigateToApp('dashboard'); - await PageObjects.dashboard.clickNewDashboard(); - await dashboardAddPanel.clickOpenAddPanel(); - await dashboardAddPanel.filterEmbeddableNames('lnsXYvis'); - await find.clickByButtonText('lnsXYvis'); - await dashboardAddPanel.closeAddPanel(); - await PageObjects.lens.goToTimeRange(); - await clickOnBarHistogram(); - - await retry.try(async () => { - await testSubjects.click('applyFiltersPopoverButton'); - await testSubjects.missingOrFail('applyFiltersPopoverButton'); - }); - - await assertExpectedChart(); - await assertExpectedTimerange(); - const hasIpFilter = await filterBar.hasFilter('ip', '97.220.3.248'); - expect(hasIpFilter).to.be(true); - }); - - it('should allow seamless transition to and from table view', async () => { - await PageObjects.visualize.gotoVisualizationLandingPage(); - await listingTable.searchForItemWithName('Artistpreviouslyknownaslens'); - await PageObjects.lens.clickVisualizeListItemTitle('Artistpreviouslyknownaslens'); - await PageObjects.lens.goToTimeRange(); - await assertExpectedMetric(); - await PageObjects.lens.switchToVisualization('lnsDatatable'); - await assertExpectedTable(); - await PageObjects.lens.switchToVisualization('lnsMetric'); - await assertExpectedMetric(); - }); - - it('should allow creation of lens visualizations', async () => { + it('should allow creation of lens xy chart', async () => { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickVisType('lens'); await PageObjects.lens.goToTimeRange(); @@ -165,6 +70,19 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(await find.allByCssSelector('.echLegendItem')).to.have.length(3); }); + it('should allow seamless transition to and from table view', async () => { + await PageObjects.visualize.gotoVisualizationLandingPage(); + await listingTable.searchForItemWithName('Artistpreviouslyknownaslens'); + await PageObjects.lens.clickVisualizeListItemTitle('Artistpreviouslyknownaslens'); + await PageObjects.lens.goToTimeRange(); + await PageObjects.lens.assertMetric('Maximum of bytes', '19,986'); + await PageObjects.lens.switchToVisualization('lnsDatatable'); + expect(await PageObjects.lens.getDatatableHeaderText()).to.eql('Maximum of bytes'); + expect(await PageObjects.lens.getDatatableCellText(0, 0)).to.eql('19,986'); + await PageObjects.lens.switchToVisualization('lnsMetric'); + await PageObjects.lens.assertMetric('Maximum of bytes', '19,986'); + }); + it('should switch from a multi-layer stacked bar to a multi-layer line chart', async () => { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickVisType('lens'); @@ -190,5 +108,94 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(await PageObjects.lens.getLayerCount()).to.eql(2); }); + + it('should allow transition from line chart to donut chart and to bar chart', async () => { + await PageObjects.visualize.gotoVisualizationLandingPage(); + await listingTable.searchForItemWithName('lnsXYvis'); + await PageObjects.lens.clickVisualizeListItemTitle('lnsXYvis'); + await PageObjects.lens.goToTimeRange(); + expect(await PageObjects.lens.hasChartSwitchWarning('donut')).to.eql(true); + await PageObjects.lens.switchToVisualization('donut'); + + expect(await PageObjects.lens.getTitle()).to.eql('lnsXYvis'); + expect(await PageObjects.lens.getDimensionTriggerText('lnsPie_sliceByDimensionPanel')).to.eql( + 'Top values of ip' + ); + expect(await PageObjects.lens.getDimensionTriggerText('lnsPie_sizeByDimensionPanel')).to.eql( + 'Average of bytes' + ); + + expect(await PageObjects.lens.hasChartSwitchWarning('bar')).to.eql(false); + await PageObjects.lens.switchToVisualization('bar'); + expect(await PageObjects.lens.getTitle()).to.eql('lnsXYvis'); + expect(await PageObjects.lens.getDimensionTriggerText('lnsXY_xDimensionPanel')).to.eql( + 'Top values of ip' + ); + expect(await PageObjects.lens.getDimensionTriggerText('lnsXY_yDimensionPanel')).to.eql( + 'Average of bytes' + ); + }); + + it('should allow seamless transition from bar chart to line chart using layer chart switch', async () => { + await PageObjects.visualize.gotoVisualizationLandingPage(); + await listingTable.searchForItemWithName('lnsXYvis'); + await PageObjects.lens.clickVisualizeListItemTitle('lnsXYvis'); + await PageObjects.lens.goToTimeRange(); + await PageObjects.lens.switchLayerSeriesType('line'); + expect(await PageObjects.lens.getTitle()).to.eql('lnsXYvis'); + expect(await PageObjects.lens.getDimensionTriggerText('lnsXY_xDimensionPanel')).to.eql( + '@timestamp' + ); + expect(await PageObjects.lens.getDimensionTriggerText('lnsXY_yDimensionPanel')).to.eql( + 'Average of bytes' + ); + expect(await PageObjects.lens.getDimensionTriggerText('lnsXY_splitDimensionPanel')).to.eql( + 'Top values of ip' + ); + }); + + it('should allow seamless transition from pie chart to treemap chart', async () => { + await PageObjects.visualize.gotoVisualizationLandingPage(); + await listingTable.searchForItemWithName('lnsPieVis'); + await PageObjects.lens.clickVisualizeListItemTitle('lnsPieVis'); + await PageObjects.lens.goToTimeRange(); + expect(await PageObjects.lens.hasChartSwitchWarning('treemap')).to.eql(false); + await PageObjects.lens.switchToVisualization('treemap'); + expect( + await PageObjects.lens.getDimensionTriggerText('lnsPie_groupByDimensionPanel', 0) + ).to.eql('Top values of geo.dest'); + expect( + await PageObjects.lens.getDimensionTriggerText('lnsPie_groupByDimensionPanel', 1) + ).to.eql('Top values of geo.src'); + expect(await PageObjects.lens.getDimensionTriggerText('lnsPie_sizeByDimensionPanel')).to.eql( + 'Average of bytes' + ); + }); + + it('should allow creating a pie chart and switching to datatable', async () => { + await PageObjects.visualize.navigateToNewVisualization(); + await PageObjects.visualize.clickVisType('lens'); + await PageObjects.lens.goToTimeRange(); + await PageObjects.lens.switchToVisualization('pie'); + await PageObjects.lens.configureDimension({ + dimension: 'lnsPie_sliceByDimensionPanel > lns-empty-dimension', + operation: 'date_histogram', + field: '@timestamp', + }); + + await PageObjects.lens.configureDimension({ + dimension: 'lnsPie_sizeByDimensionPanel > lns-empty-dimension', + operation: 'avg', + field: 'bytes', + }); + + expect(await PageObjects.lens.hasChartSwitchWarning('lnsDatatable')).to.eql(false); + await PageObjects.lens.switchToVisualization('lnsDatatable'); + + expect(await PageObjects.lens.getDatatableHeaderText()).to.eql('@timestamp per 3 hours'); + expect(await PageObjects.lens.getDatatableCellText(0, 0)).to.eql('2015-09-20 00:00'); + expect(await PageObjects.lens.getDatatableHeaderText(1)).to.eql('Average of bytes'); + expect(await PageObjects.lens.getDatatableCellText(0, 1)).to.eql('6,011.351'); + }); }); } diff --git a/x-pack/test/functional/apps/ml/pages.ts b/x-pack/test/functional/apps/ml/pages.ts index e2c80c8dab558..3691e6b1afcdc 100644 --- a/x-pack/test/functional/apps/ml/pages.ts +++ b/x-pack/test/functional/apps/ml/pages.ts @@ -53,5 +53,17 @@ export default function ({ getService }: FtrProviderContext) { await ml.dataVisualizer.assertDataVisualizerImportDataCardExists(); await ml.dataVisualizer.assertDataVisualizerIndexDataCardExists(); }); + + it('should load the stack management with the ML menu item being present', async () => { + await ml.navigation.navigateToStackManagement(); + }); + + it('should load the jobs list page in stack management', async () => { + await ml.navigation.navigateToStackManagementJobsListPage(); + }); + + it('should load the analytics jobs list page in stack management', async () => { + await ml.navigation.navigateToStackManagementJobsListPageAnalyticsTab(); + }); }); } diff --git a/x-pack/test/functional/apps/uptime/certificates.ts b/x-pack/test/functional/apps/uptime/certificates.ts index 7e9a2cd85935e..a27317dccee8d 100644 --- a/x-pack/test/functional/apps/uptime/certificates.ts +++ b/x-pack/test/functional/apps/uptime/certificates.ts @@ -25,7 +25,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it('can navigate to cert page', async () => { - await uptimeService.cert.isUptimeDataMissing(); + await uptimeService.common.waitUntilDataIsLoaded(); await uptimeService.cert.hasViewCertButton(); await uptimeService.navigation.goToCertificates(); }); diff --git a/x-pack/test/functional/apps/uptime/index.ts b/x-pack/test/functional/apps/uptime/index.ts index 6b2b61cba2b64..261f685eeb9cc 100644 --- a/x-pack/test/functional/apps/uptime/index.ts +++ b/x-pack/test/functional/apps/uptime/index.ts @@ -56,6 +56,10 @@ export default ({ loadTestFile, getService }: FtrProviderContext) => { loadTestFile(require.resolve('./certificates')); }); + describe('with generated data but no data reset', () => { + loadTestFile(require.resolve('./ping_redirects')); + }); + describe('with real-world data', () => { before(async () => { await esArchiver.unload(ARCHIVE); diff --git a/x-pack/test/functional/apps/uptime/locations.ts b/x-pack/test/functional/apps/uptime/locations.ts index 8aefca6a70195..6bfa19c6ef578 100644 --- a/x-pack/test/functional/apps/uptime/locations.ts +++ b/x-pack/test/functional/apps/uptime/locations.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import moment from 'moment'; import { makeChecksWithStatus } from '../../../api_integration/apis/uptime/rest/helper/make_checks'; import { FtrProviderContext } from '../../ftr_provider_context'; @@ -40,8 +39,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }; describe('Observer location', () => { - const start = moment().subtract('15', 'm').toISOString(); - const end = moment().toISOString(); + const start = '~ 15 minutes ago'; + const end = 'now'; before(async () => { await addMonitorWithNoLocation(); diff --git a/x-pack/test/functional/apps/uptime/ping_redirects.ts b/x-pack/test/functional/apps/uptime/ping_redirects.ts new file mode 100644 index 0000000000000..b87e8c1748c82 --- /dev/null +++ b/x-pack/test/functional/apps/uptime/ping_redirects.ts @@ -0,0 +1,74 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { makeChecksWithStatus } from '../../../api_integration/apis/uptime/rest/helper/make_checks'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); + +export default ({ getPageObjects, getService }: FtrProviderContext) => { + const { uptime: uptimePage, header } = getPageObjects(['uptime', 'header']); + const uptime = getService('uptime'); + const esArchiver = getService('esArchiver'); + + const archive = 'uptime/blank'; + + const monitor = () => uptime.monitor; + + describe('Ping redirects', () => { + const start = '~ 15 minutes ago'; + const end = 'now'; + + const MONITOR_ID = 'redirect-testing-id'; + + before(async () => { + await esArchiver.loadIfNeeded(archive); + }); + + after('unload', async () => { + await esArchiver.unload(archive); + }); + + beforeEach(async () => { + await makeChecksWithStatus( + getService('legacyEs'), + MONITOR_ID, + 5, + 2, + 10000, + { + http: { + rtt: { total: { us: 157784 } }, + response: { + status_code: 200, + redirects: ['http://localhost:3000/first', 'https://www.washingtonpost.com/'], + body: { + bytes: 642102, + hash: '597a8cfb33ff8e09bff16283306553c3895282aaf5386e1843d466d44979e28a', + }, + }, + }, + }, + 'up' + ); + await delay(1000); + }); + + it('loads and goes to details page', async () => { + await uptime.navigation.goToUptime(); + await uptimePage.loadDataAndGoToMonitorPage(start, end, MONITOR_ID); + }); + + it('display redirect info in detail panel', async () => { + await header.waitUntilLoadingHasFinished(); + await monitor().hasRedirectInfo(); + }); + + it('displays redirects in ping list expand row', async () => { + await monitor().hasRedirectInfoInPingList(); + }); + }); +}; diff --git a/x-pack/test/functional/es_archives/fleet/agents/mappings.json b/x-pack/test/functional/es_archives/fleet/agents/mappings.json index 23b404a53703f..12d3be3e2a971 100644 --- a/x-pack/test/functional/es_archives/fleet/agents/mappings.json +++ b/x-pack/test/functional/es_archives/fleet/agents/mappings.json @@ -1870,9 +1870,9 @@ "config": { "type": "flattened" }, - "dataset": { + "data_stream": { "properties": { - "name": { + "dataset": { "type": "keyword" }, "type": { diff --git a/x-pack/test/functional/es_archives/lens/basic/data.json.gz b/x-pack/test/functional/es_archives/lens/basic/data.json.gz index 4ed7c29f7391e..ddf4a27289dff 100644 Binary files a/x-pack/test/functional/es_archives/lens/basic/data.json.gz and b/x-pack/test/functional/es_archives/lens/basic/data.json.gz differ diff --git a/x-pack/test/functional/es_archives/lists/mappings.json b/x-pack/test/functional/es_archives/lists/mappings.json index 3b4d915cc1ca5..ba4e1b276d45e 100644 --- a/x-pack/test/functional/es_archives/lists/mappings.json +++ b/x-pack/test/functional/es_archives/lists/mappings.json @@ -1310,9 +1310,9 @@ "config": { "type": "flattened" }, - "dataset": { + "data_stream": { "properties": { - "name": { + "dataset": { "type": "keyword" }, "type": { diff --git a/x-pack/test/functional/es_archives/reporting/canvas_disallowed_url/mappings.json b/x-pack/test/functional/es_archives/reporting/canvas_disallowed_url/mappings.json index 3519103d06814..2380154277e55 100644 --- a/x-pack/test/functional/es_archives/reporting/canvas_disallowed_url/mappings.json +++ b/x-pack/test/functional/es_archives/reporting/canvas_disallowed_url/mappings.json @@ -1246,9 +1246,9 @@ "config": { "type": "flattened" }, - "dataset": { + "data_stream": { "properties": { - "name": { + "dataset": { "type": "keyword" }, "type": { diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts index 79548db0e2630..bed0e3a159e23 100644 --- a/x-pack/test/functional/page_objects/lens_page.ts +++ b/x-pack/test/functional/page_objects/lens_page.ts @@ -176,9 +176,26 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont */ async hasChartSwitchWarning(subVisualizationId: string) { await this.openChartSwitchPopover(); - const element = await testSubjects.find(`lnsChartSwitchPopover_${subVisualizationId}`); - return await testSubjects.descendantExists('euiKeyPadMenuItem__betaBadgeWrapper', element); + return await find.descendantExistsByCssSelector( + '.euiKeyPadMenuItem__betaBadgeWrapper', + element + ); + }, + + /** + * Uses the Lens layer switcher to switch seriesType for xy charts. + * + * @param subVisualizationId - the ID of the sub-visualization to switch to, such as + * line, + */ + async switchLayerSeriesType(seriesType: string) { + await retry.try(async () => { + await testSubjects.click('lns_layer_settings'); + await testSubjects.exists(`lnsXY_seriesType-${seriesType}`); + }); + + return await testSubjects.click(`lnsXY_seriesType-${seriesType}`); }, /** @@ -205,5 +222,60 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont await PageObjects.header.waitUntilLoadingHasFinished(); await testSubjects.missingOrFail('lnsApp_saveAndReturnButton'); }, + /** + * Gets label of dimension trigger in dimension panel + * + * @param dimension - the selector of the dimension + */ + async getDimensionTriggerText(dimension: string, index = 0) { + const dimensionElements = await testSubjects.findAll(dimension); + const trigger = await testSubjects.findDescendant( + 'lns-dimensionTrigger', + dimensionElements[index] + ); + return await trigger.getVisibleText(); + }, + + /** + * Gets text of the specified datatable header cell + * + * @param index - index of th element in datatable + */ + async getDatatableHeaderText(index = 0) { + return find + .byCssSelector( + `[data-test-subj="lnsDataTable"] thead th:nth-child(${ + index + 1 + }) .euiTableCellContent__text` + ) + .then((el) => el.getVisibleText()); + }, + + /** + * Gets text of the specified datatable cell + * + * @param rowIndex - index of row of the cell + * @param colIndex - index of column of the cell + */ + async getDatatableCellText(rowIndex = 0, colIndex = 0) { + return find + .byCssSelector( + `[data-test-subj="lnsDataTable"] tr:nth-child(${rowIndex + 1}) td:nth-child(${ + colIndex + 1 + })` + ) + .then((el) => el.getVisibleText()); + }, + + /** + * Asserts that metric has expected title and count + * + * @param title - expected title + * @param count - expected count of metric + */ + async assertMetric(title: string, count: string) { + await this.assertExactText('[data-test-subj="lns_metric_title"]', title); + await this.assertExactText('[data-test-subj="lns_metric_value"]', count); + }, }); } diff --git a/x-pack/test/functional/page_objects/uptime_page.ts b/x-pack/test/functional/page_objects/uptime_page.ts index 074a2d598be8a..8102d8b95680e 100644 --- a/x-pack/test/functional/page_objects/uptime_page.ts +++ b/x-pack/test/functional/page_objects/uptime_page.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../ftr_provider_context'; export function UptimePageProvider({ getPageObjects, getService }: FtrProviderContext) { - const pageObjects = getPageObjects(['common', 'timePicker']); + const pageObjects = getPageObjects(['common', 'timePicker', 'header']); const { common: commonService, monitor, navigation } = getService('uptime'); const retry = getService('retry'); @@ -42,6 +42,7 @@ export function UptimePageProvider({ getPageObjects, getService }: FtrProviderCo } public async loadDataAndGoToMonitorPage(dateStart: string, dateEnd: string, monitorId: string) { + await pageObjects.header.waitUntilLoadingHasFinished(); await this.setDateRange(dateStart, dateEnd); await navigation.goToMonitor(monitorId); } diff --git a/x-pack/test/functional/services/ml/data_frame_analytics_creation.ts b/x-pack/test/functional/services/ml/data_frame_analytics_creation.ts index a49febfe68f61..d8df2fb869ed7 100644 --- a/x-pack/test/functional/services/ml/data_frame_analytics_creation.ts +++ b/x-pack/test/functional/services/ml/data_frame_analytics_creation.ts @@ -46,14 +46,16 @@ export function MachineLearningDataFrameAnalyticsCreationProvider( }, async assertJobTypeSelection(expectedSelection: string) { - const actualSelection = await testSubjects.getAttribute( - 'mlAnalyticsCreateJobWizardJobTypeSelect', - 'value' - ); - expect(actualSelection).to.eql( - expectedSelection, - `Job type selection should be '${expectedSelection}' (got '${actualSelection}')` - ); + await retry.tryForTime(5000, async () => { + const actualSelection = await testSubjects.getAttribute( + 'mlAnalyticsCreateJobWizardJobTypeSelect', + 'value' + ); + expect(actualSelection).to.eql( + expectedSelection, + `Job type selection should be '${expectedSelection}' (got '${actualSelection}')` + ); + }); }, async selectJobType(jobType: string) { diff --git a/x-pack/test/functional/services/ml/navigation.ts b/x-pack/test/functional/services/ml/navigation.ts index 9b67a369f055f..f52197d4b2256 100644 --- a/x-pack/test/functional/services/ml/navigation.ts +++ b/x-pack/test/functional/services/ml/navigation.ts @@ -23,6 +23,13 @@ export function MachineLearningNavigationProvider({ }); }, + async navigateToStackManagement() { + await retry.tryForTime(60 * 1000, async () => { + await PageObjects.common.navigateToApp('management'); + await testSubjects.existOrFail('jobsListLink', { timeout: 2000 }); + }); + }, + async assertTabsExist(tabTypeSubject: string, areaSubjects: string[]) { await retry.tryForTime(10000, async () => { const allTabs = await testSubjects.findAll(`~${tabTypeSubject}`, 3); @@ -76,5 +83,25 @@ export function MachineLearningNavigationProvider({ async navigateToSettings() { await this.navigateToArea('~mlMainTab & ~settings', 'mlPageSettings'); }, + + async navigateToStackManagementJobsListPage() { + // clicks the jobsListLink and loads the jobs list page + await testSubjects.click('jobsListLink'); + await retry.tryForTime(60 * 1000, async () => { + // verify that the overall page is present + await testSubjects.existOrFail('mlPageStackManagementJobsList'); + // verify that the default tab with the anomaly detection jobs list got loaded + await testSubjects.existOrFail('ml-jobs-list'); + }); + }, + + async navigateToStackManagementJobsListPageAnalyticsTab() { + // clicks the `Analytics` tab and loads the analytics list page + await testSubjects.click('mlStackManagementJobsListAnalyticsTab'); + await retry.tryForTime(60 * 1000, async () => { + // verify that the empty prompt for analytics jobs list got loaded + await testSubjects.existOrFail('mlNoDataFrameAnalyticsFound'); + }); + }, }; } diff --git a/x-pack/test/functional/services/uptime/certificates.ts b/x-pack/test/functional/services/uptime/certificates.ts index 06de9be5af7e9..ab43604786282 100644 --- a/x-pack/test/functional/services/uptime/certificates.ts +++ b/x-pack/test/functional/services/uptime/certificates.ts @@ -24,14 +24,6 @@ export function UptimeCertProvider({ getService, getPageObjects }: FtrProviderCo }; return { - async isUptimeDataMissing() { - return retry.tryForTime(60 * 1000, async () => { - if (await testSubjects.exists('data-missing', { timeout: 0 })) { - await refreshApp(); - } - await testSubjects.missingOrFail('data-missing'); - }); - }, async hasViewCertButton() { return retry.tryForTime(15000, async () => { await testSubjects.existOrFail('uptimeCertificatesLink'); diff --git a/x-pack/test/functional/services/uptime/common.ts b/x-pack/test/functional/services/uptime/common.ts index 5f544b5e46010..13c9ead89d09d 100644 --- a/x-pack/test/functional/services/uptime/common.ts +++ b/x-pack/test/functional/services/uptime/common.ts @@ -91,5 +91,13 @@ export function UptimeCommonProvider({ getService }: FtrProviderContext) { 5000 ); }, + async waitUntilDataIsLoaded() { + return retry.tryForTime(60 * 1000, async () => { + if (await testSubjects.exists('data-missing')) { + await testSubjects.click('superDatePickerApplyTimeButton'); + } + await testSubjects.missingOrFail('data-missing'); + }); + }, }; } diff --git a/x-pack/test/functional/services/uptime/monitor.ts b/x-pack/test/functional/services/uptime/monitor.ts index 593950fbb7619..c45454e731696 100644 --- a/x-pack/test/functional/services/uptime/monitor.ts +++ b/x-pack/test/functional/services/uptime/monitor.ts @@ -7,11 +7,13 @@ import expect from '@kbn/expect/expect.js'; import { FtrProviderContext } from '../../ftr_provider_context'; -export function UptimeMonitorProvider({ getService }: FtrProviderContext) { +export function UptimeMonitorProvider({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const retry = getService('retry'); const find = getService('find'); + const PageObjects = getPageObjects(['header']); + return { async locationMissingExists() { return await testSubjects.existOrFail('xpack.uptime.locationMap.locationMissing', { @@ -56,5 +58,29 @@ export function UptimeMonitorProvider({ getService }: FtrProviderContext) { async toggleToMapView() { await testSubjects.click('uptimeMonitorToggleMapBtn'); }, + async hasRedirectInfo() { + return retry.tryForTime(30000, async () => { + await testSubjects.existOrFail('uptimeMonitorRedirectInfo'); + }); + }, + async expandPingRow() { + return retry.tryForTime( + 60 * 3000, + async () => { + await testSubjects.existOrFail('uptimePingListExpandBtn', { timeout: 5000 }); + await testSubjects.click('uptimePingListExpandBtn'); + }, + async () => { + await testSubjects.click('superDatePickerApplyTimeButton'); + await PageObjects.header.waitUntilLoadingHasFinished(); + } + ); + }, + async hasRedirectInfoInPingList() { + await this.expandPingRow(); + return retry.tryForTime(60 * 1000, async () => { + await testSubjects.existOrFail('uptimeMonitorPingListRedirectInfo'); + }); + }, }; } diff --git a/x-pack/test/functional_enterprise_search/apps/enterprise_search/with_host_configured/app_search/engines.ts b/x-pack/test/functional_enterprise_search/apps/enterprise_search/with_host_configured/app_search/engines.ts index 1742ed443984b..85ae4d77b828f 100644 --- a/x-pack/test/functional_enterprise_search/apps/enterprise_search/with_host_configured/app_search/engines.ts +++ b/x-pack/test/functional_enterprise_search/apps/enterprise_search/with_host_configured/app_search/engines.ts @@ -52,6 +52,9 @@ export default function enterpriseSearchSetupEnginesTests({ await retry.try(async function () { const currentUrl = await browser.getCurrentUrl(); expect(currentUrl).to.contain('/app_search'); + + const documentTitle = await browser.getTitle(); + expect(documentTitle).to.contain('App Search - Elastic'); }); }); diff --git a/x-pack/test/functional_enterprise_search/apps/enterprise_search/without_host_configured/app_search/setup_guide.ts b/x-pack/test/functional_enterprise_search/apps/enterprise_search/without_host_configured/app_search/setup_guide.ts index 76a47cc4a7e10..86c35db504eab 100644 --- a/x-pack/test/functional_enterprise_search/apps/enterprise_search/without_host_configured/app_search/setup_guide.ts +++ b/x-pack/test/functional_enterprise_search/apps/enterprise_search/without_host_configured/app_search/setup_guide.ts @@ -29,6 +29,9 @@ export default function enterpriseSearchSetupGuideTests({ await retry.try(async function () { const currentUrl = await browser.getCurrentUrl(); expect(currentUrl).to.contain('/app_search/setup_guide'); + + const documentTitle = await browser.getTitle(); + expect(documentTitle).to.contain('Setup Guide - App Search - Elastic'); }); }); }); diff --git a/x-pack/test/functional_enterprise_search/apps/enterprise_search/without_host_configured/workplace_search/setup_guide.ts b/x-pack/test/functional_enterprise_search/apps/enterprise_search/without_host_configured/workplace_search/setup_guide.ts index 20145306b21c8..81d600952cd43 100644 --- a/x-pack/test/functional_enterprise_search/apps/enterprise_search/without_host_configured/workplace_search/setup_guide.ts +++ b/x-pack/test/functional_enterprise_search/apps/enterprise_search/without_host_configured/workplace_search/setup_guide.ts @@ -29,6 +29,9 @@ export default function enterpriseSearchSetupGuideTests({ await retry.try(async function () { const currentUrl = await browser.getCurrentUrl(); expect(currentUrl).to.contain('/workplace_search/setup_guide'); + + const documentTitle = await browser.getTitle(); + expect(documentTitle).to.contain('Setup Guide - Workplace Search - Elastic'); }); }); }); diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/data_stream.ts b/x-pack/test/ingest_manager_api_integration/apis/epm/data_stream.ts new file mode 100644 index 0000000000000..68a4812d4af40 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/data_stream.ts @@ -0,0 +1,130 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; +import { skipIfNoDockerRegistry } from '../../helpers'; + +export default function (providerContext: FtrProviderContext) { + const { getService } = providerContext; + const supertest = getService('supertest'); + const es = getService('es'); + const pkgName = 'datastreams'; + const pkgVersion = '0.1.0'; + const pkgUpdateVersion = '0.2.0'; + const pkgKey = `${pkgName}-${pkgVersion}`; + const pkgUpdateKey = `${pkgName}-${pkgUpdateVersion}`; + const logsTemplateName = `logs-${pkgName}.test_logs`; + const metricsTemplateName = `metrics-${pkgName}.test_metrics`; + + const uninstallPackage = async (pkg: string) => { + await supertest.delete(`/api/ingest_manager/epm/packages/${pkg}`).set('kbn-xsrf', 'xxxx'); + }; + const installPackage = async (pkg: string) => { + await supertest + .post(`/api/ingest_manager/epm/packages/${pkg}`) + .set('kbn-xsrf', 'xxxx') + .send({ force: true }); + }; + + describe('datastreams', async () => { + skipIfNoDockerRegistry(providerContext); + before(async () => { + await installPackage(pkgKey); + await es.transport.request({ + method: 'POST', + path: `/${logsTemplateName}-default/_doc`, + body: { + '@timestamp': '2015-01-01', + logs_test_name: 'test', + data_stream: { + dataset: `${pkgName}.test_logs`, + namespace: 'default', + type: 'logs', + }, + }, + }); + await es.transport.request({ + method: 'POST', + path: `/${metricsTemplateName}-default/_doc`, + body: { + '@timestamp': '2015-01-01', + logs_test_name: 'test', + data_stream: { + dataset: `${pkgName}.test_metrics`, + namespace: 'default', + type: 'metrics', + }, + }, + }); + }); + after(async () => { + await uninstallPackage(pkgUpdateKey); + await es.transport.request({ + method: 'DELETE', + path: `/_data_stream/${logsTemplateName}-default`, + }); + await es.transport.request({ + method: 'DELETE', + path: `/_data_stream/${metricsTemplateName}-default`, + }); + }); + describe('get datastreams after data sent', async () => { + skipIfNoDockerRegistry(providerContext); + let resLogsDatastream: any; + let resMetricsDatastream: any; + before(async () => { + resLogsDatastream = await es.transport.request({ + method: 'GET', + path: `/_data_stream/${logsTemplateName}-default`, + }); + resMetricsDatastream = await es.transport.request({ + method: 'GET', + path: `/_data_stream/${metricsTemplateName}-default`, + }); + }); + it('should list the logs datastream', async function () { + expect(resLogsDatastream.body.data_streams.length).equal(1); + expect(resLogsDatastream.body.data_streams[0].indices.length).equal(1); + expect(resLogsDatastream.body.data_streams[0].indices[0].index_name).equal( + `.ds-${logsTemplateName}-default-000001` + ); + }); + it('should list the metrics datastream', async function () { + expect(resMetricsDatastream.body.data_streams.length).equal(1); + expect(resMetricsDatastream.body.data_streams[0].indices.length).equal(1); + expect(resMetricsDatastream.body.data_streams[0].indices[0].index_name).equal( + `.ds-${metricsTemplateName}-default-000001` + ); + }); + }); + describe('rollover datastream when mappings are not compatible', async () => { + skipIfNoDockerRegistry(providerContext); + let resLogsDatastream: any; + let resMetricsDatastream: any; + before(async () => { + await installPackage(pkgUpdateKey); + resLogsDatastream = await es.transport.request({ + method: 'GET', + path: `/_data_stream/${logsTemplateName}-default`, + }); + resMetricsDatastream = await es.transport.request({ + method: 'GET', + path: `/_data_stream/${metricsTemplateName}-default`, + }); + }); + it('should have rolled over logs datastream', async function () { + expect(resLogsDatastream.body.data_streams[0].indices.length).equal(2); + expect(resLogsDatastream.body.data_streams[0].indices[1].index_name).equal( + `.ds-${logsTemplateName}-default-000002` + ); + }); + it('should have not rolled over metrics datastream', async function () { + expect(resMetricsDatastream.body.data_streams[0].indices.length).equal(1); + }); + }); + }); +} diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/get.ts b/x-pack/test/ingest_manager_api_integration/apis/epm/get.ts new file mode 100644 index 0000000000000..382bd6beb2e2f --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/get.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; +import { warnAndSkipTest } from '../../helpers'; + +export default function ({ getService }: FtrProviderContext) { + const log = getService('log'); + const supertest = getService('supertest'); + const dockerServers = getService('dockerServers'); + const server = dockerServers.get('registry'); + + describe('EPM - get', () => { + it('returns a 500 for a package key without a proper name', async function () { + if (server.enabled) { + await supertest.get('/api/ingest_manager/epm/packages/-0.1.0').expect(500); + } else { + warnAndSkipTest(this, log); + } + }); + + it('returns a 500 for a package key without a proper semver version', async function () { + if (server.enabled) { + await supertest.get('/api/ingest_manager/epm/packages/endpoint-0.1.0.1.2.3').expect(500); + } else { + warnAndSkipTest(this, log); + } + }); + }); +} diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/index.js b/x-pack/test/ingest_manager_api_integration/apis/epm/index.js index 1582f72dd1cd8..0a259cb96bf59 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/epm/index.js +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/index.js @@ -7,11 +7,15 @@ export default function loadTests({ loadTestFile }) { describe('EPM Endpoints', () => { loadTestFile(require.resolve('./list')); + loadTestFile(require.resolve('./get')); loadTestFile(require.resolve('./file')); //loadTestFile(require.resolve('./template')); loadTestFile(require.resolve('./ilm')); loadTestFile(require.resolve('./install_overrides')); + loadTestFile(require.resolve('./install_prerelease')); loadTestFile(require.resolve('./install_remove_assets')); loadTestFile(require.resolve('./install_update')); + loadTestFile(require.resolve('./update_assets')); + loadTestFile(require.resolve('./data_stream')); }); } diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/install_overrides.ts b/x-pack/test/ingest_manager_api_integration/apis/epm/install_overrides.ts index f73ba56c172c4..c75c51f6a5000 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/epm/install_overrides.ts +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/install_overrides.ts @@ -14,13 +14,13 @@ export default function ({ getService }: FtrProviderContext) { const dockerServers = getService('dockerServers'); const log = getService('log'); + const mappingsPackage = 'overrides-0.1.0'; + const server = dockerServers.get('registry'); + const deletePackage = async (pkgkey: string) => { await supertest.delete(`/api/ingest_manager/epm/packages/${pkgkey}`).set('kbn-xsrf', 'xxxx'); }; - const mappingsPackage = 'overrides-0.1.0'; - const server = dockerServers.get('registry'); - describe('installs packages that include settings and mappings overrides', async () => { after(async () => { if (server.enabled) { diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/install_prerelease.ts b/x-pack/test/ingest_manager_api_integration/apis/epm/install_prerelease.ts new file mode 100644 index 0000000000000..a641a105c66e0 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/install_prerelease.ts @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; +import { warnAndSkipTest } from '../../helpers'; + +export default function ({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const dockerServers = getService('dockerServers'); + const log = getService('log'); + + const testPackage = 'prerelease-0.1.0-dev.0+abc'; + const server = dockerServers.get('registry'); + + const deletePackage = async (pkgkey: string) => { + await supertest.delete(`/api/ingest_manager/epm/packages/${pkgkey}`).set('kbn-xsrf', 'xxxx'); + }; + + describe('installs package that has a prerelease version', async () => { + after(async () => { + if (server.enabled) { + // remove the package just in case it being installed will affect other tests + await deletePackage(testPackage); + } + }); + + it('should install the package correctly', async function () { + if (server.enabled) { + await supertest + .post(`/api/ingest_manager/epm/packages/${testPackage}`) + .set('kbn-xsrf', 'xxxx') + .expect(200); + } else { + warnAndSkipTest(this, log); + } + }); + }); +} diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/install_remove_assets.ts b/x-pack/test/ingest_manager_api_integration/apis/epm/install_remove_assets.ts index 35058de0684b2..7fb8b0a2b1708 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/epm/install_remove_assets.ts +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/install_remove_assets.ts @@ -23,7 +23,10 @@ export default function (providerContext: FtrProviderContext) { await supertest.delete(`/api/ingest_manager/epm/packages/${pkg}`).set('kbn-xsrf', 'xxxx'); }; const installPackage = async (pkg: string) => { - await supertest.post(`/api/ingest_manager/epm/packages/${pkg}`).set('kbn-xsrf', 'xxxx'); + await supertest + .post(`/api/ingest_manager/epm/packages/${pkg}`) + .set('kbn-xsrf', 'xxxx') + .send({ force: true }); }; describe('installs and uninstalls all assets', async () => { @@ -82,11 +85,6 @@ export default function (providerContext: FtrProviderContext) { id: 'metrics-*', }); expect(resIndexPatternMetrics.id).equal('metrics-*'); - const resIndexPatternEvents = await kibanaServer.savedObjects.get({ - type: 'index-pattern', - id: 'events-*', - }); - expect(resIndexPatternEvents.id).equal('events-*'); const resDashboard = await kibanaServer.savedObjects.get({ type: 'dashboard', id: 'sample_dashboard', @@ -108,6 +106,18 @@ export default function (providerContext: FtrProviderContext) { }); expect(resSearch.id).equal('sample_search'); }); + it('should have installed placeholder indices', async function () { + const resLogsIndexPatternPlaceholder = await es.transport.request({ + method: 'GET', + path: `/logs-index_pattern_placeholder`, + }); + expect(resLogsIndexPatternPlaceholder.statusCode).equal(200); + const resMetricsIndexPatternPlaceholder = await es.transport.request({ + method: 'GET', + path: `/metrics-index_pattern_placeholder`, + }); + expect(resMetricsIndexPatternPlaceholder.statusCode).equal(200); + }); it('should have created the correct saved object', async function () { const res = await kibanaServer.savedObjects.get({ type: 'epm-packages', diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/list.ts b/x-pack/test/ingest_manager_api_integration/apis/epm/list.ts index 0b6a37d77387e..bfe1954e46c9f 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/epm/list.ts +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/list.ts @@ -29,7 +29,7 @@ export default function ({ getService }: FtrProviderContext) { return response.body; }; const listResponse = await fetchPackageList(); - expect(listResponse.response.length).to.be(8); + expect(listResponse.response.length).not.to.be(0); } else { warnAndSkipTest(this, log); } diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/update_assets.ts b/x-pack/test/ingest_manager_api_integration/apis/epm/update_assets.ts new file mode 100644 index 0000000000000..59ad7a9744ae1 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/update_assets.ts @@ -0,0 +1,299 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; +import { skipIfNoDockerRegistry } from '../../helpers'; + +export default function (providerContext: FtrProviderContext) { + const { getService } = providerContext; + const kibanaServer = getService('kibanaServer'); + const supertest = getService('supertest'); + const es = getService('es'); + const pkgName = 'all_assets'; + const pkgVersion = '0.1.0'; + const pkgUpdateVersion = '0.2.0'; + const pkgKey = `${pkgName}-${pkgVersion}`; + const pkgUpdateKey = `${pkgName}-${pkgUpdateVersion}`; + const logsTemplateName = `logs-${pkgName}.test_logs`; + const logsTemplateName2 = `logs-${pkgName}.test_logs2`; + const metricsTemplateName = `metrics-${pkgName}.test_metrics`; + + const uninstallPackage = async (pkg: string) => { + await supertest.delete(`/api/ingest_manager/epm/packages/${pkg}`).set('kbn-xsrf', 'xxxx'); + }; + const installPackage = async (pkg: string) => { + await supertest + .post(`/api/ingest_manager/epm/packages/${pkg}`) + .set('kbn-xsrf', 'xxxx') + .send({ force: true }); + }; + + describe('updates all assets when updating a package to a different version', async () => { + skipIfNoDockerRegistry(providerContext); + before(async () => { + await installPackage(pkgKey); + await installPackage(pkgUpdateKey); + }); + after(async () => { + await uninstallPackage(pkgUpdateKey); + }); + it('should have updated the ILM policy', async function () { + const resPolicy = await es.transport.request({ + method: 'GET', + path: `/_ilm/policy/all_assets`, + }); + expect(resPolicy.body.all_assets.policy).eql({ + phases: { + hot: { + min_age: '1ms', + actions: { + rollover: { + max_size: '50gb', + max_age: '31d', + }, + }, + }, + }, + }); + }); + it('should have updated the index templates', async function () { + const resLogsTemplate = await es.transport.request({ + method: 'GET', + path: `/_index_template/${logsTemplateName}`, + }); + expect(resLogsTemplate.statusCode).equal(200); + expect( + resLogsTemplate.body.index_templates[0].index_template.template.mappings.properties + ).eql({ + '@timestamp': { + type: 'date', + }, + logs_test_name: { + type: 'text', + }, + new_field_name: { + ignore_above: 1024, + type: 'keyword', + }, + data_stream: { + properties: { + dataset: { + type: 'constant_keyword', + }, + namespace: { + type: 'constant_keyword', + }, + type: { + type: 'constant_keyword', + }, + }, + }, + }); + const resMetricsTemplate = await es.transport.request({ + method: 'GET', + path: `/_index_template/${metricsTemplateName}`, + }); + expect(resMetricsTemplate.statusCode).equal(200); + expect( + resMetricsTemplate.body.index_templates[0].index_template.template.mappings.properties + ).eql({ + '@timestamp': { + type: 'date', + }, + metrics_test_name2: { + ignore_above: 1024, + type: 'keyword', + }, + data_stream: { + properties: { + dataset: { + type: 'constant_keyword', + }, + namespace: { + type: 'constant_keyword', + }, + type: { + type: 'constant_keyword', + }, + }, + }, + }); + }); + it('should have installed the new index template', async function () { + const resLogsTemplate = await es.transport.request({ + method: 'GET', + path: `/_index_template/${logsTemplateName2}`, + }); + expect(resLogsTemplate.statusCode).equal(200); + expect( + resLogsTemplate.body.index_templates[0].index_template.template.mappings.properties + ).eql({ + '@timestamp': { + type: 'date', + }, + test_logs2: { + ignore_above: 1024, + type: 'keyword', + }, + data_stream: { + properties: { + dataset: { + type: 'constant_keyword', + }, + namespace: { + type: 'constant_keyword', + }, + type: { + type: 'constant_keyword', + }, + }, + }, + }); + }); + it('should have installed the new versionized pipeline', async function () { + const res = await es.transport.request({ + method: 'GET', + path: `/_ingest/pipeline/${logsTemplateName}-${pkgUpdateVersion}`, + }); + expect(res.statusCode).equal(200); + }); + it('should have removed the old versionized pipelines', async function () { + let res; + try { + res = await es.transport.request({ + method: 'GET', + path: `/_ingest/pipeline/${logsTemplateName}-${pkgVersion}`, + }); + } catch (err) { + res = err; + } + expect(res.statusCode).equal(404); + }); + it('should have updated the template components', async function () { + const res = await es.transport.request({ + method: 'GET', + path: `/_component_template/${logsTemplateName}-mappings`, + }); + expect(res.statusCode).equal(200); + expect(res.body.component_templates[0].component_template.template.mappings).eql({ + dynamic: true, + properties: { '@timestamp': { type: 'date' } }, + }); + const resSettings = await es.transport.request({ + method: 'GET', + path: `/_component_template/${logsTemplateName}-settings`, + }); + expect(res.statusCode).equal(200); + expect(resSettings.body.component_templates[0].component_template.template.settings).eql({ + index: { lifecycle: { name: 'reference2' } }, + }); + }); + it('should have updated the index patterns', async function () { + const resIndexPatternLogs = await kibanaServer.savedObjects.get({ + type: 'index-pattern', + id: 'logs-*', + }); + const fields = JSON.parse(resIndexPatternLogs.attributes.fields); + const updated = fields.filter((field: { name: string }) => field.name === 'new_field_name'); + expect(!!updated.length).equal(true); + const resIndexPatternMetrics = await kibanaServer.savedObjects.get({ + type: 'index-pattern', + id: 'metrics-*', + }); + const fieldsMetrics = JSON.parse(resIndexPatternMetrics.attributes.fields); + const updatedMetrics = fieldsMetrics.filter( + (field: { name: string }) => field.name === 'metrics_test_name2' + ); + expect(!!updatedMetrics.length).equal(true); + }); + it('should have updated the kibana assets', async function () { + const resDashboard = await kibanaServer.savedObjects.get({ + type: 'dashboard', + id: 'sample_dashboard', + }); + expect(resDashboard.id).equal('sample_dashboard'); + let resDashboard2; + try { + resDashboard2 = await kibanaServer.savedObjects.get({ + type: 'dashboard', + id: 'sample_dashboard2', + }); + } catch (err) { + resDashboard2 = err; + } + expect(resDashboard2.response.data.statusCode).equal(404); + const resVis = await kibanaServer.savedObjects.get({ + type: 'visualization', + id: 'sample_visualization', + }); + expect(resVis.attributes.description).equal('sample visualization 0.2.0'); + let resSearch; + try { + resSearch = await kibanaServer.savedObjects.get({ + type: 'search', + id: 'sample_search', + }); + } catch (err) { + resSearch = err; + } + expect(resSearch.response.data.statusCode).equal(404); + const resSearch2 = await kibanaServer.savedObjects.get({ + type: 'search', + id: 'sample_search2', + }); + expect(resSearch2.id).equal('sample_search2'); + }); + it('should have updated the saved object', async function () { + const res = await kibanaServer.savedObjects.get({ + type: 'epm-packages', + id: 'all_assets', + }); + expect(res.attributes).eql({ + installed_kibana: [ + { + id: 'sample_dashboard', + type: 'dashboard', + }, + { + id: 'sample_search2', + type: 'search', + }, + { + id: 'sample_visualization', + type: 'visualization', + }, + ], + installed_es: [ + { + id: 'logs-all_assets.test_logs-0.2.0', + type: 'ingest_pipeline', + }, + { + id: 'logs-all_assets.test_logs', + type: 'index_template', + }, + { + id: 'logs-all_assets.test_logs2', + type: 'index_template', + }, + { + id: 'metrics-all_assets.test_metrics', + type: 'index_template', + }, + ], + es_index_patterns: { + test_logs: 'logs-all_assets.test_logs-*', + test_metrics: 'metrics-all_assets.test_metrics-*', + }, + name: 'all_assets', + version: '0.2.0', + internal: false, + removable: true, + }); + }); + }); +} diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/dataset/test_logs/fields/ecs.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/dataset/test_logs/fields/ecs.yml new file mode 100644 index 0000000000000..3d88fe5dfefb6 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/dataset/test_logs/fields/ecs.yml @@ -0,0 +1,3 @@ +- name: logs_test_name + title: logs_test_title + type: keyword \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/dataset/test_metrics/fields/ecs.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/dataset/test_metrics/fields/ecs.yml new file mode 100644 index 0000000000000..a30e3c7a87856 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/dataset/test_metrics/fields/ecs.yml @@ -0,0 +1,3 @@ +- name: metrics_test_name + title: metrics_test_title + type: keyword \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/kibana/visualization/sample_visualization.json b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/kibana/visualization/sample_visualization.json index e814b83bbf324..917479fd7d120 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/kibana/visualization/sample_visualization.json +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/kibana/visualization/sample_visualization.json @@ -1,6 +1,6 @@ { "attributes": { - "description": "sample visualization", + "description": "sample visualization update", "title": "sample vis title", "uiStateJSON": "{}", "version": 1, diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs/elasticsearch/ilm_policy/all_assets.json b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs/elasticsearch/ilm_policy/all_assets.json new file mode 100644 index 0000000000000..d8bab8a75f680 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs/elasticsearch/ilm_policy/all_assets.json @@ -0,0 +1,15 @@ +{ + "policy": { + "phases": { + "hot": { + "min_age": "1ms", + "actions": { + "rollover": { + "max_size": "50gb", + "max_age": "31d" + } + } + } + } + } +} \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs/elasticsearch/ingest_pipeline/default.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs/elasticsearch/ingest_pipeline/default.yml new file mode 100644 index 0000000000000..580db049d0d5d --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs/elasticsearch/ingest_pipeline/default.yml @@ -0,0 +1,7 @@ +--- +description: Pipeline for parsing test logs + plugins. +processors: +- set: + field: error.message + value: '{{ _ingest.on_failure_message }}' \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs/fields/ecs.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs/fields/ecs.yml new file mode 100644 index 0000000000000..7df52cc11fd20 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs/fields/ecs.yml @@ -0,0 +1,6 @@ +- name: logs_test_name + title: logs_test_title + type: text +- name: new_field_name + title: new_field_title + type: keyword diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs/fields/fields.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs/fields/fields.yml new file mode 100644 index 0000000000000..6e003ed0ad147 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs/fields/fields.yml @@ -0,0 +1,16 @@ +- name: data_stream.type + type: constant_keyword + description: > + Data stream type. +- name: data_stream.dataset + type: constant_keyword + description: > + Data stream dataset. +- name: data_stream.namespace + type: constant_keyword + description: > + Data stream namespace. +- name: '@timestamp' + type: date + description: > + Event timestamp. diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs/manifest.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs/manifest.yml new file mode 100644 index 0000000000000..8a53f9e26e827 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs/manifest.yml @@ -0,0 +1,9 @@ +title: Test Dataset + +type: logs + +elasticsearch: + index_template.mappings: + dynamic: true + index_template.settings: + index.lifecycle.name: reference2 \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs2/fields/ecs.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs2/fields/ecs.yml new file mode 100644 index 0000000000000..c5819deb1ee37 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs2/fields/ecs.yml @@ -0,0 +1,3 @@ +- name: test_logs2 + title: test_logs2 + type: keyword \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs2/fields/fields.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs2/fields/fields.yml new file mode 100644 index 0000000000000..6e003ed0ad147 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs2/fields/fields.yml @@ -0,0 +1,16 @@ +- name: data_stream.type + type: constant_keyword + description: > + Data stream type. +- name: data_stream.dataset + type: constant_keyword + description: > + Data stream dataset. +- name: data_stream.namespace + type: constant_keyword + description: > + Data stream namespace. +- name: '@timestamp' + type: date + description: > + Event timestamp. diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs2/manifest.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs2/manifest.yml new file mode 100644 index 0000000000000..e12f454657ea2 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_logs2/manifest.yml @@ -0,0 +1,3 @@ +title: Test Dataset + +type: logs \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_metrics/fields/ecs.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_metrics/fields/ecs.yml new file mode 100644 index 0000000000000..9529c3a8eaf1a --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_metrics/fields/ecs.yml @@ -0,0 +1,3 @@ +- name: metrics_test_name2 + title: metrics_test_title2 + type: keyword \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_metrics/fields/fields.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_metrics/fields/fields.yml new file mode 100644 index 0000000000000..6e003ed0ad147 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_metrics/fields/fields.yml @@ -0,0 +1,16 @@ +- name: data_stream.type + type: constant_keyword + description: > + Data stream type. +- name: data_stream.dataset + type: constant_keyword + description: > + Data stream dataset. +- name: data_stream.namespace + type: constant_keyword + description: > + Data stream namespace. +- name: '@timestamp' + type: date + description: > + Event timestamp. diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_metrics/manifest.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_metrics/manifest.yml new file mode 100644 index 0000000000000..6bc20442bd432 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/dataset/test_metrics/manifest.yml @@ -0,0 +1,3 @@ +title: Test Dataset + +type: metrics \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/docs/README.md b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/docs/README.md new file mode 100644 index 0000000000000..2617f1fcabe11 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/docs/README.md @@ -0,0 +1,3 @@ +# Test package + +For testing that a package installs its elasticsearch assets when installed for the first time (not updating) and removing the package diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/img/logo_overrides_64_color.svg b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/img/logo_overrides_64_color.svg new file mode 100644 index 0000000000000..b03007a76ffcc --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/img/logo_overrides_64_color.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/dashboard/sample_dashboard.json b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/dashboard/sample_dashboard.json new file mode 100644 index 0000000000000..ef08d69324210 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/dashboard/sample_dashboard.json @@ -0,0 +1,16 @@ +{ + "attributes": { + "description": "Sample dashboard", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[],\"highlightAll\":true,\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"version\":true}" + }, + "optionsJSON": "{\"darkTheme\":false}", + "panelsJSON": "[{\"embeddableConfig\":{},\"gridData\":{\"h\":12,\"i\":\"1\",\"w\":24,\"x\":0,\"y\":0},\"panelIndex\":\"1\",\"panelRefName\":\"panel_0\",\"version\":\"7.3.0\"},{\"embeddableConfig\":{\"columns\":[\"kafka.log.class\",\"kafka.log.trace.class\",\"kafka.log.trace.full\"],\"sort\":[\"@timestamp\",\"desc\"]},\"gridData\":{\"h\":12,\"i\":\"2\",\"w\":24,\"x\":24,\"y\":0},\"panelIndex\":\"2\",\"panelRefName\":\"panel_1\",\"version\":\"7.3.0\"},{\"embeddableConfig\":{\"columns\":[\"log.level\",\"kafka.log.component\",\"message\"],\"sort\":[\"@timestamp\",\"desc\"]},\"gridData\":{\"h\":20,\"i\":\"3\",\"w\":48,\"x\":0,\"y\":20},\"panelIndex\":\"3\",\"panelRefName\":\"panel_2\",\"version\":\"7.3.0\"},{\"embeddableConfig\":{},\"gridData\":{\"h\":8,\"i\":\"4\",\"w\":48,\"x\":0,\"y\":12},\"panelIndex\":\"4\",\"panelRefName\":\"panel_3\",\"version\":\"7.3.0\"}]", + "timeRestore": false, + "title": "[Logs Sample] Overview ECS", + "version": 1 + }, + "id": "sample_dashboard", + "type": "dashboard" +} \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/search/sample_search2.json b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/search/sample_search2.json new file mode 100644 index 0000000000000..aa5cea19208a4 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/search/sample_search2.json @@ -0,0 +1,24 @@ +{ + "attributes": { + "columns": [ + "log.level", + "kafka.log.component", + "message" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"filter\":[{\"$state\":{\"store\":\"appState\"},\"meta\":{\"alias\":null,\"disabled\":false,\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\",\"key\":\"dataset.name\",\"negate\":false,\"params\":{\"query\":\"kafka.log\",\"type\":\"phrase\"},\"type\":\"phrase\",\"value\":\"log\"},\"query\":{\"match\":{\"dataset.name\":{\"query\":\"kafka.log\",\"type\":\"phrase\"}}}}],\"highlightAll\":true,\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\",\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"version\":true}" + }, + "sort": [ + [ + "@timestamp", + "desc" + ] + ], + "title": "All logs [Logs Kafka] ECS", + "version": 1 + }, + "id": "sample_search2", + "type": "search" +} \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/visualization/sample_visualization.json b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/visualization/sample_visualization.json new file mode 100644 index 0000000000000..626f1f787f421 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/visualization/sample_visualization.json @@ -0,0 +1,11 @@ +{ + "attributes": { + "description": "sample visualization 0.2.0", + "title": "sample vis title", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{},\"schema\":\"metric\",\"type\":\"count\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"extended_bounds\":{},\"field\":\"@timestamp\",\"interval\":\"auto\",\"min_doc_count\":1},\"schema\":\"segment\",\"type\":\"date_histogram\"},{\"enabled\":true,\"id\":\"3\",\"params\":{\"customLabel\":\"Log Level\",\"field\":\"log.level\",\"order\":\"desc\",\"orderBy\":\"1\",\"size\":5},\"schema\":\"group\",\"type\":\"terms\"}],\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"labels\":{\"show\":true,\"truncate\":100},\"position\":\"bottom\",\"scale\":{\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"@timestamp per day\"},\"type\":\"category\"}],\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"legendPosition\":\"right\",\"seriesParams\":[{\"data\":{\"id\":\"1\",\"label\":\"Count\"},\"drawLinesBetweenPoints\":true,\"mode\":\"stacked\",\"show\":\"true\",\"showCircles\":true,\"type\":\"histogram\",\"valueAxis\":\"ValueAxis-1\"}],\"times\":[],\"type\":\"histogram\",\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"labels\":{\"filter\":false,\"rotate\":0,\"show\":true,\"truncate\":100},\"name\":\"LeftAxis-1\",\"position\":\"left\",\"scale\":{\"mode\":\"normal\",\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"Count\"},\"type\":\"value\"}]},\"title\":\"Log levels over time [Logs Kafka] ECS\",\"type\":\"histogram\"}" + }, + "id": "sample_visualization", + "type": "visualization" +} \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/manifest.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/manifest.yml new file mode 100644 index 0000000000000..70da51a14bce8 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/manifest.yml @@ -0,0 +1,20 @@ +format_version: 1.0.0 +name: all_assets +title: All Assets Updated +description: tests that all assets are updated +version: 0.2.0 +categories: [] +release: beta +type: integration +license: basic + +requirement: + elasticsearch: + versions: '>7.7.0' + kibana: + versions: '>7.7.0' + +icons: + - src: '/img/logo_overrides_64_color.svg' + size: '16x16' + type: 'image/svg+xml' diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_logs/elasticsearch/ilm_policy/all_assets.json b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_logs/elasticsearch/ilm_policy/all_assets.json new file mode 100644 index 0000000000000..7cf62e890f865 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_logs/elasticsearch/ilm_policy/all_assets.json @@ -0,0 +1,15 @@ +{ + "policy": { + "phases": { + "hot": { + "min_age": "0ms", + "actions": { + "rollover": { + "max_size": "50gb", + "max_age": "30d" + } + } + } + } + } +} \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_logs/elasticsearch/ingest_pipeline/default.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_logs/elasticsearch/ingest_pipeline/default.yml new file mode 100644 index 0000000000000..580db049d0d5d --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_logs/elasticsearch/ingest_pipeline/default.yml @@ -0,0 +1,7 @@ +--- +description: Pipeline for parsing test logs + plugins. +processors: +- set: + field: error.message + value: '{{ _ingest.on_failure_message }}' \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_logs/fields/ecs.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_logs/fields/ecs.yml new file mode 100644 index 0000000000000..3d88fe5dfefb6 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_logs/fields/ecs.yml @@ -0,0 +1,3 @@ +- name: logs_test_name + title: logs_test_title + type: keyword \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_logs/fields/fields.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_logs/fields/fields.yml new file mode 100644 index 0000000000000..6e003ed0ad147 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_logs/fields/fields.yml @@ -0,0 +1,16 @@ +- name: data_stream.type + type: constant_keyword + description: > + Data stream type. +- name: data_stream.dataset + type: constant_keyword + description: > + Data stream dataset. +- name: data_stream.namespace + type: constant_keyword + description: > + Data stream namespace. +- name: '@timestamp' + type: date + description: > + Event timestamp. diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_logs/manifest.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_logs/manifest.yml new file mode 100644 index 0000000000000..8cd522e2845bb --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_logs/manifest.yml @@ -0,0 +1,9 @@ +title: Test Dataset + +type: logs + +elasticsearch: + index_template.mappings: + dynamic: false + index_template.settings: + index.lifecycle.name: reference \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_metrics/fields/ecs.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_metrics/fields/ecs.yml new file mode 100644 index 0000000000000..a30e3c7a87856 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_metrics/fields/ecs.yml @@ -0,0 +1,3 @@ +- name: metrics_test_name + title: metrics_test_title + type: keyword \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_metrics/fields/fields.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_metrics/fields/fields.yml new file mode 100644 index 0000000000000..6e003ed0ad147 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_metrics/fields/fields.yml @@ -0,0 +1,16 @@ +- name: data_stream.type + type: constant_keyword + description: > + Data stream type. +- name: data_stream.dataset + type: constant_keyword + description: > + Data stream dataset. +- name: data_stream.namespace + type: constant_keyword + description: > + Data stream namespace. +- name: '@timestamp' + type: date + description: > + Event timestamp. diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_metrics/manifest.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_metrics/manifest.yml new file mode 100644 index 0000000000000..6bc20442bd432 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/dataset/test_metrics/manifest.yml @@ -0,0 +1,3 @@ +title: Test Dataset + +type: metrics \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/docs/README.md b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/docs/README.md new file mode 100644 index 0000000000000..34b1f08a55cbe --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/docs/README.md @@ -0,0 +1,3 @@ +# Test package + +For testing that datastream rolls over when mappings are not compatible diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/manifest.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/manifest.yml new file mode 100644 index 0000000000000..0ab43760b7ee8 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.1.0/manifest.yml @@ -0,0 +1,20 @@ +format_version: 1.0.0 +name: datastreams +title: datastream test +description: This is a test package for testing that datastreams rollover when mappings are incompatible +version: 0.1.0 +categories: [] +release: beta +type: integration +license: basic + +requirement: + elasticsearch: + versions: '>7.7.0' + kibana: + versions: '>7.7.0' + +icons: + - src: '/img/logo_overrides_64_color.svg' + size: '16x16' + type: 'image/svg+xml' diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_logs/elasticsearch/ilm_policy/all_assets.json b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_logs/elasticsearch/ilm_policy/all_assets.json new file mode 100644 index 0000000000000..d8bab8a75f680 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_logs/elasticsearch/ilm_policy/all_assets.json @@ -0,0 +1,15 @@ +{ + "policy": { + "phases": { + "hot": { + "min_age": "1ms", + "actions": { + "rollover": { + "max_size": "50gb", + "max_age": "31d" + } + } + } + } + } +} \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_logs/elasticsearch/ingest_pipeline/default.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_logs/elasticsearch/ingest_pipeline/default.yml new file mode 100644 index 0000000000000..580db049d0d5d --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_logs/elasticsearch/ingest_pipeline/default.yml @@ -0,0 +1,7 @@ +--- +description: Pipeline for parsing test logs + plugins. +processors: +- set: + field: error.message + value: '{{ _ingest.on_failure_message }}' \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_logs/fields/ecs.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_logs/fields/ecs.yml new file mode 100644 index 0000000000000..7df52cc11fd20 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_logs/fields/ecs.yml @@ -0,0 +1,6 @@ +- name: logs_test_name + title: logs_test_title + type: text +- name: new_field_name + title: new_field_title + type: keyword diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_logs/fields/fields.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_logs/fields/fields.yml new file mode 100644 index 0000000000000..6e003ed0ad147 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_logs/fields/fields.yml @@ -0,0 +1,16 @@ +- name: data_stream.type + type: constant_keyword + description: > + Data stream type. +- name: data_stream.dataset + type: constant_keyword + description: > + Data stream dataset. +- name: data_stream.namespace + type: constant_keyword + description: > + Data stream namespace. +- name: '@timestamp' + type: date + description: > + Event timestamp. diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_logs/manifest.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_logs/manifest.yml new file mode 100644 index 0000000000000..8a53f9e26e827 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_logs/manifest.yml @@ -0,0 +1,9 @@ +title: Test Dataset + +type: logs + +elasticsearch: + index_template.mappings: + dynamic: true + index_template.settings: + index.lifecycle.name: reference2 \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_metrics/fields/ecs.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_metrics/fields/ecs.yml new file mode 100644 index 0000000000000..8fb3ccd3de8fd --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_metrics/fields/ecs.yml @@ -0,0 +1,6 @@ +- name: metrics_test_name + title: metrics_test_title + type: keyword +- name: metrics_test_name2 + title: metrics_test_title2 + type: keyword \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_metrics/fields/fields.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_metrics/fields/fields.yml new file mode 100644 index 0000000000000..6e003ed0ad147 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_metrics/fields/fields.yml @@ -0,0 +1,16 @@ +- name: data_stream.type + type: constant_keyword + description: > + Data stream type. +- name: data_stream.dataset + type: constant_keyword + description: > + Data stream dataset. +- name: data_stream.namespace + type: constant_keyword + description: > + Data stream namespace. +- name: '@timestamp' + type: date + description: > + Event timestamp. diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_metrics/manifest.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_metrics/manifest.yml new file mode 100644 index 0000000000000..6bc20442bd432 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/dataset/test_metrics/manifest.yml @@ -0,0 +1,3 @@ +title: Test Dataset + +type: metrics \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/docs/README.md b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/docs/README.md new file mode 100644 index 0000000000000..34b1f08a55cbe --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/docs/README.md @@ -0,0 +1,3 @@ +# Test package + +For testing that datastream rolls over when mappings are not compatible diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/manifest.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/manifest.yml new file mode 100644 index 0000000000000..1aa1410bd0aef --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/datastreams/0.2.0/manifest.yml @@ -0,0 +1,20 @@ +format_version: 1.0.0 +name: datastreams +title: datastream test +description: This is a test package for testing that datastreams rollover when mappings are incompatible +version: 0.2.0 +categories: [] +release: beta +type: integration +license: basic + +requirement: + elasticsearch: + versions: '>7.7.0' + kibana: + versions: '>7.7.0' + +icons: + - src: '/img/logo_overrides_64_color.svg' + size: '16x16' + type: 'image/svg+xml' diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/prerelease/0.1.0-dev.0+abc/dataset/test/fields/fields.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/prerelease/0.1.0-dev.0+abc/dataset/test/fields/fields.yml new file mode 100644 index 0000000000000..6e003ed0ad147 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/prerelease/0.1.0-dev.0+abc/dataset/test/fields/fields.yml @@ -0,0 +1,16 @@ +- name: data_stream.type + type: constant_keyword + description: > + Data stream type. +- name: data_stream.dataset + type: constant_keyword + description: > + Data stream dataset. +- name: data_stream.namespace + type: constant_keyword + description: > + Data stream namespace. +- name: '@timestamp' + type: date + description: > + Event timestamp. diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/prerelease/0.1.0-dev.0+abc/dataset/test/manifest.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/prerelease/0.1.0-dev.0+abc/dataset/test/manifest.yml new file mode 100644 index 0000000000000..17c33c745ce74 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/prerelease/0.1.0-dev.0+abc/dataset/test/manifest.yml @@ -0,0 +1,3 @@ +title: Test Dataset + +type: logs diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/prerelease/0.1.0-dev.0+abc/docs/README.md b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/prerelease/0.1.0-dev.0+abc/docs/README.md new file mode 100644 index 0000000000000..0002afd9cdfc0 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/prerelease/0.1.0-dev.0+abc/docs/README.md @@ -0,0 +1,3 @@ +# Test package + +For testing a prerelease package diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/prerelease/0.1.0-dev.0+abc/img/logo_prerelease_64_color.svg b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/prerelease/0.1.0-dev.0+abc/img/logo_prerelease_64_color.svg new file mode 100644 index 0000000000000..b03007a76ffcc --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/prerelease/0.1.0-dev.0+abc/img/logo_prerelease_64_color.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/prerelease/0.1.0-dev.0+abc/manifest.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/prerelease/0.1.0-dev.0+abc/manifest.yml new file mode 100644 index 0000000000000..a0adb184cfc59 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/prerelease/0.1.0-dev.0+abc/manifest.yml @@ -0,0 +1,20 @@ +format_version: 1.0.0 +name: prerelease +title: Prerelease package +description: This is a test package for testing that parsing a prerelease version works +version: 0.1.0-dev.0+abc +categories: ['security'] +release: beta +type: integration +license: basic + +requirement: + elasticsearch: + versions: '>7.7.0' + kibana: + versions: '>7.7.0' + +icons: + - src: '/img/logo_prerelease_64_color.svg' + size: '16x16' + type: 'image/svg+xml' diff --git a/x-pack/test/security_solution_cypress/es_archives/export_rule/mappings.json b/x-pack/test/security_solution_cypress/es_archives/export_rule/mappings.json index bb63d29503663..249b03981386d 100644 --- a/x-pack/test/security_solution_cypress/es_archives/export_rule/mappings.json +++ b/x-pack/test/security_solution_cypress/es_archives/export_rule/mappings.json @@ -1320,9 +1320,9 @@ "config": { "type": "flattened" }, - "dataset": { + "data_stream": { "properties": { - "name": { + "dataset": { "type": "keyword" }, "type": { diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts index d4947222a6cc0..02f893029f819 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts @@ -108,7 +108,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { inputs: [ { id: policyInfo.packageConfig.id, - dataset: { namespace: 'default' }, + data_stream: { namespace: 'default' }, name: 'Protect East Coast', meta: { package: { diff --git a/x-pack/test/security_solution_endpoint_api_int/apis/resolver/children.ts b/x-pack/test/security_solution_endpoint_api_int/apis/resolver/children.ts index cde1a3616b620..2dec3c755a93b 100644 --- a/x-pack/test/security_solution_endpoint_api_int/apis/resolver/children.ts +++ b/x-pack/test/security_solution_endpoint_api_int/apis/resolver/children.ts @@ -7,11 +7,12 @@ import expect from '@kbn/expect'; import { SearchResponse } from 'elasticsearch'; import { entityId } from '../../../../plugins/security_solution/common/endpoint/models/event'; import { eventsIndexPattern } from '../../../../plugins/security_solution/common/endpoint/constants'; -import { PaginationBuilder } from '../../../../plugins/security_solution/server/endpoint/routes/resolver/utils/pagination'; +import { ChildrenPaginationBuilder } from '../../../../plugins/security_solution/server/endpoint/routes/resolver/utils/children_pagination'; import { ChildrenQuery } from '../../../../plugins/security_solution/server/endpoint/routes/resolver/queries/children'; import { ResolverTree, ResolverEvent, + ResolverChildren, } from '../../../../plugins/security_solution/common/endpoint/types'; import { FtrProviderContext } from '../../ftr_provider_context'; import { @@ -112,7 +113,7 @@ export default function resolverAPIIntegrationTests({ getService }: FtrProviderC it('only retrieves the start event for the child node', async () => { const childrenQuery = new ChildrenQuery( - PaginationBuilder.createBuilder(100), + ChildrenPaginationBuilder.createBuilder(100), eventsIndexPattern ); // [1] here gets the body portion of the array @@ -125,5 +126,83 @@ export default function resolverAPIIntegrationTests({ getService }: FtrProviderC expect(event.event?.type).to.eql(['start']); }); }); + + describe('children api returns same node multiple times', () => { + let origin: Event; + let startEvent: Event; + let infoEvent: Event; + let execEvent: Event; + let genData: InsertedEvents; + + before(async () => { + // Construct the following tree: + // Origin -> (infoEvent, startEvent, execEvent are all for the same node) + origin = generator.generateEvent(); + startEvent = generator.generateEvent({ + parentEntityID: origin.process.entity_id, + ancestry: [origin.process.entity_id], + eventType: ['start'], + }); + + infoEvent = generator.generateEvent({ + timestamp: startEvent['@timestamp'] + 100, + parentEntityID: origin.process.entity_id, + ancestry: [origin.process.entity_id], + entityID: startEvent.process.entity_id, + eventType: ['info'], + }); + + execEvent = generator.generateEvent({ + timestamp: infoEvent['@timestamp'] + 100, + parentEntityID: origin.process.entity_id, + ancestry: [origin.process.entity_id], + eventType: ['change'], + entityID: startEvent.process.entity_id, + }); + genData = await resolver.insertEvents([origin, infoEvent, startEvent, execEvent]); + }); + + after(async () => { + await resolver.deleteData(genData); + }); + + it('retrieves the same node three times', async () => { + let { body }: { body: ResolverChildren } = await supertest + .get(`/api/endpoint/resolver/${origin.process.entity_id}/children?children=1`) + .expect(200); + expect(body.childNodes.length).to.be(1); + expect(body.nextChild).to.not.be(null); + expect(body.childNodes[0].entityID).to.be(startEvent.process.entity_id); + expect(body.childNodes[0].lifecycle[0].event?.type).to.eql(startEvent.event.type); + + ({ body } = await supertest + .get( + `/api/endpoint/resolver/${origin.process.entity_id}/children?children=1&afterChild=${body.nextChild}` + ) + .expect(200)); + expect(body.childNodes.length).to.be(1); + expect(body.nextChild).to.not.be(null); + expect(body.childNodes[0].entityID).to.be(infoEvent.process.entity_id); + expect(body.childNodes[0].lifecycle[1].event?.type).to.eql(infoEvent.event.type); + + ({ body } = await supertest + .get( + `/api/endpoint/resolver/${origin.process.entity_id}/children?children=1&afterChild=${body.nextChild}` + ) + .expect(200)); + expect(body.childNodes.length).to.be(1); + expect(body.nextChild).to.not.be(null); + expect(body.childNodes[0].entityID).to.be(infoEvent.process.entity_id); + expect(body.childNodes[0].lifecycle[2].event?.type).to.eql(execEvent.event.type); + + ({ body } = await supertest + .get( + `/api/endpoint/resolver/${origin.process.entity_id}/children?children=1&afterChild=${body.nextChild}` + ) + .expect(200)); + expect(body.childNodes.length).to.be(0); + expect(body.nextChild).to.be(null); + }); + }); }); } diff --git a/x-pack/test/security_solution_endpoint_api_int/apis/resolver/tree.ts b/x-pack/test/security_solution_endpoint_api_int/apis/resolver/tree.ts index 7b511c3be74b5..f4836379ca273 100644 --- a/x-pack/test/security_solution_endpoint_api_int/apis/resolver/tree.ts +++ b/x-pack/test/security_solution_endpoint_api_int/apis/resolver/tree.ts @@ -537,7 +537,6 @@ export default function ({ getService }: FtrProviderContext) { describe('legacy events', () => { const endpointID = '5a0c957f-b8e7-4538-965e-57e8bb86ad3a'; const entityID = '94041'; - const cursor = 'eyJ0aW1lc3RhbXAiOjE1ODE0NTYyNTUwMDAsImV2ZW50SUQiOiI5NDA0MiJ9'; it('returns child process lifecycle events', async () => { const { body }: { body: ResolverChildren } = await supertest @@ -566,20 +565,25 @@ export default function ({ getService }: FtrProviderContext) { ).to.eql(93932); }); - // The children api does not support pagination currently - it.skip('returns no values when there is no more data', async () => { - const { body } = await supertest - // after is set to the document id of the last event so there shouldn't be any more after it + it('returns no values when there is no more data', async () => { + let { body }: { body: ResolverChildren } = await supertest .get( - `/api/endpoint/resolver/${entityID}/children?legacyEndpointID=${endpointID}&afterChild=${cursor}` + // there should only be a single child for this node + `/api/endpoint/resolver/94041/children?legacyEndpointID=${endpointID}&children=1` ) .expect(200); + expect(body.nextChild).to.not.be(null); + + ({ body } = await supertest + .get( + `/api/endpoint/resolver/94041/children?legacyEndpointID=${endpointID}&afterChild=${body.nextChild}` + ) + .expect(200)); expect(body.childNodes).be.empty(); expect(body.nextChild).to.eql(null); }); - // The children api does not support pagination currently - it.skip('returns the first page of information when the cursor is invalid', async () => { + it('returns the first page of information when the cursor is invalid', async () => { const { body }: { body: ResolverChildren } = await supertest .get( `/api/endpoint/resolver/${entityID}/children?legacyEndpointID=${endpointID}&afterChild=blah` @@ -641,8 +645,7 @@ export default function ({ getService }: FtrProviderContext) { expect(body.nextChild).to.not.eql(null); }); - // children api does not support pagination currently - it.skip('paginates the children', async () => { + it('paginates the children', async () => { // this gets a node should have 3 children which were created in succession so that the timestamps // are ordered correctly to be retrieved in a single call const distantChildEntityID = Array.from(tree.childrenLevels[0].values())[0].id; @@ -671,8 +674,7 @@ export default function ({ getService }: FtrProviderContext) { expect(body.nextChild).to.be(null); }); - // children api does not support pagination currently - it.skip('gets all children in two queries', async () => { + it('gets all children in two queries', async () => { // should get all the children of the origin let { body }: { body: ResolverChildren } = await supertest .get(`/api/endpoint/resolver/${tree.origin.id}/children?children=3`) diff --git a/yarn.lock b/yarn.lock index 7aff34fab23ce..6f82c8126ac06 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,16 +2,16 @@ # yarn lockfile v1 -"@babel/cli@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.10.1.tgz#b6e5cd43a17b8f639442ab027976408ebe6d79a0" - integrity sha512-cVB+dXeGhMOqViIaZs3A9OUAe4pKw4SBNdMw6yHJMYR7s4TB+Cei7ThquV/84O19PdIFWuwe03vxxES0BHUm5g== +"@babel/cli@^7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.10.5.tgz#57df2987c8cf89d0fc7d4b157ec59d7619f1b77a" + integrity sha512-j9H9qSf3kLdM0Ao3aGPbGZ73mEA9XazuupcS6cDGWuiyAcANoguhP0r2Lx32H5JGw4sSSoHG3x/mxVnHgvOoyA== dependencies: commander "^4.0.1" convert-source-map "^1.1.0" fs-readdir-recursive "^1.1.0" glob "^7.0.0" - lodash "^4.17.13" + lodash "^4.17.19" make-dir "^2.1.0" slash "^2.0.0" source-map "^0.5.0" @@ -32,17 +32,17 @@ dependencies: "@babel/highlight" "^7.8.3" -"@babel/code-frame@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.1.tgz#d5481c5095daa1c57e16e54c6f9198443afb49ff" - integrity sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw== +"@babel/code-frame@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" + integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== dependencies: - "@babel/highlight" "^7.10.1" + "@babel/highlight" "^7.10.4" -"@babel/compat-data@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.10.1.tgz#b1085ffe72cd17bf2c0ee790fc09f9626011b2db" - integrity sha512-CHvCj7So7iCkGKPRFUfryXIkU2gSBw7VSZFYLsqVhrS47269VK2Hfi9S/YcublPMW8k1u2bQBlbDruoQEm4fgw== +"@babel/compat-data@^7.10.4", "@babel/compat-data@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.11.0.tgz#e9f73efe09af1355b723a7f39b11bad637d7c99c" + integrity sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ== dependencies: browserslist "^4.12.0" invariant "^2.2.4" @@ -79,24 +79,24 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.10.2": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.2.tgz#bd6786046668a925ac2bd2fd95b579b92a23b36a" - integrity sha512-KQmV9yguEjQsXqyOUGKjS4+3K8/DlOCE2pZcq4augdQmtTy5iv5EHtmMSJ7V4c1BIPjuwtZYqYLCq9Ga+hGBRQ== - dependencies: - "@babel/code-frame" "^7.10.1" - "@babel/generator" "^7.10.2" - "@babel/helper-module-transforms" "^7.10.1" - "@babel/helpers" "^7.10.1" - "@babel/parser" "^7.10.2" - "@babel/template" "^7.10.1" - "@babel/traverse" "^7.10.1" - "@babel/types" "^7.10.2" +"@babel/core@^7.11.1": + version "7.11.1" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.1.tgz#2c55b604e73a40dc21b0e52650b11c65cf276643" + integrity sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.0" + "@babel/helper-module-transforms" "^7.11.0" + "@babel/helpers" "^7.10.4" + "@babel/parser" "^7.11.1" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.11.0" + "@babel/types" "^7.11.0" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" json5 "^2.1.2" - lodash "^4.17.13" + lodash "^4.17.19" resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" @@ -111,14 +111,13 @@ lodash "^4.17.13" source-map "^0.5.0" -"@babel/generator@^7.10.1", "@babel/generator@^7.10.2": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.2.tgz#0fa5b5b2389db8bfdfcc3492b551ee20f5dd69a9" - integrity sha512-AxfBNHNu99DTMvlUPlt1h2+Hn7knPpH5ayJ8OqDWSeLld+Fi2AYBTC/IejWDM9Edcii4UzZRCsbUt0WlSDsDsA== +"@babel/generator@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.0.tgz#4b90c78d8c12825024568cbe83ee6c9af193585c" + integrity sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ== dependencies: - "@babel/types" "^7.10.2" + "@babel/types" "^7.11.0" jsesc "^2.5.1" - lodash "^4.17.13" source-map "^0.5.0" "@babel/generator@^7.9.5": @@ -138,20 +137,20 @@ dependencies: "@babel/types" "^7.8.3" -"@babel/helper-annotate-as-pure@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.1.tgz#f6d08acc6f70bbd59b436262553fb2e259a1a268" - integrity sha512-ewp3rvJEwLaHgyWGe4wQssC2vjks3E80WiUe2BpMb0KhreTjMROCbxXcEovTrbeGVdQct5VjQfrv9EgC+xMzCw== +"@babel/helper-annotate-as-pure@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3" + integrity sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA== dependencies: - "@babel/types" "^7.10.1" + "@babel/types" "^7.10.4" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.1.tgz#0ec7d9be8174934532661f87783eb18d72290059" - integrity sha512-cQpVq48EkYxUU0xozpGCLla3wlkdRRqLWu1ksFMXA9CM5KQmyyRpSEsYXbao7JUkOw/tAaYKCaYyZq6HOFYtyw== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" + integrity sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg== dependencies: - "@babel/helper-explode-assignable-expression" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/helper-explode-assignable-expression" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/helper-builder-binary-assignment-operator-visitor@^7.8.3": version "7.8.3" @@ -161,14 +160,14 @@ "@babel/helper-explode-assignable-expression" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helper-builder-react-jsx-experimental@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.10.1.tgz#9a7d58ad184d3ac3bafb1a452cec2bad7e4a0bc8" - integrity sha512-irQJ8kpQUV3JasXPSFQ+LCCtJSc5ceZrPFVj6TElR6XCHssi3jV8ch3odIrNtjJFRZZVbrOEfJMI79TPU/h1pQ== +"@babel/helper-builder-react-jsx-experimental@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.10.5.tgz#f35e956a19955ff08c1258e44a515a6d6248646b" + integrity sha512-Buewnx6M4ttG+NLkKyt7baQn7ScC/Td+e99G914fRU8fGIUivDDgVIQeDHFa5e4CRSJQt58WpNHhsAZgtzVhsg== dependencies: - "@babel/helper-annotate-as-pure" "^7.10.1" - "@babel/helper-module-imports" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-module-imports" "^7.10.4" + "@babel/types" "^7.10.5" "@babel/helper-builder-react-jsx-experimental@^7.9.0": version "7.9.0" @@ -179,13 +178,13 @@ "@babel/helper-module-imports" "^7.8.3" "@babel/types" "^7.9.0" -"@babel/helper-builder-react-jsx@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.1.tgz#a327f0cf983af5554701b1215de54a019f09b532" - integrity sha512-KXzzpyWhXgzjXIlJU1ZjIXzUPdej1suE6vzqgImZ/cpAsR/CC8gUcX4EWRmDfWz/cs6HOCPMBIJ3nKoXt3BFuw== +"@babel/helper-builder-react-jsx@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.4.tgz#8095cddbff858e6fa9c326daee54a2f2732c1d5d" + integrity sha512-5nPcIZ7+KKDxT1427oBivl9V9YTal7qk0diccnh7RrcgrT/pGFOjgGw1dgryyx1GvHEpXVfoDF6Ak3rTiWh8Rg== dependencies: - "@babel/helper-annotate-as-pure" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/helper-builder-react-jsx@^7.9.0": version "7.9.0" @@ -195,12 +194,12 @@ "@babel/helper-annotate-as-pure" "^7.8.3" "@babel/types" "^7.9.0" -"@babel/helper-compilation-targets@^7.10.2": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.2.tgz#a17d9723b6e2c750299d2a14d4637c76936d8285" - integrity sha512-hYgOhF4To2UTB4LTaZepN/4Pl9LD4gfbJx8A34mqoluT8TLbof1mhUlYuNWTEebONa8+UlCC4X0TEXu7AOUyGA== +"@babel/helper-compilation-targets@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz#804ae8e3f04376607cc791b9d47d540276332bd2" + integrity sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ== dependencies: - "@babel/compat-data" "^7.10.1" + "@babel/compat-data" "^7.10.4" browserslist "^4.12.0" invariant "^2.2.4" levenary "^1.1.1" @@ -217,17 +216,17 @@ levenary "^1.1.1" semver "^5.5.0" -"@babel/helper-create-class-features-plugin@^7.10.1": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.2.tgz#7474295770f217dbcf288bf7572eb213db46ee67" - integrity sha512-5C/QhkGFh1vqcziq1vAL6SI9ymzUp8BCYjFpvYVhWP4DlATIb3u5q3iUd35mvlyGs8fO7hckkW7i0tmH+5+bvQ== +"@babel/helper-create-class-features-plugin@^7.10.4", "@babel/helper-create-class-features-plugin@^7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d" + integrity sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A== dependencies: - "@babel/helper-function-name" "^7.10.1" - "@babel/helper-member-expression-to-functions" "^7.10.1" - "@babel/helper-optimise-call-expression" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/helper-replace-supers" "^7.10.1" - "@babel/helper-split-export-declaration" "^7.10.1" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^7.10.5" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" "@babel/helper-create-class-features-plugin@^7.8.3": version "7.8.6" @@ -241,13 +240,13 @@ "@babel/helper-replace-supers" "^7.8.6" "@babel/helper-split-export-declaration" "^7.8.3" -"@babel/helper-create-regexp-features-plugin@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.1.tgz#1b8feeab1594cbcfbf3ab5a3bbcabac0468efdbd" - integrity sha512-Rx4rHS0pVuJn5pJOqaqcZR4XSgeF9G/pO/79t+4r7380tXFJdzImFnxMU19f83wjSrmKHq6myrM10pFHTGzkUA== +"@babel/helper-create-regexp-features-plugin@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz#fdd60d88524659a0b6959c0579925e425714f3b8" + integrity sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g== dependencies: - "@babel/helper-annotate-as-pure" "^7.10.1" - "@babel/helper-regex" "^7.10.1" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-regex" "^7.10.4" regexpu-core "^4.7.0" "@babel/helper-create-regexp-features-plugin@^7.8.3", "@babel/helper-create-regexp-features-plugin@^7.8.8": @@ -259,14 +258,14 @@ "@babel/helper-regex" "^7.8.3" regexpu-core "^4.7.0" -"@babel/helper-define-map@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.1.tgz#5e69ee8308648470dd7900d159c044c10285221d" - integrity sha512-+5odWpX+OnvkD0Zmq7panrMuAGQBu6aPUgvMzuMGo4R+jUOvealEj2hiqI6WhxgKrTpFoFj0+VdsuA8KDxHBDg== +"@babel/helper-define-map@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" + integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ== dependencies: - "@babel/helper-function-name" "^7.10.1" - "@babel/types" "^7.10.1" - lodash "^4.17.13" + "@babel/helper-function-name" "^7.10.4" + "@babel/types" "^7.10.5" + lodash "^4.17.19" "@babel/helper-define-map@^7.8.3": version "7.8.3" @@ -277,13 +276,13 @@ "@babel/types" "^7.8.3" lodash "^4.17.13" -"@babel/helper-explode-assignable-expression@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.1.tgz#e9d76305ee1162ca467357ae25df94f179af2b7e" - integrity sha512-vcUJ3cDjLjvkKzt6rHrl767FeE7pMEYfPanq5L16GRtrXIoznc0HykNW2aEYkcnP76P0isoqJ34dDMFZwzEpJg== +"@babel/helper-explode-assignable-expression@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.4.tgz#40a1cd917bff1288f699a94a75b37a1a2dbd8c7c" + integrity sha512-4K71RyRQNPRrR85sr5QY4X3VwG4wtVoXZB9+L3r1Gp38DhELyHCtovqydRi7c1Ovb17eRGiQ/FD5s8JdU0Uy5A== dependencies: - "@babel/traverse" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/helper-explode-assignable-expression@^7.8.3": version "7.8.3" @@ -293,14 +292,14 @@ "@babel/traverse" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helper-function-name@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.1.tgz#92bd63829bfc9215aca9d9defa85f56b539454f4" - integrity sha512-fcpumwhs3YyZ/ttd5Rz0xn0TpIwVkN7X0V38B9TWNfVF42KEkhkAAuPCQ3oXmtTRtiPJrmZ0TrfS0GKF0eMaRQ== +"@babel/helper-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" + integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== dependencies: - "@babel/helper-get-function-arity" "^7.10.1" - "@babel/template" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/helper-function-name@^7.8.3": version "7.8.3" @@ -320,12 +319,12 @@ "@babel/template" "^7.8.3" "@babel/types" "^7.9.5" -"@babel/helper-get-function-arity@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz#7303390a81ba7cb59613895a192b93850e373f7d" - integrity sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw== +"@babel/helper-get-function-arity@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" + integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== dependencies: - "@babel/types" "^7.10.1" + "@babel/types" "^7.10.4" "@babel/helper-get-function-arity@^7.8.3": version "7.8.3" @@ -334,12 +333,12 @@ dependencies: "@babel/types" "^7.8.3" -"@babel/helper-hoist-variables@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.1.tgz#7e77c82e5dcae1ebf123174c385aaadbf787d077" - integrity sha512-vLm5srkU8rI6X3+aQ1rQJyfjvCBLXP8cAGeuw04zeAM2ItKb1e7pmVmLyHb4sDaAYnLL13RHOZPLEtcGZ5xvjg== +"@babel/helper-hoist-variables@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" + integrity sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA== dependencies: - "@babel/types" "^7.10.1" + "@babel/types" "^7.10.4" "@babel/helper-hoist-variables@^7.8.3": version "7.8.3" @@ -348,12 +347,12 @@ dependencies: "@babel/types" "^7.8.3" -"@babel/helper-member-expression-to-functions@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.1.tgz#432967fd7e12a4afef66c4687d4ca22bc0456f15" - integrity sha512-u7XLXeM2n50gb6PWJ9hoO5oO7JFPaZtrh35t8RqKLT1jFKj9IWeD1zrcrYp1q1qiZTdEarfDWfTIP8nGsu0h5g== +"@babel/helper-member-expression-to-functions@^7.10.4", "@babel/helper-member-expression-to-functions@^7.10.5": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df" + integrity sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q== dependencies: - "@babel/types" "^7.10.1" + "@babel/types" "^7.11.0" "@babel/helper-member-expression-to-functions@^7.8.3": version "7.8.3" @@ -369,25 +368,25 @@ dependencies: "@babel/types" "^7.8.3" -"@babel/helper-module-imports@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.1.tgz#dd331bd45bccc566ce77004e9d05fe17add13876" - integrity sha512-SFxgwYmZ3HZPyZwJRiVNLRHWuW2OgE5k2nrVs6D9Iv4PPnXVffuEHy83Sfx/l4SqF+5kyJXjAyUmrG7tNm+qVg== +"@babel/helper-module-imports@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620" + integrity sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw== dependencies: - "@babel/types" "^7.10.1" + "@babel/types" "^7.10.4" -"@babel/helper-module-transforms@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz#24e2f08ee6832c60b157bb0936c86bef7210c622" - integrity sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg== +"@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.10.5", "@babel/helper-module-transforms@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359" + integrity sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg== dependencies: - "@babel/helper-module-imports" "^7.10.1" - "@babel/helper-replace-supers" "^7.10.1" - "@babel/helper-simple-access" "^7.10.1" - "@babel/helper-split-export-declaration" "^7.10.1" - "@babel/template" "^7.10.1" - "@babel/types" "^7.10.1" - lodash "^4.17.13" + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/template" "^7.10.4" + "@babel/types" "^7.11.0" + lodash "^4.17.19" "@babel/helper-module-transforms@^7.9.0": version "7.9.0" @@ -402,12 +401,12 @@ "@babel/types" "^7.9.0" lodash "^4.17.13" -"@babel/helper-optimise-call-expression@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.1.tgz#b4a1f2561870ce1247ceddb02a3860fa96d72543" - integrity sha512-a0DjNS1prnBsoKx83dP2falChcs7p3i8VMzdrSbfLhuQra/2ENC4sbri34dz/rWmDADsmF1q5GbfaXydh0Jbjg== +"@babel/helper-optimise-call-expression@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" + integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg== dependencies: - "@babel/types" "^7.10.1" + "@babel/types" "^7.10.4" "@babel/helper-optimise-call-expression@^7.8.3": version "7.8.3" @@ -421,17 +420,17 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== -"@babel/helper-plugin-utils@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.1.tgz#ec5a5cf0eec925b66c60580328b122c01230a127" - integrity sha512-fvoGeXt0bJc7VMWZGCAEBEMo/HAjW2mP8apF5eXK0wSqwLAVHAISCWRoLMBMUs2kqeaG77jltVqu4Hn8Egl3nA== +"@babel/helper-plugin-utils@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" + integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== -"@babel/helper-regex@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.1.tgz#021cf1a7ba99822f993222a001cc3fec83255b96" - integrity sha512-7isHr19RsIJWWLLFn21ubFt223PjQyg1HY7CZEMRr820HttHPpVvrsIN3bUOo44DEfFV4kBXO7Abbn9KTUZV7g== +"@babel/helper-regex@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.5.tgz#32dfbb79899073c415557053a19bd055aae50ae0" + integrity sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg== dependencies: - lodash "^4.17.13" + lodash "^4.17.19" "@babel/helper-regex@^7.8.3": version "7.8.3" @@ -440,16 +439,16 @@ dependencies: lodash "^4.17.13" -"@babel/helper-remap-async-to-generator@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.1.tgz#bad6aaa4ff39ce8d4b82ccaae0bfe0f7dbb5f432" - integrity sha512-RfX1P8HqsfgmJ6CwaXGKMAqbYdlleqglvVtht0HGPMSsy2V6MqLlOJVF/0Qyb/m2ZCi2z3q3+s6Pv7R/dQuZ6A== +"@babel/helper-remap-async-to-generator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.4.tgz#fce8bea4e9690bbe923056ded21e54b4e8b68ed5" + integrity sha512-86Lsr6NNw3qTNl+TBcF1oRZMaVzJtbWTyTko+CQL/tvNvcGYEFKbLXDPxtW0HKk3McNOk4KzY55itGWCAGK5tg== dependencies: - "@babel/helper-annotate-as-pure" "^7.10.1" - "@babel/helper-wrap-function" "^7.10.1" - "@babel/template" "^7.10.1" - "@babel/traverse" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-wrap-function" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/helper-remap-async-to-generator@^7.8.3": version "7.8.3" @@ -462,15 +461,15 @@ "@babel/traverse" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helper-replace-supers@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz#ec6859d20c5d8087f6a2dc4e014db7228975f13d" - integrity sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A== +"@babel/helper-replace-supers@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf" + integrity sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A== dependencies: - "@babel/helper-member-expression-to-functions" "^7.10.1" - "@babel/helper-optimise-call-expression" "^7.10.1" - "@babel/traverse" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/helper-member-expression-to-functions" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/helper-replace-supers@^7.8.3", "@babel/helper-replace-supers@^7.8.6": version "7.8.6" @@ -482,13 +481,13 @@ "@babel/traverse" "^7.8.6" "@babel/types" "^7.8.6" -"@babel/helper-simple-access@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz#08fb7e22ace9eb8326f7e3920a1c2052f13d851e" - integrity sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw== +"@babel/helper-simple-access@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz#0f5ccda2945277a2a7a2d3a821e15395edcf3461" + integrity sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw== dependencies: - "@babel/template" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/helper-simple-access@^7.8.3": version "7.8.3" @@ -498,12 +497,19 @@ "@babel/template" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helper-split-export-declaration@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz#c6f4be1cbc15e3a868e4c64a17d5d31d754da35f" - integrity sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g== +"@babel/helper-skip-transparent-expression-wrappers@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz#eec162f112c2f58d3af0af125e3bb57665146729" + integrity sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q== dependencies: - "@babel/types" "^7.10.1" + "@babel/types" "^7.11.0" + +"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" + integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== + dependencies: + "@babel/types" "^7.11.0" "@babel/helper-split-export-declaration@^7.8.3": version "7.8.3" @@ -512,10 +518,10 @@ dependencies: "@babel/types" "^7.8.3" -"@babel/helper-validator-identifier@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz#5770b0c1a826c4f53f5ede5e153163e0318e94b5" - integrity sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw== +"@babel/helper-validator-identifier@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" + integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== "@babel/helper-validator-identifier@^7.9.0": version "7.9.0" @@ -527,15 +533,15 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80" integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g== -"@babel/helper-wrap-function@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.1.tgz#956d1310d6696257a7afd47e4c42dfda5dfcedc9" - integrity sha512-C0MzRGteVDn+H32/ZgbAv5r56f2o1fZSA/rj/TYo8JEJNHg+9BdSmKBUND0shxWRztWhjlT2cvHYuynpPsVJwQ== +"@babel/helper-wrap-function@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" + integrity sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug== dependencies: - "@babel/helper-function-name" "^7.10.1" - "@babel/template" "^7.10.1" - "@babel/traverse" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/helper-function-name" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/helper-wrap-function@^7.8.3": version "7.8.3" @@ -547,14 +553,14 @@ "@babel/traverse" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helpers@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.1.tgz#a6827b7cb975c9d9cef5fd61d919f60d8844a973" - integrity sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw== +"@babel/helpers@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044" + integrity sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA== dependencies: - "@babel/template" "^7.10.1" - "@babel/traverse" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/helpers@^7.9.0": version "7.9.2" @@ -574,12 +580,12 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/highlight@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.1.tgz#841d098ba613ba1a427a2b383d79e35552c38ae0" - integrity sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg== +"@babel/highlight@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== dependencies: - "@babel/helper-validator-identifier" "^7.10.1" + "@babel/helper-validator-identifier" "^7.10.4" chalk "^2.0.0" js-tokens "^4.0.0" @@ -588,18 +594,18 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8" integrity sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA== -"@babel/parser@^7.10.1", "@babel/parser@^7.10.2": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.2.tgz#871807f10442b92ff97e4783b9b54f6a0ca812d0" - integrity sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ== +"@babel/parser@^7.10.4", "@babel/parser@^7.11.0", "@babel/parser@^7.11.1", "@babel/parser@^7.11.2": + version "7.11.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.2.tgz#0882ab8a455df3065ea2dcb4c753b2460a24bead" + integrity sha512-Vuj/+7vLo6l1Vi7uuO+1ngCDNeVmNbTngcJFKCR/oEtz8tKz0CJxZEGmPt9KcIloZhOZ3Zit6xbpXT2MDlS9Vw== -"@babel/plugin-proposal-async-generator-functions@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.1.tgz#6911af5ba2e615c4ff3c497fe2f47b35bf6d7e55" - integrity sha512-vzZE12ZTdB336POZjmpblWfNNRpMSua45EYnRigE2XsZxcXcIyly2ixnTJasJE4Zq3U7t2d8rRF7XRUuzHxbOw== +"@babel/plugin-proposal-async-generator-functions@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz#3491cabf2f7c179ab820606cec27fed15e0e8558" + integrity sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/helper-remap-async-to-generator" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.10.4" "@babel/plugin-syntax-async-generators" "^7.8.0" "@babel/plugin-proposal-async-generator-functions@^7.8.3": @@ -611,13 +617,13 @@ "@babel/helper-remap-async-to-generator" "^7.8.3" "@babel/plugin-syntax-async-generators" "^7.8.0" -"@babel/plugin-proposal-class-properties@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.1.tgz#046bc7f6550bb08d9bd1d4f060f5f5a4f1087e01" - integrity sha512-sqdGWgoXlnOdgMXU+9MbhzwFRgxVLeiGBqTrnuS7LC2IBU31wSsESbTUreT2O418obpfPdGUR2GbEufZF1bpqw== +"@babel/plugin-proposal-class-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz#a33bf632da390a59c7a8c570045d1115cd778807" + integrity sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg== dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-proposal-class-properties@^7.7.0": version "7.8.3" @@ -627,12 +633,12 @@ "@babel/helper-create-class-features-plugin" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-proposal-dynamic-import@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.1.tgz#e36979dc1dc3b73f6d6816fc4951da2363488ef0" - integrity sha512-Cpc2yUVHTEGPlmiQzXj026kqwjEQAD9I4ZC16uzdbgWgitg/UHKHLffKNCQZ5+y8jpIZPJcKcwsr2HwPh+w3XA== +"@babel/plugin-proposal-dynamic-import@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz#ba57a26cb98b37741e9d5bca1b8b0ddf8291f17e" + integrity sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-dynamic-import" "^7.8.0" "@babel/plugin-proposal-dynamic-import@^7.8.3": @@ -643,20 +649,20 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-dynamic-import" "^7.8.0" -"@babel/plugin-proposal-export-namespace-from@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.1.tgz#512ee069cd866256600bdf89639cf7e1b51fbfe9" - integrity sha512-eR4CoYb6mh5y9LWjnb4CyUatuhtZ8pNLXLDi46GkqtF7WPafFqXycHdvF5qWviozZVGRSAmHzdayc8wUReCdjA== +"@babel/plugin-proposal-export-namespace-from@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz#570d883b91031637b3e2958eea3c438e62c05f54" + integrity sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-proposal-json-strings@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.1.tgz#b1e691ee24c651b5a5e32213222b2379734aff09" - integrity sha512-m8r5BmV+ZLpWPtMY2mOKN7wre6HIO4gfIiV+eOmsnZABNenrt/kzYBwrh+KOfgumSWpnlGs5F70J8afYMSJMBg== +"@babel/plugin-proposal-json-strings@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz#593e59c63528160233bd321b1aebe0820c2341db" + integrity sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.0" "@babel/plugin-proposal-json-strings@^7.8.3": @@ -667,12 +673,20 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-json-strings" "^7.8.0" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.1.tgz#02dca21673842ff2fe763ac253777f235e9bbf78" - integrity sha512-56cI/uHYgL2C8HVuHOuvVowihhX0sxb3nnfVRzUeVHTWmRHTZrKuAh/OBIMggGU/S1g/1D2CRCXqP+3u7vX7iA== +"@babel/plugin-proposal-logical-assignment-operators@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz#9f80e482c03083c87125dee10026b58527ea20c8" + integrity sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz#02a7e961fc32e6d5b2db0649e01bf80ddee7e04a" + integrity sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" "@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": @@ -683,13 +697,13 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@babel/plugin-proposal-numeric-separator@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.1.tgz#a9a38bc34f78bdfd981e791c27c6fdcec478c123" - integrity sha512-jjfym4N9HtCiNfyyLAVD8WqPYeHUrw4ihxuAynWj6zzp2gf9Ey2f7ImhFm6ikB3CLf5Z/zmcJDri6B4+9j9RsA== +"@babel/plugin-proposal-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz#ce1590ff0a65ad12970a609d78855e9a4c1aef06" + integrity sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-numeric-separator" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-proposal-numeric-separator@^7.8.3": version "7.8.3" @@ -699,14 +713,14 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-numeric-separator" "^7.8.3" -"@babel/plugin-proposal-object-rest-spread@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.10.1.tgz#cba44908ac9f142650b4a65b8aa06bf3478d5fb6" - integrity sha512-Z+Qri55KiQkHh7Fc4BW6o+QBuTagbOp9txE+4U1i79u9oWlf2npkiDx+Rf3iK3lbcHBuNy9UOkwuR5wOMH3LIQ== +"@babel/plugin-proposal-object-rest-spread@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz#bd81f95a1f746760ea43b6c2d3d62b11790ad0af" + integrity sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.10.1" + "@babel/plugin-transform-parameters" "^7.10.4" "@babel/plugin-proposal-object-rest-spread@^7.6.2", "@babel/plugin-proposal-object-rest-spread@^7.9.0": version "7.9.0" @@ -716,12 +730,12 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" -"@babel/plugin-proposal-optional-catch-binding@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.1.tgz#c9f86d99305f9fa531b568ff5ab8c964b8b223d2" - integrity sha512-VqExgeE62YBqI3ogkGoOJp1R6u12DFZjqwJhqtKc2o5m1YTUuUWnos7bZQFBhwkxIFpWYJ7uB75U7VAPPiKETA== +"@babel/plugin-proposal-optional-catch-binding@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz#31c938309d24a78a49d68fdabffaa863758554dd" + integrity sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" "@babel/plugin-proposal-optional-catch-binding@^7.8.3": @@ -732,12 +746,13 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.1.tgz#15f5d6d22708629451a91be28f8facc55b0e818c" - integrity sha512-dqQj475q8+/avvok72CF3AOSV/SGEcH29zT5hhohqqvvZ2+boQoOr7iGldBG5YXTO2qgCgc2B3WvVLUdbeMlGA== +"@babel/plugin-proposal-optional-chaining@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz#de5866d0646f6afdaab8a566382fe3a221755076" + integrity sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" "@babel/plugin-syntax-optional-chaining" "^7.8.0" "@babel/plugin-proposal-optional-chaining@^7.9.0": @@ -748,21 +763,21 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-private-methods@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.1.tgz#ed85e8058ab0fe309c3f448e5e1b73ca89cdb598" - integrity sha512-RZecFFJjDiQ2z6maFprLgrdnm0OzoC23Mx89xf1CcEsxmHuzuXOdniEuI+S3v7vjQG4F5sa6YtUp+19sZuSxHg== +"@babel/plugin-proposal-private-methods@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz#b160d972b8fdba5c7d111a145fc8c421fc2a6909" + integrity sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-proposal-unicode-property-regex@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.1.tgz#dc04feb25e2dd70c12b05d680190e138fa2c0c6f" - integrity sha512-JjfngYRvwmPwmnbRZyNiPFI8zxCZb8euzbCG/LxyKdeTb59tVciKo9GK9bi6JYKInk1H11Dq9j/zRqIH4KigfQ== +"@babel/plugin-proposal-unicode-property-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz#4483cda53041ce3413b7fe2f00022665ddfaa75d" + integrity sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.8.3": version "7.8.8" @@ -786,12 +801,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-class-properties@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.1.tgz#d5bc0645913df5b17ad7eda0fa2308330bde34c5" - integrity sha512-Gf2Yx/iRs1JREDtVZ56OrjjgFHCaldpTnuy9BHla10qyVT3YkIIGEtoDWhyop0ksu1GvNjHIoYRBqm3zoR1jyQ== +"@babel/plugin-syntax-class-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz#6644e6a0baa55a61f9e3231f6c9eeb6ee46c124c" + integrity sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-class-properties@^7.8.3": version "7.8.3" @@ -828,12 +843,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.1.tgz#0ae371134a42b91d5418feb3c8c8d43e1565d2da" - integrity sha512-+OxyOArpVFXQeXKLO9o+r2I4dIoVoy6+Uu0vKELrlweDM3QJADZj+Z+5ERansZqIZBcLj42vHnDI8Rz9BnRIuQ== +"@babel/plugin-syntax-jsx@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.4.tgz#39abaae3cbf710c4373d8429484e6ba21340166c" + integrity sha512-KCg9mio9jwiARCB7WAcQ7Y1q+qicILjoK8LP/VkPkEKaf5dkaZZK1EcTe91a3JJlZ3qy6L5s9X52boEYi8DM9g== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-jsx@^7.8.3": version "7.8.3" @@ -842,6 +857,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.8.3.tgz#3995d7d7ffff432f6ddc742b47e730c054599897" @@ -856,12 +878,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.1.tgz#25761ee7410bc8cf97327ba741ee94e4a61b7d99" - integrity sha512-uTd0OsHrpe3tH5gRPTxG8Voh99/WCU78vIm5NMRYPAqC8lR4vajt6KkCAknCHrx24vkPdd/05yfdGSB4EIY2mg== +"@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-numeric-separator@^7.8.0", "@babel/plugin-syntax-numeric-separator@^7.8.3": version "7.8.3" @@ -891,12 +913,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.1.tgz#8b8733f8c57397b3eaa47ddba8841586dcaef362" - integrity sha512-hgA5RYkmZm8FTFT3yu2N9Bx7yVVOKYT6yEdXXo6j2JTm0wNxgqaGeQVaSHRjhfnQbX91DtjFB6McRFSlcJH3xQ== +"@babel/plugin-syntax-top-level-await@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz#4bbeb8917b54fcf768364e0a81f560e33a3ef57d" + integrity sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-top-level-await@^7.8.3": version "7.8.3" @@ -905,19 +927,19 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-typescript@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.10.1.tgz#5e82bc27bb4202b93b949b029e699db536733810" - integrity sha512-X/d8glkrAtra7CaQGMiGs/OGa6XgUzqPcBXCIGFCpCqnfGlT0Wfbzo/B89xHhnInTaItPK8LALblVXcUOEh95Q== +"@babel/plugin-syntax-typescript@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.10.4.tgz#2f55e770d3501e83af217d782cb7517d7bb34d25" + integrity sha512-oSAEz1YkBCAKr5Yiq8/BNtvSAPwkp/IyUnwZogd8p+F0RuYQQrLeRUzIQhueQTTBy/F+a40uS7OFKxnkRvmvFQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-arrow-functions@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.1.tgz#cb5ee3a36f0863c06ead0b409b4cc43a889b295b" - integrity sha512-6AZHgFJKP3DJX0eCNJj01RpytUa3SOGawIxweHkNX2L6PYikOZmoh5B0d7hIHaIgveMjX990IAa/xK7jRTN8OA== +"@babel/plugin-transform-arrow-functions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd" + integrity sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-arrow-functions@^7.8.3": version "7.8.3" @@ -926,14 +948,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-async-to-generator@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.1.tgz#e5153eb1a3e028f79194ed8a7a4bf55f862b2062" - integrity sha512-XCgYjJ8TY2slj6SReBUyamJn3k2JLUIiiR5b6t1mNCMSvv7yx+jJpaewakikp0uWFQSF7ChPPoe3dHmXLpISkg== +"@babel/plugin-transform-async-to-generator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz#41a5017e49eb6f3cda9392a51eef29405b245a37" + integrity sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ== dependencies: - "@babel/helper-module-imports" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/helper-remap-async-to-generator" "^7.10.1" + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.10.4" "@babel/plugin-transform-async-to-generator@^7.8.3": version "7.8.3" @@ -944,12 +966,12 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/helper-remap-async-to-generator" "^7.8.3" -"@babel/plugin-transform-block-scoped-functions@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.1.tgz#146856e756d54b20fff14b819456b3e01820b85d" - integrity sha512-B7K15Xp8lv0sOJrdVAoukKlxP9N59HS48V1J3U/JGj+Ad+MHq+am6xJVs85AgXrQn4LV8vaYFOB+pr/yIuzW8Q== +"@babel/plugin-transform-block-scoped-functions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz#1afa595744f75e43a91af73b0d998ecfe4ebc2e8" + integrity sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-block-scoped-functions@^7.8.3": version "7.8.3" @@ -958,13 +980,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-block-scoping@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.1.tgz#47092d89ca345811451cd0dc5d91605982705d5e" - integrity sha512-8bpWG6TtF5akdhIm/uWTyjHqENpy13Fx8chg7pFH875aNLwX8JxIxqm08gmAT+Whe6AOmaTeLPe7dpLbXt+xUw== +"@babel/plugin-transform-block-scoping@^7.10.4": + version "7.11.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz#5b7efe98852bef8d652c0b28144cd93a9e4b5215" + integrity sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - lodash "^4.17.13" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-block-scoping@^7.8.3": version "7.8.3" @@ -974,18 +995,18 @@ "@babel/helper-plugin-utils" "^7.8.3" lodash "^4.17.13" -"@babel/plugin-transform-classes@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.1.tgz#6e11dd6c4dfae70f540480a4702477ed766d733f" - integrity sha512-P9V0YIh+ln/B3RStPoXpEQ/CoAxQIhRSUn7aXqQ+FZJ2u8+oCtjIXR3+X0vsSD8zv+mb56K7wZW1XiDTDGiDRQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.1" - "@babel/helper-define-map" "^7.10.1" - "@babel/helper-function-name" "^7.10.1" - "@babel/helper-optimise-call-expression" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/helper-replace-supers" "^7.10.1" - "@babel/helper-split-export-declaration" "^7.10.1" +"@babel/plugin-transform-classes@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz#405136af2b3e218bc4a1926228bc917ab1a0adc7" + integrity sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-define-map" "^7.10.4" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" globals "^11.1.0" "@babel/plugin-transform-classes@^7.9.0": @@ -1002,12 +1023,12 @@ "@babel/helper-split-export-declaration" "^7.8.3" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.1.tgz#59aa399064429d64dce5cf76ef9b90b7245ebd07" - integrity sha512-mqSrGjp3IefMsXIenBfGcPXxJxweQe2hEIwMQvjtiDQ9b1IBvDUjkAtV/HMXX47/vXf14qDNedXsIiNd1FmkaQ== +"@babel/plugin-transform-computed-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz#9ded83a816e82ded28d52d4b4ecbdd810cdfc0eb" + integrity sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-computed-properties@^7.8.3": version "7.8.3" @@ -1016,12 +1037,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-destructuring@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.1.tgz#abd58e51337815ca3a22a336b85f62b998e71907" - integrity sha512-V/nUc4yGWG71OhaTH705pU8ZSdM6c1KmmLP8ys59oOYbT7RpMYAR3MsVOt6OHL0WzG7BlTU076va9fjJyYzJMA== +"@babel/plugin-transform-destructuring@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz#70ddd2b3d1bea83d01509e9bb25ddb3a74fc85e5" + integrity sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-destructuring@^7.8.3": version "7.8.8" @@ -1030,13 +1051,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-dotall-regex@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.1.tgz#920b9fec2d78bb57ebb64a644d5c2ba67cc104ee" - integrity sha512-19VIMsD1dp02RvduFUmfzj8uknaO3uiHHF0s3E1OHnVsNj8oge8EQ5RzHRbJjGSetRnkEuBYO7TG1M5kKjGLOA== +"@babel/plugin-transform-dotall-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz#469c2062105c1eb6a040eaf4fac4b488078395ee" + integrity sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": version "7.8.3" @@ -1046,12 +1067,12 @@ "@babel/helper-create-regexp-features-plugin" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-duplicate-keys@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.1.tgz#c900a793beb096bc9d4d0a9d0cde19518ffc83b9" - integrity sha512-wIEpkX4QvX8Mo9W6XF3EdGttrIPZWozHfEaDTU0WJD/TDnXMvdDh30mzUl/9qWhnf7naicYartcEfUghTCSNpA== +"@babel/plugin-transform-duplicate-keys@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz#697e50c9fee14380fe843d1f306b295617431e47" + integrity sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-duplicate-keys@^7.8.3": version "7.8.3" @@ -1060,13 +1081,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-exponentiation-operator@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.1.tgz#279c3116756a60dd6e6f5e488ba7957db9c59eb3" - integrity sha512-lr/przdAbpEA2BUzRvjXdEDLrArGRRPwbaF9rvayuHRvdQ7lUTTkZnhZrJ4LE2jvgMRFF4f0YuPQ20vhiPYxtA== +"@babel/plugin-transform-exponentiation-operator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz#5ae338c57f8cf4001bdb35607ae66b92d665af2e" + integrity sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-exponentiation-operator@^7.8.3": version "7.8.3" @@ -1084,12 +1105,12 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-flow" "^7.8.3" -"@babel/plugin-transform-for-of@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.1.tgz#ff01119784eb0ee32258e8646157ba2501fcfda5" - integrity sha512-US8KCuxfQcn0LwSCMWMma8M2R5mAjJGsmoCBVwlMygvmDUMkTCykc84IqN1M7t+agSfOmLYTInLCHJM+RUoz+w== +"@babel/plugin-transform-for-of@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz#c08892e8819d3a5db29031b115af511dbbfebae9" + integrity sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-for-of@^7.9.0": version "7.9.0" @@ -1098,13 +1119,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-function-name@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.1.tgz#4ed46fd6e1d8fde2a2ec7b03c66d853d2c92427d" - integrity sha512-//bsKsKFBJfGd65qSNNh1exBy5Y9gD9ZN+DvrJ8f7HXr4avE5POW6zB7Rj6VnqHV33+0vXWUwJT0wSHubiAQkw== +"@babel/plugin-transform-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz#6a467880e0fc9638514ba369111811ddbe2644b7" + integrity sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg== dependencies: - "@babel/helper-function-name" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-function-name@^7.8.3": version "7.8.3" @@ -1114,12 +1135,12 @@ "@babel/helper-function-name" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-literals@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.1.tgz#5794f8da82846b22e4e6631ea1658bce708eb46a" - integrity sha512-qi0+5qgevz1NHLZroObRm5A+8JJtibb7vdcPQF1KQE12+Y/xxl8coJ+TpPW9iRq+Mhw/NKLjm+5SHtAHCC7lAw== +"@babel/plugin-transform-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz#9f42ba0841100a135f22712d0e391c462f571f3c" + integrity sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-literals@^7.8.3": version "7.8.3" @@ -1128,12 +1149,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-member-expression-literals@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.1.tgz#90347cba31bca6f394b3f7bd95d2bbfd9fce2f39" - integrity sha512-UmaWhDokOFT2GcgU6MkHC11i0NQcL63iqeufXWfRy6pUOGYeCGEKhvfFO6Vz70UfYJYHwveg62GS83Rvpxn+NA== +"@babel/plugin-transform-member-expression-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz#b1ec44fcf195afcb8db2c62cd8e551c881baf8b7" + integrity sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-member-expression-literals@^7.8.3": version "7.8.3" @@ -1142,13 +1163,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-modules-amd@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.1.tgz#65950e8e05797ebd2fe532b96e19fc5482a1d52a" - integrity sha512-31+hnWSFRI4/ACFr1qkboBbrTxoBIzj7qA69qlq8HY8p7+YCzkCT6/TvQ1a4B0z27VeWtAeJd6pr5G04dc1iHw== +"@babel/plugin-transform-modules-amd@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz#1b9cddaf05d9e88b3aad339cb3e445c4f020a9b1" + integrity sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw== dependencies: - "@babel/helper-module-transforms" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-module-transforms" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" "@babel/plugin-transform-modules-amd@^7.9.0": @@ -1160,14 +1181,14 @@ "@babel/helper-plugin-utils" "^7.8.3" babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-modules-commonjs@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.1.tgz#d5ff4b4413ed97ffded99961056e1fb980fb9301" - integrity sha512-AQG4fc3KOah0vdITwt7Gi6hD9BtQP/8bhem7OjbaMoRNCH5Djx42O2vYMfau7QnAzQCa+RJnhJBmFFMGpQEzrg== +"@babel/plugin-transform-modules-commonjs@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz#66667c3eeda1ebf7896d41f1f16b17105a2fbca0" + integrity sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w== dependencies: - "@babel/helper-module-transforms" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/helper-simple-access" "^7.10.1" + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" "@babel/plugin-transform-modules-commonjs@^7.9.0": @@ -1180,14 +1201,14 @@ "@babel/helper-simple-access" "^7.8.3" babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-modules-systemjs@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.1.tgz#9962e4b0ac6aaf2e20431ada3d8ec72082cbffb6" - integrity sha512-ewNKcj1TQZDL3YnO85qh9zo1YF1CHgmSTlRQgHqe63oTrMI85cthKtZjAiZSsSNjPQ5NCaYo5QkbYqEw1ZBgZA== +"@babel/plugin-transform-modules-systemjs@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz#6270099c854066681bae9e05f87e1b9cadbe8c85" + integrity sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw== dependencies: - "@babel/helper-hoist-variables" "^7.10.1" - "@babel/helper-module-transforms" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-hoist-variables" "^7.10.4" + "@babel/helper-module-transforms" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" "@babel/plugin-transform-modules-systemjs@^7.9.0": @@ -1200,13 +1221,13 @@ "@babel/helper-plugin-utils" "^7.8.3" babel-plugin-dynamic-import-node "^2.3.0" -"@babel/plugin-transform-modules-umd@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.1.tgz#ea080911ffc6eb21840a5197a39ede4ee67b1595" - integrity sha512-EIuiRNMd6GB6ulcYlETnYYfgv4AxqrswghmBRQbWLHZxN4s7mupxzglnHqk9ZiUpDI4eRWewedJJNj67PWOXKA== +"@babel/plugin-transform-modules-umd@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz#9a8481fe81b824654b3a0b65da3df89f3d21839e" + integrity sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA== dependencies: - "@babel/helper-module-transforms" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-modules-umd@^7.9.0": version "7.9.0" @@ -1216,6 +1237,13 @@ "@babel/helper-module-transforms" "^7.9.0" "@babel/helper-plugin-utils" "^7.8.3" +"@babel/plugin-transform-named-capturing-groups-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz#78b4d978810b6f3bcf03f9e318f2fc0ed41aecb6" + integrity sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz#a2a72bffa202ac0e2d0506afd0939c5ecbc48c6c" @@ -1223,12 +1251,12 @@ dependencies: "@babel/helper-create-regexp-features-plugin" "^7.8.3" -"@babel/plugin-transform-new-target@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.1.tgz#6ee41a5e648da7632e22b6fb54012e87f612f324" - integrity sha512-MBlzPc1nJvbmO9rPr1fQwXOM2iGut+JC92ku6PbiJMMK7SnQc1rytgpopveE3Evn47gzvGYeCdgfCDbZo0ecUw== +"@babel/plugin-transform-new-target@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz#9097d753cb7b024cb7381a3b2e52e9513a9c6888" + integrity sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-new-target@^7.8.3": version "7.8.3" @@ -1237,13 +1265,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-object-super@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.1.tgz#2e3016b0adbf262983bf0d5121d676a5ed9c4fde" - integrity sha512-WnnStUDN5GL+wGQrJylrnnVlFhFmeArINIR9gjhSeYyvroGhBrSAXYg/RHsnfzmsa+onJrTJrEClPzgNmmQ4Gw== +"@babel/plugin-transform-object-super@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz#d7146c4d139433e7a6526f888c667e314a093894" + integrity sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/helper-replace-supers" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" "@babel/plugin-transform-object-super@^7.8.3": version "7.8.3" @@ -1253,13 +1281,13 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/helper-replace-supers" "^7.8.3" -"@babel/plugin-transform-parameters@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.1.tgz#b25938a3c5fae0354144a720b07b32766f683ddd" - integrity sha512-tJ1T0n6g4dXMsL45YsSzzSDZCxiHXAQp/qHrucOq5gEHncTA3xDxnd5+sZcoQp+N1ZbieAaB8r/VUCG0gqseOg== +"@babel/plugin-transform-parameters@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz#59d339d58d0b1950435f4043e74e2510005e2c4a" + integrity sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw== dependencies: - "@babel/helper-get-function-arity" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-parameters@^7.8.7": version "7.9.3" @@ -1269,12 +1297,12 @@ "@babel/helper-get-function-arity" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-property-literals@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.1.tgz#cffc7315219230ed81dc53e4625bf86815b6050d" - integrity sha512-Kr6+mgag8auNrgEpbfIWzdXYOvqDHZOF0+Bx2xh4H2EDNwcbRb9lY6nkZg8oSjsX+DH9Ebxm9hOqtKW+gRDeNA== +"@babel/plugin-transform-property-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz#f6fe54b6590352298785b83edd815d214c42e3c0" + integrity sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-property-literals@^7.8.3": version "7.8.3" @@ -1290,12 +1318,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-react-display-name@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.10.1.tgz#e6a33f6d48dfb213dda5e007d0c7ff82b6a3d8ef" - integrity sha512-rBjKcVwjk26H3VX8pavMxGf33LNlbocMHdSeldIEswtQ/hrjyTG8fKKILW1cSkODyRovckN/uZlGb2+sAV9JUQ== +"@babel/plugin-transform-react-display-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.10.4.tgz#b5795f4e3e3140419c3611b7a2a3832b9aef328d" + integrity sha512-Zd4X54Mu9SBfPGnEcaGcOrVAYOtjT2on8QZkLKEq1S/tHexG39d9XXGZv19VfRrDjPJzFmPfTAqOQS1pfFOujw== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-react-display-name@^7.8.3": version "7.8.3" @@ -1304,14 +1332,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-react-jsx-development@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.10.1.tgz#1ac6300d8b28ef381ee48e6fec430cc38047b7f3" - integrity sha512-XwDy/FFoCfw9wGFtdn5Z+dHh6HXKHkC6DwKNWpN74VWinUagZfDcEJc3Y8Dn5B3WMVnAllX8Kviaw7MtC5Epwg== +"@babel/plugin-transform-react-jsx-development@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.10.4.tgz#6ec90f244394604623880e15ebc3c34c356258ba" + integrity sha512-RM3ZAd1sU1iQ7rI2dhrZRZGv0aqzNQMbkIUCS1txYpi9wHQ2ZHNjo5TwX+UD6pvFW4AbWqLVYvKy5qJSAyRGjQ== dependencies: - "@babel/helper-builder-react-jsx-experimental" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-jsx" "^7.10.1" + "@babel/helper-builder-react-jsx-experimental" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" "@babel/plugin-transform-react-jsx-development@^7.9.0": version "7.9.0" @@ -1322,13 +1350,13 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-jsx" "^7.8.3" -"@babel/plugin-transform-react-jsx-self@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.10.1.tgz#22143e14388d72eb88649606bb9e46f421bc3821" - integrity sha512-4p+RBw9d1qV4S749J42ZooeQaBomFPrSxa9JONLHJ1TxCBo3TzJ79vtmG2S2erUT8PDDrPdw4ZbXGr2/1+dILA== +"@babel/plugin-transform-react-jsx-self@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.10.4.tgz#cd301a5fed8988c182ed0b9d55e9bd6db0bd9369" + integrity sha512-yOvxY2pDiVJi0axdTWHSMi5T0DILN+H+SaeJeACHKjQLezEzhLx9nEF9xgpBLPtkZsks9cnb5P9iBEi21En3gg== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-jsx" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" "@babel/plugin-transform-react-jsx-self@^7.9.0": version "7.9.0" @@ -1338,13 +1366,13 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-jsx" "^7.8.3" -"@babel/plugin-transform-react-jsx-source@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.1.tgz#30db3d4ee3cdebbb26a82a9703673714777a4273" - integrity sha512-neAbaKkoiL+LXYbGDvh6PjPG+YeA67OsZlE78u50xbWh2L1/C81uHiNP5d1fw+uqUIoiNdCC8ZB+G4Zh3hShJA== +"@babel/plugin-transform-react-jsx-source@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.5.tgz#34f1779117520a779c054f2cdd9680435b9222b4" + integrity sha512-wTeqHVkN1lfPLubRiZH3o73f4rfon42HpgxUSs86Nc+8QIcm/B9s8NNVXu/gwGcOyd7yDib9ikxoDLxJP0UiDA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-jsx" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" "@babel/plugin-transform-react-jsx-source@^7.9.0": version "7.9.0" @@ -1354,15 +1382,15 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-jsx" "^7.8.3" -"@babel/plugin-transform-react-jsx@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.10.1.tgz#91f544248ba131486decb5d9806da6a6e19a2896" - integrity sha512-MBVworWiSRBap3Vs39eHt+6pJuLUAaK4oxGc8g+wY+vuSJvLiEQjW1LSTqKb8OUPtDvHCkdPhk7d6sjC19xyFw== +"@babel/plugin-transform-react-jsx@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.10.4.tgz#673c9f913948764a4421683b2bef2936968fddf2" + integrity sha512-L+MfRhWjX0eI7Js093MM6MacKU4M6dnCRa/QPDwYMxjljzSCzzlzKzj9Pk4P3OtrPcxr2N3znR419nr3Xw+65A== dependencies: - "@babel/helper-builder-react-jsx" "^7.10.1" - "@babel/helper-builder-react-jsx-experimental" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-jsx" "^7.10.1" + "@babel/helper-builder-react-jsx" "^7.10.4" + "@babel/helper-builder-react-jsx-experimental" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" "@babel/plugin-transform-react-jsx@^7.9.4": version "7.9.4" @@ -1374,18 +1402,18 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-jsx" "^7.8.3" -"@babel/plugin-transform-react-pure-annotations@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.10.1.tgz#f5e7c755d3e7614d4c926e144f501648a5277b70" - integrity sha512-mfhoiai083AkeewsBHUpaS/FM1dmUENHBMpS/tugSJ7VXqXO5dCN1Gkint2YvM1Cdv1uhmAKt1ZOuAjceKmlLA== +"@babel/plugin-transform-react-pure-annotations@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.10.4.tgz#3eefbb73db94afbc075f097523e445354a1c6501" + integrity sha512-+njZkqcOuS8RaPakrnR9KvxjoG1ASJWpoIv/doyWngId88JoFlPlISenGXjrVacZUIALGUr6eodRs1vmPnF23A== dependencies: - "@babel/helper-annotate-as-pure" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-regenerator@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.1.tgz#10e175cbe7bdb63cc9b39f9b3f823c5c7c5c5490" - integrity sha512-B3+Y2prScgJ2Bh/2l9LJxKbb8C8kRfsG4AdPT+n7ixBHIxJaIG8bi8tgjxUMege1+WqSJ+7gu1YeoMVO3gPWzw== +"@babel/plugin-transform-regenerator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz#2015e59d839074e76838de2159db421966fd8b63" + integrity sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw== dependencies: regenerator-transform "^0.14.2" @@ -1396,12 +1424,12 @@ dependencies: regenerator-transform "^0.14.2" -"@babel/plugin-transform-reserved-words@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.1.tgz#0fc1027312b4d1c3276a57890c8ae3bcc0b64a86" - integrity sha512-qN1OMoE2nuqSPmpTqEM7OvJ1FkMEV+BjVeZZm9V9mq/x1JLKQ4pcv8riZJMNN3u2AUGl0ouOMjRr2siecvHqUQ== +"@babel/plugin-transform-reserved-words@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz#8f2682bcdcef9ed327e1b0861585d7013f8a54dd" + integrity sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-reserved-words@^7.8.3": version "7.8.3" @@ -1410,22 +1438,22 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-runtime@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.10.1.tgz#fd1887f749637fb2ed86dc278e79eb41df37f4b1" - integrity sha512-4w2tcglDVEwXJ5qxsY++DgWQdNJcCCsPxfT34wCUwIf2E7dI7pMpH8JczkMBbgBTNzBX62SZlNJ9H+De6Zebaw== +"@babel/plugin-transform-runtime@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.11.0.tgz#e27f78eb36f19448636e05c33c90fd9ad9b8bccf" + integrity sha512-LFEsP+t3wkYBlis8w6/kmnd6Kb1dxTd+wGJ8MlxTGzQo//ehtqlVL4S9DNUa53+dtPSQobN2CXx4d81FqC58cw== dependencies: - "@babel/helper-module-imports" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" resolve "^1.8.1" semver "^5.5.1" -"@babel/plugin-transform-shorthand-properties@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.1.tgz#e8b54f238a1ccbae482c4dce946180ae7b3143f3" - integrity sha512-AR0E/lZMfLstScFwztApGeyTHJ5u3JUKMjneqRItWeEqDdHWZwAOKycvQNCasCK/3r5YXsuNG25funcJDu7Y2g== +"@babel/plugin-transform-shorthand-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz#9fd25ec5cdd555bb7f473e5e6ee1c971eede4dd6" + integrity sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-shorthand-properties@^7.8.3": version "7.8.3" @@ -1434,12 +1462,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-spread@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.10.1.tgz#0c6d618a0c4461a274418460a28c9ccf5239a7c8" - integrity sha512-8wTPym6edIrClW8FI2IoaePB91ETOtg36dOkj3bYcNe7aDMN2FXEoUa+WrmPc4xa1u2PQK46fUX2aCb+zo9rfw== +"@babel/plugin-transform-spread@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz#fa84d300f5e4f57752fe41a6d1b3c554f13f17cc" + integrity sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" "@babel/plugin-transform-spread@^7.8.3": version "7.8.3" @@ -1448,13 +1477,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-sticky-regex@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.1.tgz#90fc89b7526228bed9842cff3588270a7a393b00" - integrity sha512-j17ojftKjrL7ufX8ajKvwRilwqTok4q+BjkknmQw9VNHnItTyMP5anPFzxFJdCQs7clLcWpCV3ma+6qZWLnGMA== +"@babel/plugin-transform-sticky-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz#8f3889ee8657581130a29d9cc91d7c73b7c4a28d" + integrity sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/helper-regex" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-regex" "^7.10.4" "@babel/plugin-transform-sticky-regex@^7.8.3": version "7.8.3" @@ -1464,13 +1493,13 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/helper-regex" "^7.8.3" -"@babel/plugin-transform-template-literals@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.1.tgz#914c7b7f4752c570ea00553b4284dad8070e8628" - integrity sha512-t7B/3MQf5M1T9hPCRG28DNGZUuxAuDqLYS03rJrIk2prj/UV7Z6FOneijhQhnv/Xa039vidXeVbvjK2SK5f7Gg== +"@babel/plugin-transform-template-literals@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz#78bc5d626a6642db3312d9d0f001f5e7639fde8c" + integrity sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw== dependencies: - "@babel/helper-annotate-as-pure" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-template-literals@^7.8.3": version "7.8.3" @@ -1480,12 +1509,12 @@ "@babel/helper-annotate-as-pure" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-typeof-symbol@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.1.tgz#60c0239b69965d166b80a84de7315c1bc7e0bb0e" - integrity sha512-qX8KZcmbvA23zDi+lk9s6hC1FM7jgLHYIjuLgULgc8QtYnmB3tAVIYkNoKRQ75qWBeyzcoMoK8ZQmogGtC/w0g== +"@babel/plugin-transform-typeof-symbol@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz#9509f1a7eec31c4edbffe137c16cc33ff0bc5bfc" + integrity sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-typeof-symbol@^7.8.4": version "7.8.4" @@ -1494,29 +1523,29 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-typescript@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.10.1.tgz#2c54daea231f602468686d9faa76f182a94507a6" - integrity sha512-v+QWKlmCnsaimLeqq9vyCsVRMViZG1k2SZTlcZvB+TqyH570Zsij8nvVUZzOASCRiQFUxkLrn9Wg/kH0zgy5OQ== +"@babel/plugin-transform-typescript@^7.10.4": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.11.0.tgz#2b4879676af37342ebb278216dd090ac67f13abb" + integrity sha512-edJsNzTtvb3MaXQwj8403B7mZoGu9ElDJQZOKjGUnvilquxBA3IQoEIOvkX/1O8xfAsnHS/oQhe2w/IXrr+w0w== dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-syntax-typescript" "^7.10.1" + "@babel/helper-create-class-features-plugin" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-typescript" "^7.10.4" -"@babel/plugin-transform-unicode-escapes@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.1.tgz#add0f8483dab60570d9e03cecef6c023aa8c9940" - integrity sha512-zZ0Poh/yy1d4jeDWpx/mNwbKJVwUYJX73q+gyh4bwtG0/iUlzdEu0sLMda8yuDFS6LBQlT/ST1SJAR6zYwXWgw== +"@babel/plugin-transform-unicode-escapes@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz#feae523391c7651ddac115dae0a9d06857892007" + integrity sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-unicode-regex@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.1.tgz#6b58f2aea7b68df37ac5025d9c88752443a6b43f" - integrity sha512-Y/2a2W299k0VIUdbqYm9X2qS6fE0CUBhhiPpimK6byy7OJ/kORLlIX+J6UrjgNu5awvs62k+6RSslxhcvVw2Tw== +"@babel/plugin-transform-unicode-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz#e56d71f9282fac6db09c82742055576d5e6d80a8" + integrity sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-unicode-regex@^7.8.3": version "7.8.3" @@ -1592,70 +1621,74 @@ levenary "^1.1.1" semver "^5.5.0" -"@babel/preset-env@^7.10.2": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.10.2.tgz#715930f2cf8573b0928005ee562bed52fb65fdfb" - integrity sha512-MjqhX0RZaEgK/KueRzh+3yPSk30oqDKJ5HP5tqTSB1e2gzGS3PLy7K0BIpnp78+0anFuSwOeuCf1zZO7RzRvEA== - dependencies: - "@babel/compat-data" "^7.10.1" - "@babel/helper-compilation-targets" "^7.10.2" - "@babel/helper-module-imports" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-proposal-async-generator-functions" "^7.10.1" - "@babel/plugin-proposal-class-properties" "^7.10.1" - "@babel/plugin-proposal-dynamic-import" "^7.10.1" - "@babel/plugin-proposal-json-strings" "^7.10.1" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.10.1" - "@babel/plugin-proposal-numeric-separator" "^7.10.1" - "@babel/plugin-proposal-object-rest-spread" "^7.10.1" - "@babel/plugin-proposal-optional-catch-binding" "^7.10.1" - "@babel/plugin-proposal-optional-chaining" "^7.10.1" - "@babel/plugin-proposal-private-methods" "^7.10.1" - "@babel/plugin-proposal-unicode-property-regex" "^7.10.1" +"@babel/preset-env@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.11.0.tgz#860ee38f2ce17ad60480c2021ba9689393efb796" + integrity sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg== + dependencies: + "@babel/compat-data" "^7.11.0" + "@babel/helper-compilation-targets" "^7.10.4" + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-proposal-async-generator-functions" "^7.10.4" + "@babel/plugin-proposal-class-properties" "^7.10.4" + "@babel/plugin-proposal-dynamic-import" "^7.10.4" + "@babel/plugin-proposal-export-namespace-from" "^7.10.4" + "@babel/plugin-proposal-json-strings" "^7.10.4" + "@babel/plugin-proposal-logical-assignment-operators" "^7.11.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.10.4" + "@babel/plugin-proposal-numeric-separator" "^7.10.4" + "@babel/plugin-proposal-object-rest-spread" "^7.11.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.10.4" + "@babel/plugin-proposal-optional-chaining" "^7.11.0" + "@babel/plugin-proposal-private-methods" "^7.10.4" + "@babel/plugin-proposal-unicode-property-regex" "^7.10.4" "@babel/plugin-syntax-async-generators" "^7.8.0" - "@babel/plugin-syntax-class-properties" "^7.10.1" + "@babel/plugin-syntax-class-properties" "^7.10.4" "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - "@babel/plugin-syntax-numeric-separator" "^7.10.1" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" "@babel/plugin-syntax-optional-chaining" "^7.8.0" - "@babel/plugin-syntax-top-level-await" "^7.10.1" - "@babel/plugin-transform-arrow-functions" "^7.10.1" - "@babel/plugin-transform-async-to-generator" "^7.10.1" - "@babel/plugin-transform-block-scoped-functions" "^7.10.1" - "@babel/plugin-transform-block-scoping" "^7.10.1" - "@babel/plugin-transform-classes" "^7.10.1" - "@babel/plugin-transform-computed-properties" "^7.10.1" - "@babel/plugin-transform-destructuring" "^7.10.1" - "@babel/plugin-transform-dotall-regex" "^7.10.1" - "@babel/plugin-transform-duplicate-keys" "^7.10.1" - "@babel/plugin-transform-exponentiation-operator" "^7.10.1" - "@babel/plugin-transform-for-of" "^7.10.1" - "@babel/plugin-transform-function-name" "^7.10.1" - "@babel/plugin-transform-literals" "^7.10.1" - "@babel/plugin-transform-member-expression-literals" "^7.10.1" - "@babel/plugin-transform-modules-amd" "^7.10.1" - "@babel/plugin-transform-modules-commonjs" "^7.10.1" - "@babel/plugin-transform-modules-systemjs" "^7.10.1" - "@babel/plugin-transform-modules-umd" "^7.10.1" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" - "@babel/plugin-transform-new-target" "^7.10.1" - "@babel/plugin-transform-object-super" "^7.10.1" - "@babel/plugin-transform-parameters" "^7.10.1" - "@babel/plugin-transform-property-literals" "^7.10.1" - "@babel/plugin-transform-regenerator" "^7.10.1" - "@babel/plugin-transform-reserved-words" "^7.10.1" - "@babel/plugin-transform-shorthand-properties" "^7.10.1" - "@babel/plugin-transform-spread" "^7.10.1" - "@babel/plugin-transform-sticky-regex" "^7.10.1" - "@babel/plugin-transform-template-literals" "^7.10.1" - "@babel/plugin-transform-typeof-symbol" "^7.10.1" - "@babel/plugin-transform-unicode-escapes" "^7.10.1" - "@babel/plugin-transform-unicode-regex" "^7.10.1" + "@babel/plugin-syntax-top-level-await" "^7.10.4" + "@babel/plugin-transform-arrow-functions" "^7.10.4" + "@babel/plugin-transform-async-to-generator" "^7.10.4" + "@babel/plugin-transform-block-scoped-functions" "^7.10.4" + "@babel/plugin-transform-block-scoping" "^7.10.4" + "@babel/plugin-transform-classes" "^7.10.4" + "@babel/plugin-transform-computed-properties" "^7.10.4" + "@babel/plugin-transform-destructuring" "^7.10.4" + "@babel/plugin-transform-dotall-regex" "^7.10.4" + "@babel/plugin-transform-duplicate-keys" "^7.10.4" + "@babel/plugin-transform-exponentiation-operator" "^7.10.4" + "@babel/plugin-transform-for-of" "^7.10.4" + "@babel/plugin-transform-function-name" "^7.10.4" + "@babel/plugin-transform-literals" "^7.10.4" + "@babel/plugin-transform-member-expression-literals" "^7.10.4" + "@babel/plugin-transform-modules-amd" "^7.10.4" + "@babel/plugin-transform-modules-commonjs" "^7.10.4" + "@babel/plugin-transform-modules-systemjs" "^7.10.4" + "@babel/plugin-transform-modules-umd" "^7.10.4" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.10.4" + "@babel/plugin-transform-new-target" "^7.10.4" + "@babel/plugin-transform-object-super" "^7.10.4" + "@babel/plugin-transform-parameters" "^7.10.4" + "@babel/plugin-transform-property-literals" "^7.10.4" + "@babel/plugin-transform-regenerator" "^7.10.4" + "@babel/plugin-transform-reserved-words" "^7.10.4" + "@babel/plugin-transform-shorthand-properties" "^7.10.4" + "@babel/plugin-transform-spread" "^7.11.0" + "@babel/plugin-transform-sticky-regex" "^7.10.4" + "@babel/plugin-transform-template-literals" "^7.10.4" + "@babel/plugin-transform-typeof-symbol" "^7.10.4" + "@babel/plugin-transform-unicode-escapes" "^7.10.4" + "@babel/plugin-transform-unicode-regex" "^7.10.4" "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.10.2" + "@babel/types" "^7.11.0" browserslist "^4.12.0" core-js-compat "^3.6.2" invariant "^2.2.2" @@ -1693,34 +1726,34 @@ "@babel/plugin-transform-react-jsx-self" "^7.9.0" "@babel/plugin-transform-react-jsx-source" "^7.9.0" -"@babel/preset-react@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.10.1.tgz#e2ab8ae9a363ec307b936589f07ed753192de041" - integrity sha512-Rw0SxQ7VKhObmFjD/cUcKhPTtzpeviEFX1E6PgP+cYOhQ98icNqtINNFANlsdbQHrmeWnqdxA4Tmnl1jy5tp3Q== +"@babel/preset-react@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.10.4.tgz#92e8a66d816f9911d11d4cc935be67adfc82dbcf" + integrity sha512-BrHp4TgOIy4M19JAfO1LhycVXOPWdDbTRep7eVyatf174Hff+6Uk53sDyajqZPu8W1qXRBiYOfIamek6jA7YVw== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-transform-react-display-name" "^7.10.1" - "@babel/plugin-transform-react-jsx" "^7.10.1" - "@babel/plugin-transform-react-jsx-development" "^7.10.1" - "@babel/plugin-transform-react-jsx-self" "^7.10.1" - "@babel/plugin-transform-react-jsx-source" "^7.10.1" - "@babel/plugin-transform-react-pure-annotations" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-react-display-name" "^7.10.4" + "@babel/plugin-transform-react-jsx" "^7.10.4" + "@babel/plugin-transform-react-jsx-development" "^7.10.4" + "@babel/plugin-transform-react-jsx-self" "^7.10.4" + "@babel/plugin-transform-react-jsx-source" "^7.10.4" + "@babel/plugin-transform-react-pure-annotations" "^7.10.4" -"@babel/preset-typescript@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.10.1.tgz#a8d8d9035f55b7d99a2461a0bdc506582914d07e" - integrity sha512-m6GV3y1ShiqxnyQj10600ZVOFrSSAa8HQ3qIUk2r+gcGtHTIRw0dJnFLt1WNXpKjtVw7yw1DAPU/6ma2ZvgJuA== +"@babel/preset-typescript@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.10.4.tgz#7d5d052e52a682480d6e2cc5aa31be61c8c25e36" + integrity sha512-SdYnvGPv+bLlwkF2VkJnaX/ni1sMNetcGI1+nThF1gyv6Ph8Qucc4ZZAjM5yZcE/AKRXIOTZz7eSRDWOEjPyRQ== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/plugin-transform-typescript" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-typescript" "^7.10.4" -"@babel/register@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.10.1.tgz#b6567c5cb5049f44bbf8c35d6ff68ca3c43238ed" - integrity sha512-sl96+kB3IA2B9EzpwwBmYadOT14vw3KaXOknGDbJaZCOj52GDA4Tivudq9doCJcB+bEIKCEARZYwRgBBsCGXyg== +"@babel/register@^7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.10.5.tgz#354f3574895f1307f79efe37a51525e52fd38d89" + integrity sha512-eYHdLv43nyvmPn9bfNfrcC4+iYNwdQ8Pxk1MFJuU/U5LpSYl/PH4dFMazCYZDFVi8ueG3shvO+AQfLrxpYulQw== dependencies: find-cache-dir "^2.0.0" - lodash "^4.17.13" + lodash "^4.17.19" make-dir "^2.1.0" pirates "^4.0.0" source-map-support "^0.5.16" @@ -1747,10 +1780,10 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.10.2": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.2.tgz#d103f21f2602497d38348a32e008637d506db839" - integrity sha512-6sF3uQw2ivImfVIl62RZ7MXhO2tap69WeWK57vAaimT6AZbE4FbqjdEJIN1UqoD6wI6B+1n9UiagafH1sxjOtg== +"@babel/runtime@^7.11.2": + version "7.11.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736" + integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw== dependencies: regenerator-runtime "^0.13.4" @@ -1775,14 +1808,14 @@ "@babel/parser" "^7.8.6" "@babel/types" "^7.8.6" -"@babel/template@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.1.tgz#e167154a94cb5f14b28dc58f5356d2162f539811" - integrity sha512-OQDg6SqvFSsc9A0ej6SKINWrpJiNonRIniYondK2ViKhB06i3c0s+76XUft71iqBEe9S1OKsHwPAjfHnuvnCig== +"@babel/template@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" + integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== dependencies: - "@babel/code-frame" "^7.10.1" - "@babel/parser" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.6", "@babel/traverse@^7.4.5", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0": version "7.9.0" @@ -1799,20 +1832,20 @@ globals "^11.1.0" lodash "^4.17.13" -"@babel/traverse@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.1.tgz#bbcef3031e4152a6c0b50147f4958df54ca0dd27" - integrity sha512-C/cTuXeKt85K+p08jN6vMDz8vSV0vZcI0wmQ36o6mjbuo++kPMdpOYw23W2XH04dbRt9/nMEfA4W3eR21CD+TQ== - dependencies: - "@babel/code-frame" "^7.10.1" - "@babel/generator" "^7.10.1" - "@babel/helper-function-name" "^7.10.1" - "@babel/helper-split-export-declaration" "^7.10.1" - "@babel/parser" "^7.10.1" - "@babel/types" "^7.10.1" +"@babel/traverse@^7.10.4", "@babel/traverse@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.0.tgz#9b996ce1b98f53f7c3e4175115605d56ed07dd24" + integrity sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.0" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/parser" "^7.11.0" + "@babel/types" "^7.11.0" debug "^4.1.0" globals "^11.1.0" - lodash "^4.17.13" + lodash "^4.17.19" "@babel/traverse@^7.7.4": version "7.9.5" @@ -1838,13 +1871,13 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@babel/types@^7.10.1", "@babel/types@^7.10.2": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.2.tgz#30283be31cad0dbf6fb00bd40641ca0ea675172d" - integrity sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng== +"@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d" + integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA== dependencies: - "@babel/helper-validator-identifier" "^7.10.1" - lodash "^4.17.13" + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" to-fast-properties "^2.0.0" "@babel/types@^7.3.3": @@ -1943,29 +1976,29 @@ enabled "2.0.x" kuler "^2.0.0" -"@elastic/apm-rum-core@^5.3.0": - version "5.3.0" - resolved "https://registry.yarnpkg.com/@elastic/apm-rum-core/-/apm-rum-core-5.3.0.tgz#3ae5e84eba5b5287b92458a49755f6e39e7bba5b" - integrity sha512-b/qAnPqi3km808BhSYo+ROpTINm3eVBQ6hNcxOELwKitS3O/HikkwRn5aPkVIhQXOVrbPSufMl1A991nrE3daA== +"@elastic/apm-rum-core@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@elastic/apm-rum-core/-/apm-rum-core-5.5.0.tgz#e05ffd87b95420c788ed3be7cfbbbce1ff54bcf5" + integrity sha512-fPx65oZD495WdHQ3YA8TnzqmjqlvSxoXm0tZqXQKzKVv7CMsNkolnEPSAXFl0W5pmAVRvw6T+vMmxcVIGsCD4Q== dependencies: error-stack-parser "^1.3.5" opentracing "^0.14.3" promise-polyfill "^8.1.3" -"@elastic/apm-rum-react@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@elastic/apm-rum-react/-/apm-rum-react-1.1.2.tgz#274cc414074d05e33e8f0afcad25ef9a30d99452" - integrity sha512-2/wEaPF4EQaVzU8Qj5aYucDc+VFr7438AieON31fx8wsbvnxh9iG+iV7xky2YtT/mf53BbFgZm35L5y/pxCKwA== +"@elastic/apm-rum-react@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@elastic/apm-rum-react/-/apm-rum-react-1.2.2.tgz#b92f1491bae62de0b4296264afe73171f17af022" + integrity sha512-KXM2qxG4p1GeDoud9jpmUA19uuQxW4M+CgtrNIXuNwITMIw46qRLyl5zOIvy9dqHodvLIvZ7RWsFtSZH4kZnAQ== dependencies: - "@elastic/apm-rum" "^5.2.0" + "@elastic/apm-rum" "^5.4.0" hoist-non-react-statics "^3.3.0" -"@elastic/apm-rum@^5.2.0": - version "5.2.0" - resolved "https://registry.yarnpkg.com/@elastic/apm-rum/-/apm-rum-5.2.0.tgz#b0cfd6e5771b1e765fda2715a38c87746f49f1aa" - integrity sha512-l8/Ji1GMuahMCN5DsALIf+fioKi1QeY4pU0izfVI37se2/fxsMNEDpw52WxJknHdfBE0Imh3FPg4T56J5MO+IQ== +"@elastic/apm-rum@^5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@elastic/apm-rum/-/apm-rum-5.4.0.tgz#2d87d5ca19f7f4a021c03f075d9d767894e88b3c" + integrity sha512-X4uaJlM28pyDOsD06serggspbTyz7Za0zFr+OWUntI6tQKu++Tn8yGsr6L2WuXhKNGhyJmrAfh13pmy9ZGyFcg== dependencies: - "@elastic/apm-rum-core" "^5.3.0" + "@elastic/apm-rum-core" "^5.5.0" "@elastic/charts@19.8.1": version "19.8.1" @@ -4306,11 +4339,6 @@ resolved "https://registry.yarnpkg.com/@types/boom/-/boom-7.2.0.tgz#19c36cbb5811a7493f0f2e37f31d42b28df1abc1" integrity sha512-HonbGsHFbskh9zRAzA6tabcw18mCOsSEOL2ibGAuVqk6e7nElcRmWO5L4UfIHpDbWBWw+eZYFdsQ1+MEGgpcVA== -"@types/browserslist-useragent@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/browserslist-useragent/-/browserslist-useragent-3.0.0.tgz#d425c9818182ce71ce53866798cee9c7d41d6e53" - integrity sha512-ZBvKzg3yyWNYEkwxAzdmUzp27sFvw+1m080/+2lwrt+eltNefn1f4fnpMyrjOla31p8zLleCYqQXw+3EETfn0w== - "@types/cacheable-request@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.1.tgz#5d22f3dded1fd3a84c0bbeb5039a7419c2c91976" @@ -6256,10 +6284,10 @@ adjust-sourcemap-loader@2.0.0: object-path "0.11.4" regex-parser "2.2.10" -adm-zip@0.4.11: - version "0.4.11" - resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.11.tgz#2aa54c84c4b01a9d0fb89bb11982a51f13e3d62a" - integrity sha512-L8vcjDTCOIJk7wFvmlEUN7AsSb8T+2JrdP7KINBjzr24TJ5Mwj590sLu3BC7zNZowvJWa/JtPmD8eJCzdtDWjA== +adm-zip@0.4.16: + version "0.4.16" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" + integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== after-all-results@^2.0.0: version "2.0.0" @@ -6438,10 +6466,10 @@ ammo@3.x.x: dependencies: hoek "5.x.x" -angular-aria@^1.7.9: - version "1.7.9" - resolved "https://registry.yarnpkg.com/angular-aria/-/angular-aria-1.7.9.tgz#90c61895ffbd876e95915222b32a7bd0070af7e3" - integrity sha512-luI3Jemd1AbOQW0krdzfEG3fM0IFtLY0bSSqIDEx3POE0XjKIC1MkrO8Csyq9PPgueLphyAPofzUwZ8YeZ88SA== +angular-aria@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/angular-aria/-/angular-aria-1.8.0.tgz#97aec9b1e8bafd07d5fab30f98d8ec832e18e25d" + integrity sha512-eCQI6EwgY6bYHdzIUfDABHnZjoZ3bNYpCsnceQF4bLfbq1QtZ7raRPNca45sj6C9Pfjde6PNcEDvuLozFPYnrQ== angular-elastic@^2.5.1: version "2.5.1" @@ -6460,20 +6488,20 @@ angular-recursion@^1.0.5: resolved "https://registry.yarnpkg.com/angular-recursion/-/angular-recursion-1.0.5.tgz#cd405428a0bf55faf52eaa7988c1fe69cd930543" integrity sha1-zUBUKKC/Vfr1Lqp5iMH+ac2TBUM= -angular-resource@1.7.9: - version "1.7.9" - resolved "https://registry.yarnpkg.com/angular-resource/-/angular-resource-1.7.9.tgz#fa53623fae2c60debe2410d692447dcb0ba02396" - integrity sha512-rXXhCE2qT31Pn4Sl+2XL+ntv4zxnA2OzY+clCl8/pOp/s/gIzxpQlEtXipo3QK8Qur3glbIkeF/bJw+gjVAdUw== +angular-resource@1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/angular-resource/-/angular-resource-1.8.0.tgz#578ef122e7cb7bcc6c0ad6c2451dc3d27fd570ba" + integrity sha512-9woUq3kDwoT7R6SjKX8vaJMhOplYBm9sqRAxKgDhDIdPyA8iBowqQIusf9+8Q+z/HlXb8ZXvKspJyKXrxmKdvg== -angular-route@^1.7.9: - version "1.7.9" - resolved "https://registry.yarnpkg.com/angular-route/-/angular-route-1.7.9.tgz#f9910a2af0ba3ad7a969c5dd369b8360d0d5e4ef" - integrity sha512-vRoj5hzdQtWbODhWJqDzD1iNOEfCKshO6GFBuPVV7RHlPjzIc4R2dHCc7Qiv/8F3LDxJDohc6vSnTDMLHuaqeA== +angular-route@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/angular-route/-/angular-route-1.8.0.tgz#cb8066c5d34284ffd6a15ac7be1b3d51c5ad7bb2" + integrity sha512-ORvXAdVfCCA6XFwyjSkVQFFGufj0mNGiCvBR93Qsii8+7t/6Ioy6wheUoCj1x4NWUv7hAq3nYYGCVO6QEKb1BQ== -angular-sanitize@1.7.9, angular-sanitize@^1.7.9: - version "1.7.9" - resolved "https://registry.yarnpkg.com/angular-sanitize/-/angular-sanitize-1.7.9.tgz#6b4d5e826abdabd352b13a7c65c8c74daf6a7b15" - integrity sha512-nB/xe7JQWF9nLvhHommAICQ3eWrfRETo0EVGFESi952CDzDa+GAJ/2BFBNw44QqQPxj1Xua/uYKrbLsOGWZdbQ== +angular-sanitize@1.8.0, angular-sanitize@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/angular-sanitize/-/angular-sanitize-1.8.0.tgz#9f80782d3afeec3bcc0bb92b3ca6f1f421cfbca6" + integrity sha512-j5GiOPCvfcDWK5svEOVoPb11X3UDVy/mdHPRWuy14Iyw86xaq+Bb+x/em2sAOa5MQQeY5ciLXbF3RRp8iCKcNg== angular-sortable-view@^0.0.17: version "0.0.17" @@ -6485,10 +6513,10 @@ angular-ui-ace@0.2.3: resolved "https://registry.yarnpkg.com/angular-ui-ace/-/angular-ui-ace-0.2.3.tgz#3cb903428100621a367fc7f641440e97a42a26d0" integrity sha1-PLkDQoEAYho2f8f2QUQOl6QqJtA= -angular@>=1.0.6, angular@^1.7.9: - version "1.7.9" - resolved "https://registry.yarnpkg.com/angular/-/angular-1.7.9.tgz#e52616e8701c17724c3c238cfe4f9446fd570bc4" - integrity sha512-5se7ZpcOtu0MBFlzGv5dsM1quQDoDeUTwZrWjGtTNA7O88cD8TEk5IEKCTDa3uECV9XnvKREVUr7du1ACiWGFQ== +angular@>=1.0.6, angular@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/angular/-/angular-1.8.0.tgz#b1ec179887869215cab6dfd0df2e42caa65b1b51" + integrity sha512-VdaMx+Qk0Skla7B5gw77a8hzlcOakwF8mjlW13DpIWIDlfqwAbSSLfd8N/qZnzEmQF4jC4iofInd3gE7vL8ZZg== ansi-align@^2.0.0: version "2.0.0" @@ -8267,11 +8295,6 @@ bluebird-retry@^0.11.0: resolved "https://registry.yarnpkg.com/bluebird-retry/-/bluebird-retry-0.11.0.tgz#1289ab22cbbc3a02587baad35595351dd0c1c047" integrity sha1-EomrIsu8OgJYe6rTVZU1HdDBwEc= -bluebird@3.4.6: - version "3.4.6" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.6.tgz#01da8d821d87813d158967e743d5fe6c62cf8c0f" - integrity sha1-AdqNgh2HgT0ViWfnQ9X+bGLPjA8= - bluebird@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" @@ -8601,15 +8624,6 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist-useragent@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/browserslist-useragent/-/browserslist-useragent-3.0.2.tgz#f0e209b2742baa5de0e451b52e678e8b4402617c" - integrity sha512-/UPzK9xZnk5mwwWx4wcuBKAKx/mD3MNY8sUuZ2NPqnr4RVFWZogX+8mOP0cQEYo8j78sHk0hiDNaVXZ1U3hM9A== - dependencies: - browserslist "^4.6.6" - semver "^6.3.0" - useragent "^2.3.0" - browserslist@4.6.6: version "4.6.6" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.6.6.tgz#6e4bf467cde520bc9dbdf3747dafa03531cec453" @@ -8629,7 +8643,7 @@ browserslist@^4.12.0: node-releases "^1.1.53" pkg-up "^2.0.0" -browserslist@^4.6.6, browserslist@^4.8.3: +browserslist@^4.8.3: version "4.8.5" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.5.tgz#691af4e327ac877b25e7a3f7ee869c4ef36cdea3" integrity sha512-4LMHuicxkabIB+n9874jZX/az1IaZ5a+EUuvD7KFOu9x/Bd5YHyO0DIz2ls/Kl8g0ItS4X/ilEgf4T1Br0lgSg== @@ -12376,10 +12390,10 @@ ejs@^3.0.1: resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.0.2.tgz#745b01cdcfe38c1c6a2da3bbb2d9957060a31226" integrity sha512-IncmUpn1yN84hy2shb0POJ80FWrfGNY0cxO9f4v+/sG7qcBvAtVWUA1IdzY/8EYUmOVhoKJVdJjNd3AZcnxOjA== -elastic-apm-http-client@^9.3.0: - version "9.3.0" - resolved "https://registry.yarnpkg.com/elastic-apm-http-client/-/elastic-apm-http-client-9.3.0.tgz#fcbb3b4f2af209dc304ac496438d381ef19b9b44" - integrity sha512-vxySk7S1oPN7uPcjv0+GLs3Y1cmN7WDVTEHBJixEDg+L6DJMysgxIGst+32Nc0ZmeU5NIjV/Ds9b+6S/yXRdIQ== +elastic-apm-http-client@^9.4.0: + version "9.4.0" + resolved "https://registry.yarnpkg.com/elastic-apm-http-client/-/elastic-apm-http-client-9.4.0.tgz#1c985923369f0c511b94d5c20f6d13aef588cb55" + integrity sha512-/jOZDyfzLNwHrNkPAI+AspLg0TXYXODWT+I1eoAWRCB7gP1vKvzUQAsP5iChodVqCbAj1eUNXB0KrvM6b07Thw== dependencies: breadth-filter "^2.0.0" container-info "^1.0.1" @@ -12391,10 +12405,10 @@ elastic-apm-http-client@^9.3.0: stream-chopper "^3.0.1" unicode-byte-truncate "^1.0.0" -elastic-apm-node@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/elastic-apm-node/-/elastic-apm-node-3.6.0.tgz#675980951fbf2fc5606d5a95a8d0b097609ac6eb" - integrity sha512-T1BlWlQ3kYPIjcGaGIszaVYbsiP9aMr8V5gFxzkI7LjY9XelahOnC3u8Mmd6TWLh/QyakDcdt8J6VL3bMuR3WA== +elastic-apm-node@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/elastic-apm-node/-/elastic-apm-node-3.7.0.tgz#168f0cfce8d93b5ebc82f387b158fa0924de9d7a" + integrity sha512-ZH3Xru6eLbUyfuNe+EnTOcKlm0B+MKduu1lCXXwEM8CDfDceW1Ks9FtmTaTeZHZW4nMacieGZMpxETrceoVk/A== dependencies: after-all-results "^2.0.0" async-value-promise "^1.1.1" @@ -12402,7 +12416,7 @@ elastic-apm-node@^3.6.0: console-log-level "^1.4.1" cookie "^0.4.0" core-util-is "^1.0.2" - elastic-apm-http-client "^9.3.0" + elastic-apm-http-client "^9.4.0" end-of-stream "^1.4.4" error-stack-parser "^2.0.6" fast-safe-stringify "^2.0.7" @@ -14881,16 +14895,16 @@ gaze@^1.0.0, gaze@^1.1.0: dependencies: globule "^1.0.0" -geckodriver@^1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/geckodriver/-/geckodriver-1.19.0.tgz#b2b07e343c2e409ce645e65fe88132bd34fa400a" - integrity sha512-Zq98rXKjvB+NCfzKlJGkQkFAO8zvmUSNqYEIxUwlF1qxmv4taRwwBbEfDa6Dj7Auf7C0p+ZZZmIA8KmlL1cfsw== +geckodriver@^1.20.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/geckodriver/-/geckodriver-1.20.0.tgz#cd16edb177b88e31affcb54b18a238cae88950a7" + integrity sha512-5nVF4ixR+ZGhVsc4udnVihA9RmSlO6guPV1d2HqxYsgAOUNh0HfzxbzG7E49w4ilXq/CSu87x9yWvrsOstrADQ== dependencies: - adm-zip "0.4.11" - bluebird "3.4.6" + adm-zip "0.4.16" + bluebird "3.7.2" got "5.6.0" - https-proxy-agent "2.2.1" - tar "4.4.2" + https-proxy-agent "5.0.0" + tar "6.0.2" generate-function@^2.0.0: version "2.3.1" @@ -16797,7 +16811,15 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= -https-proxy-agent@2.2.1, https-proxy-agent@^2.2.1: +https-proxy-agent@5.0.0, https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + +https-proxy-agent@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0" integrity sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ== @@ -16821,14 +16843,6 @@ https-proxy-agent@^4.0.0: agent-base "5" debug "4" -https-proxy-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" - integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== - dependencies: - agent-base "6" - debug "4" - human-signals@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" @@ -20344,7 +20358,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@4.17.11, lodash@4.17.19, lodash@>4.17.4, lodash@^4, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.10.0, lodash@^4.11.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.16, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@~4.17.10, lodash@~4.17.15, lodash@~4.17.5: +lodash@4.17.11, lodash@4.17.19, lodash@>4.17.4, lodash@^4, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.10.0, lodash@^4.11.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.16, lodash@^4.17.19, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@~4.17.10, lodash@~4.17.15, lodash@~4.17.5: version "4.17.19" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== @@ -21296,7 +21310,7 @@ minipass-pipeline@^1.2.2: dependencies: minipass "^3.0.0" -minipass@^2.2.1, minipass@^2.2.4, minipass@^2.8.6, minipass@^2.9.0: +minipass@^2.2.1, minipass@^2.8.6, minipass@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== @@ -21311,7 +21325,7 @@ minipass@^3.0.0, minipass@^3.1.1: dependencies: yallist "^4.0.0" -minizlib@^1.1.0, minizlib@^1.2.1: +minizlib@^1.2.1: version "1.3.3" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== @@ -29161,29 +29175,7 @@ tar@4.4.13, tar@^4: safe-buffer "^5.1.2" yallist "^3.0.3" -tar@4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.2.tgz#60685211ba46b38847b1ae7ee1a24d744a2cd462" - integrity sha512-BfkE9CciGGgDsATqkikUHrQrraBCO+ke/1f6SFAEMnxyyfN9lxC+nW1NFWMpqH865DhHIy9vQi682gk1X7friw== - dependencies: - chownr "^1.0.1" - fs-minipass "^1.2.5" - minipass "^2.2.4" - minizlib "^1.1.0" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.2" - -tar@^2.0.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40" - integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA== - dependencies: - block-stream "*" - fstream "^1.0.12" - inherits "2" - -tar@^6.0.1, tar@^6.0.2: +tar@6.0.2, tar@^6.0.1, tar@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.2.tgz#5df17813468a6264ff14f766886c622b84ae2f39" integrity sha512-Glo3jkRtPcvpDlAs/0+hozav78yoXKFr+c4wgw62NNMO3oo4AaJdCo21Uu7lcwr55h39W2XD1LMERc64wtbItg== @@ -29195,6 +29187,15 @@ tar@^6.0.1, tar@^6.0.2: mkdirp "^1.0.3" yallist "^4.0.0" +tar@^2.0.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40" + integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA== + dependencies: + block-stream "*" + fstream "^1.0.12" + inherits "2" + tcomb-validation@^3.3.0: version "3.4.1" resolved "https://registry.yarnpkg.com/tcomb-validation/-/tcomb-validation-3.4.1.tgz#a7696ec176ce56a081d9e019f8b732a5a8894b65" @@ -29564,13 +29565,6 @@ tmp@0.0.30: dependencies: os-tmpdir "~1.0.1" -tmp@0.0.x, tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - tmp@0.1.0, tmp@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" @@ -29585,6 +29579,13 @@ tmp@^0.0.29: dependencies: os-tmpdir "~1.0.1" +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" @@ -30711,14 +30712,6 @@ user-home@^2.0.0: dependencies: os-homedir "^1.0.0" -useragent@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.3.0.tgz#217f943ad540cb2128658ab23fc960f6a88c9972" - integrity sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw== - dependencies: - lru-cache "4.1.x" - tmp "0.0.x" - utif@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/utif/-/utif-2.0.1.tgz#9e1582d9bbd20011a6588548ed3266298e711759"