0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-01-13 21:30:30 -05:00

refactor(console): sort quota list items (#4246)

This commit is contained in:
Xiao Yijun 2023-07-26 11:41:15 +08:00 committed by GitHub
parent 0aa00307cb
commit 5a1c9d3a7b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 51 additions and 29 deletions

View file

@ -1,7 +1,9 @@
import classNames from 'classnames'; import classNames from 'classnames';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { planQuotaItemOrder } from '@/consts/plan-quotas';
import { type SubscriptionPlanQuota } from '@/types/subscriptions'; import { type SubscriptionPlanQuota } from '@/types/subscriptions';
import { sortBy } from '@/utils/sort';
import QuotaItem from './QuotaItem'; import QuotaItem from './QuotaItem';
import * as styles from './index.module.scss'; import * as styles from './index.module.scss';
@ -16,7 +18,6 @@ type Props = {
function PlanQuotaList({ quota, featuredQuotaKeys, isDiff, hasIcon, className }: Props) { function PlanQuotaList({ quota, featuredQuotaKeys, isDiff, hasIcon, className }: Props) {
const items = useMemo(() => { const items = useMemo(() => {
// Todo: @xiaoyijun LOG-6540 order keys
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
const entries = Object.entries(quota) as Array< const entries = Object.entries(quota) as Array<
[keyof SubscriptionPlanQuota, SubscriptionPlanQuota[keyof SubscriptionPlanQuota]] [keyof SubscriptionPlanQuota, SubscriptionPlanQuota[keyof SubscriptionPlanQuota]]
@ -26,7 +27,11 @@ function PlanQuotaList({ quota, featuredQuotaKeys, isDiff, hasIcon, className }:
? entries.filter(([key]) => featuredQuotaKeys.includes(key)) ? entries.filter(([key]) => featuredQuotaKeys.includes(key))
: entries; : entries;
return featuredEntries; return featuredEntries
.slice()
.sort(([preQuotaKey], [nextQuotaKey]) =>
sortBy(planQuotaItemOrder)(preQuotaKey, nextQuotaKey)
);
}, [quota, featuredQuotaKeys]); }, [quota, featuredQuotaKeys]);
return ( return (

View file

@ -149,3 +149,5 @@ export const planTableGroupKeyMap: SubscriptionPlanTableGroupKeyMap = Object.fre
[SubscriptionPlanTableGroupKey.hooks]: ['hooksLimit'], [SubscriptionPlanTableGroupKey.hooks]: ['hooksLimit'],
[SubscriptionPlanTableGroupKey.support]: ['communitySupportEnabled', 'ticketSupportResponseTime'], [SubscriptionPlanTableGroupKey.support]: ['communitySupportEnabled', 'ticketSupportResponseTime'],
}) satisfies SubscriptionPlanTableGroupKeyMap; }) satisfies SubscriptionPlanTableGroupKeyMap;
export const planQuotaItemOrder = Object.values(planTableGroupKeyMap).flat();

View file

@ -7,6 +7,7 @@ import { type SubscriptionPlanResponse } from '@/cloud/types/router';
import { isCloud } from '@/consts/env'; import { isCloud } from '@/consts/env';
import { reservedPlanIdOrder } from '@/consts/subscriptions'; import { reservedPlanIdOrder } from '@/consts/subscriptions';
import { type SubscriptionPlan } from '@/types/subscriptions'; import { type SubscriptionPlan } from '@/types/subscriptions';
import { sortBy } from '@/utils/sort';
import { addSupportQuotaToPlan } from '@/utils/subscription'; import { addSupportQuotaToPlan } from '@/utils/subscription';
const useSubscriptionPlans = () => { const useSubscriptionPlans = () => {
@ -26,28 +27,9 @@ const useSubscriptionPlans = () => {
return subscriptionPlansResponse return subscriptionPlansResponse
.map((plan) => addSupportQuotaToPlan(plan)) .map((plan) => addSupportQuotaToPlan(plan))
.slice() .slice()
.sort(({ id: previousId }, { id: nextId }) => { .sort(({ id: previousId }, { id: nextId }) =>
const previousIndex = reservedPlanIdOrder.indexOf(previousId); sortBy(reservedPlanIdOrder)(previousId, nextId)
const nextIndex = reservedPlanIdOrder.indexOf(nextId); );
if (previousIndex === -1 && nextIndex === -1) {
// Note: If both plan ids not present in `reservedPlanIdOrder`, sort them in default order
return 0;
}
if (previousIndex === -1) {
// Note: If only the previous plan has an id not present in `reservedPlanIdOrder`, move it to the end
return 1;
}
if (nextIndex === -1) {
// Note: If only the next plan has an id not present in `reservedPlanIdOrder`, move it to the end
return -1;
}
// Note: Compare them based on the index in the `reservedPlanIdOrder` array
return previousIndex - nextIndex;
});
}, [subscriptionPlansResponse]); }, [subscriptionPlansResponse]);
return { return {

View file

@ -1,14 +1,17 @@
import { conditional } from '@silverhand/essentials'; import { conditional } from '@silverhand/essentials';
import { useMemo } from 'react';
import { Trans, useTranslation } from 'react-i18next'; import { Trans, useTranslation } from 'react-i18next';
import ContactUsPhraseLink from '@/components/ContactUsPhraseLink'; import ContactUsPhraseLink from '@/components/ContactUsPhraseLink';
import PlanName from '@/components/PlanName'; import PlanName from '@/components/PlanName';
import { planQuotaItemOrder } from '@/consts/plan-quotas';
import { import {
quotaItemLimitedPhrasesMap, quotaItemLimitedPhrasesMap,
quotaItemNotEligiblePhrasesMap, quotaItemNotEligiblePhrasesMap,
} from '@/consts/quota-item-phrases'; } from '@/consts/quota-item-phrases';
import DynamicT from '@/ds-components/DynamicT'; import DynamicT from '@/ds-components/DynamicT';
import { type SubscriptionPlan, type SubscriptionPlanQuota } from '@/types/subscriptions'; import { type SubscriptionPlan, type SubscriptionPlanQuota } from '@/types/subscriptions';
import { sortBy } from '@/utils/sort';
import * as styles from './index.module.scss'; import * as styles from './index.module.scss';
@ -30,10 +33,17 @@ function NotEligibleSwitchPlanModalContent({ targetPlan, isDowngrade = false }:
const { name, quota } = targetPlan; const { name, quota } = targetPlan;
const orderedEntries = useMemo(() => {
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
const entries = Object.entries(quota) as Array< const entries = Object.entries(quota) as Array<
[keyof SubscriptionPlanQuota, SubscriptionPlanQuota[keyof SubscriptionPlanQuota]] [keyof SubscriptionPlanQuota, SubscriptionPlanQuota[keyof SubscriptionPlanQuota]]
>; >;
return entries
.slice()
.sort(([preQuotaKey], [nextQuotaKey]) =>
sortBy(planQuotaItemOrder)(preQuotaKey, nextQuotaKey)
);
}, [quota]);
return ( return (
<div className={styles.container}> <div className={styles.container}>
@ -47,7 +57,7 @@ function NotEligibleSwitchPlanModalContent({ targetPlan, isDowngrade = false }:
</Trans> </Trans>
</div> </div>
<ul className={styles.list}> <ul className={styles.list}>
{entries.map(([quotaKey, quotaValue]) => { {orderedEntries.map(([quotaKey, quotaValue]) => {
if ( if (
excludedQuotaKeys.has(quotaKey) || excludedQuotaKeys.has(quotaKey) ||
quotaValue === null || // Unlimited items quotaValue === null || // Unlimited items

View file

@ -0,0 +1,23 @@
export const sortBy = (order: string[]) => {
return (previous: string, next: string) => {
const preIndex = order.indexOf(previous);
const nextIndex = order.indexOf(next);
// Note: If both plan ids not present in the order array, sort them in default order
if (preIndex === -1 && nextIndex === -1) {
return 0;
}
// Note: If only the previous item is not present in the order array, move it to the end
if (preIndex === -1) {
return 1;
}
// Note: If only the next item is not present in the order array, keep it in the end
if (nextIndex === -1) {
return -1;
}
// Note: Compare them based on the index in the order array
return preIndex - nextIndex;
};
};