Skip to content

Commit

Permalink
chore: Object.groupBy polyfill (#2287)
Browse files Browse the repository at this point in the history
Now Typescript comes with built-in declarations for `Object.groupBy` its a little less annoying to polyfill use Javascript's `Object.groupBy`, also see the description in #2128.

This PR adds a polyfill and uses it an a couple of places where conversations have arisen lately. most of the change here is as a result of a re-nest, but the code that came up in past conversations is now just a one-liner.

There are a few places I'll be switching this in at some point (including the code in above linked PR)

I tested the polyfill manually in Firefox 118.

Signed-off-by: John Cowen <john.cowen@konghq.com>
  • Loading branch information
johncowen committed Mar 14, 2024
1 parent b90ad9e commit 878e471
Show file tree
Hide file tree
Showing 5 changed files with 428 additions and 105 deletions.
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -45,6 +45,7 @@
"brandi": "5.0.0",
"deepmerge": "4.3.1",
"js-yaml": "4.1.0",
"object.groupby": "1.0.2",
"pretty-bytes": "6.1.1",
"prismjs": "1.29.0",
"semver": "7.6.0",
Expand Down
5 changes: 5 additions & 0 deletions src/app/application/index.ts
@@ -1,4 +1,6 @@
import { i18nTComponent } from '@kong-ui-public/i18n'
// @ts-ignore TS comes with a Object.groupBy declaration but not a polyfill
import groupBy from 'object.groupby'

import AppView from './components/app-view/AppView.vue'
import DataCollection from './components/data-collection/DataCollection.vue'
Expand All @@ -25,6 +27,9 @@ if (!('structuredClone' in globalThis)) {
return JSON.parse(JSON.stringify(obj))
}
}
// temporary Object.groupBy polyfill
// TODO(jc): delete this once we get to 2026
groupBy.shim()

export type { DataSourceResponse, Source } from './services/data-source'
type Sources = ConstructorParameters<typeof DataSourcePool>[0]
Expand Down
186 changes: 92 additions & 94 deletions src/app/data-planes/components/RuleEntryList.vue
Expand Up @@ -4,116 +4,114 @@
multiple-open
>
<template
v-for="policies in [props.rules.reduce<Record<string, Rule[]>>((prev, item) => {
if(typeof prev[item.type] === 'undefined') {
prev[item.type] = []
}
prev[item.type].push(item)
return prev
}, {})]"
v-for="policies in [Object.groupBy(props.rules, (item, i) => item.type)]"
:key="policies"
>
<AccordionItem
<template
v-for="(items, type) in policies"
:key="type"
>
<template #accordion-header>
<h3 class="policy-type-heading">
<PolicyTypeTag :policy-type="type">
{{ type }}
</PolicyTypeTag>
</h3>
</template>

<template #accordion-content>
<template
v-for="hasMatchers in [items.some((item) => item.matchers.length > 0)]"
:key="hasMatchers"
>
<div class="policy-list">
<AppCollection
class="policy-type-table"
:class="{
'has-matchers': hasMatchers,
}"
:total="items.length"
:items="items"
:headers="[
...(hasMatchers ? [{ label: 'Matchers', key: 'matchers' }] : []),
{ label: 'Origin policies', key: 'origins' },
{ label: 'Conf', key: 'config' },
]"
>
<template
#matchers="{ row }"
<AccordionItem
v-if="items"
>
<template #accordion-header>
<h3 class="policy-type-heading">
<PolicyTypeTag :policy-type="type">
{{ type }}
</PolicyTypeTag>
</h3>
</template>

<template #accordion-content>
<template
v-for="hasMatchers in [items.some((item) => item.matchers.length > 0)]"
:key="hasMatchers"
>
<div class="policy-list">
<AppCollection
class="policy-type-table"
:class="{
'has-matchers': hasMatchers,
}"
:total="items.length"
:items="items"
:headers="[
...(hasMatchers ? [{ label: 'Matchers', key: 'matchers' }] : []),
{ label: 'Origin policies', key: 'origins' },
{ label: 'Conf', key: 'config' },
]"
>
<span
v-if="row.matchers.length > 0"
class="matcher"
<template
#matchers="{ row }"
>
<template
v-for="({ key, value, not }, matcherIndex) in row.matchers"
:key="matcherIndex"
<span
v-if="row.matchers.length > 0"
class="matcher"
>
<span
v-if="matcherIndex > 0"
class="matcher__and"
> and<br></span><span
v-if="not"
class="matcher__not"
>!</span><span class="matcher__term">{{ `${key}:${value}` }}</span>
<template
v-for="({ key, value, not }, matcherIndex) in row.matchers"
:key="matcherIndex"
>
<span
v-if="matcherIndex > 0"
class="matcher__and"
> and<br></span><span
v-if="not"
class="matcher__not"
>!</span><span class="matcher__term">{{ `${key}:${value}` }}</span>
</template>
</span>

<template v-else>
<i>{{ t('data-planes.routes.item.matches_everything') }}</i>
</template>
</span>

<template v-else>
<i>{{ t('data-planes.routes.item.matches_everything') }}</i>
</template>
</template>

<template #origins="{ row }">
<ul v-if="row.origins.length > 0">
<li
v-for="(origin, originIndex) in row.origins"
:key="`${type}-${originIndex}`"
>
<RouterLink
:to="{
name: 'policy-detail-view',
params: {
mesh: origin.mesh,
policyPath: props.policyTypesByName[origin.type]!.path,
policy: origin.name,
},
}"
<template #origins="{ row }">
<ul v-if="row.origins.length > 0">
<li
v-for="(origin, originIndex) in row.origins"
:key="`${type}-${originIndex}`"
>
{{ origin.name }}
</RouterLink>
</li>
</ul>

<template v-else>
{{ t('common.collection.none') }}
</template>
</template>

<template #config="{ row }">
<template v-if="row.config">
<CodeBlock
:code="toYaml(row.config)"
language="yaml"
:show-copy-button="false"
/>
<RouterLink
:to="{
name: 'policy-detail-view',
params: {
mesh: origin.mesh,
policyPath: props.policyTypesByName[origin.type]!.path,
policy: origin.name,
},
}"
>
{{ origin.name }}
</RouterLink>
</li>
</ul>

<template v-else>
{{ t('common.collection.none') }}
</template>
</template>

<template v-else>
{{ t('common.collection.none') }}
<template #config="{ row }">
<template v-if="row.config">
<CodeBlock
:code="toYaml(row.config)"
language="yaml"
:show-copy-button="false"
/>
</template>

<template v-else>
{{ t('common.collection.none') }}
</template>
</template>
</template>
</AppCollection>
</div>
</AppCollection>
</div>
</template>
</template>
</template>
</AccordionItem>
</AccordionItem>
</template>
</template>
</AccordionList>
</template>
Expand Down
12 changes: 2 additions & 10 deletions src/app/data-planes/components/StandardDataplanePolicies.vue
Expand Up @@ -54,15 +54,7 @@
{{ t('data-planes.routes.item.from_rules') }}
</h3>
<template
v-for="inbounds in [items.reduce<Record<number, Rule[]>>((prev, item) => {
if(typeof item.inbound?.port !== 'undefined') {
if (typeof prev[item.inbound.port] === 'undefined') {
prev[item.inbound.port] = []
}
prev[item.inbound.port].push(item)
}
return prev
}, {})]"
v-for="inbounds in [Object.groupBy(items, (item) => item.inbound!.port)]"
:key="inbounds"
>
<div
Expand All @@ -73,7 +65,7 @@

<RuleEntryList
class="mt-2"
:rules="rs"
:rules="rs!"
:policy-types-by-name="props.policyTypesByName"
:data-testid="`from-rule-list-${index}`"
/>
Expand Down

0 comments on commit 878e471

Please sign in to comment.