Skip to content

Commit b00436f

Browse files
committed
next/store: debug and fix URL value parsing for site-license and course -- this should be done in a different way, though, very tricky
1 parent 18e669d commit b00436f

File tree

5 files changed

+271
-99
lines changed

5 files changed

+271
-99
lines changed

src/packages/next/components/store/quota-config-presets.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const STANDARD_DISK = 3;
4646

4747
const PRESET_STANDARD_NAME = "Standard";
4848

49-
export const PRESETS: PresetEntries = {
49+
export const SITE_LICENSE: PresetEntries = {
5050
standard: {
5151
icon: "line-chart",
5252
name: PRESET_STANDARD_NAME,

src/packages/next/components/store/quota-config.tsx

Lines changed: 64 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import A from "components/misc/A";
3131
import IntegerSlider from "components/misc/integer-slider";
3232
import {
3333
COURSE,
34-
PRESETS,
34+
SITE_LICENSE,
3535
PRESET_MATCH_FIELDS,
3636
Preset,
3737
PresetConfig,
@@ -324,7 +324,7 @@ export const QuotaConfig: React.FC<Props> = (props: Props) => {
324324

325325
function presetIsAdjusted() {
326326
if (preset == null) return;
327-
const presetData: PresetConfig = PRESETS[preset];
327+
const presetData: PresetConfig = SITE_LICENSE[preset];
328328
if (presetData == null) {
329329
return (
330330
<div>
@@ -393,7 +393,8 @@ export const QuotaConfig: React.FC<Props> = (props: Props) => {
393393
<>After selecting a preset, feel free to</>
394394
) : (
395395
<>
396-
Selected preset <strong>"{PRESETS[preset]?.name}"</strong>. You can
396+
Selected preset <strong>"{SITE_LICENSE[preset]?.name}"</strong>. You
397+
can
397398
</>
398399
)}{" "}
399400
fine tune the selection in the "{EXPERT_CONFIG}" tab. Subsequent preset
@@ -470,7 +471,7 @@ export const QuotaConfig: React.FC<Props> = (props: Props) => {
470471
}
471472

472473
function renderPresetsNarrow() {
473-
const p = preset != null ? PRESETS[preset] : undefined;
474+
const p = preset != null ? SITE_LICENSE[preset] : undefined;
474475
let presetInfo: JSX.Element | undefined = undefined;
475476
if (p != null) {
476477
const { name, cpu, disk, ram, uptime, note } = p;
@@ -505,11 +506,11 @@ export const QuotaConfig: React.FC<Props> = (props: Props) => {
505506
<Radio.Group
506507
size="large"
507508
value={preset}
508-
onChange={(e) => onPresetChange(PRESETS, e.target.value)}
509+
onChange={(e) => onPresetChange(SITE_LICENSE, e.target.value)}
509510
>
510511
<Space direction="vertical">
511-
{(Object.keys(PRESETS) as Array<Preset>).map((p) => {
512-
const { name, icon, descr } = PRESETS[p];
512+
{(Object.keys(SITE_LICENSE) as Array<Preset>).map((p) => {
513+
const { name, icon, descr } = SITE_LICENSE[p];
513514
return (
514515
<Radio key={p} value={p}>
515516
<span>
@@ -530,58 +531,62 @@ export const QuotaConfig: React.FC<Props> = (props: Props) => {
530531
function renderPresetPanels() {
531532
if (narrow) return renderPresetsNarrow();
532533

533-
const panels = (Object.keys(PRESETS) as Array<Preset>).map((p, idx) => {
534-
const { name, icon, cpu, ram, disk, uptime, expect, descr, note } =
535-
PRESETS[p];
536-
const active = preset === p;
537-
return (
538-
<PricingItem
539-
key={idx}
540-
title={name}
541-
icon={icon}
542-
style={{ flex: 1 }}
543-
active={active}
544-
onClick={() => onPresetChange(PRESETS, p)}
545-
>
546-
<Paragraph>
547-
<strong>{name}</strong> {descr}.
548-
</Paragraph>
549-
<Divider />
550-
<Line amount={cpu} desc={"CPU"} indent={false} />
551-
<Line amount={ram} desc={"RAM"} indent={false} />
552-
<Line amount={disk} desc={"Disk space"} indent={false} />
553-
<Line
554-
amount={displaySiteLicense(uptime)}
555-
desc={renderIdleTimeoutWithHelp("Idle timeout")}
556-
indent={false}
557-
/>
558-
<Divider />
559-
<Paragraph>
560-
<Text type="secondary">In each project, you will be able to:</Text>
561-
<ul>
562-
{expect.map((what, idx) => (
563-
<li key={idx}>{what}</li>
564-
))}
565-
</ul>
566-
</Paragraph>
567-
{active && note != null ? (
568-
<>
569-
<Divider />
570-
<Paragraph type="secondary">{note}</Paragraph>
571-
</>
572-
) : undefined}
573-
<Paragraph style={{ marginTop: "20px", textAlign: "center" }}>
574-
<Button
575-
onClick={() => onPresetChange(PRESETS, p)}
576-
size="large"
577-
type={active ? "primary" : undefined}
578-
>
579-
{name}
580-
</Button>
581-
</Paragraph>
582-
</PricingItem>
583-
);
584-
});
534+
const panels = (Object.keys(SITE_LICENSE) as Array<Preset>).map(
535+
(p, idx) => {
536+
const { name, icon, cpu, ram, disk, uptime, expect, descr, note } =
537+
SITE_LICENSE[p];
538+
const active = preset === p;
539+
return (
540+
<PricingItem
541+
key={idx}
542+
title={name}
543+
icon={icon}
544+
style={{ flex: 1 }}
545+
active={active}
546+
onClick={() => onPresetChange(SITE_LICENSE, p)}
547+
>
548+
<Paragraph>
549+
<strong>{name}</strong> {descr}.
550+
</Paragraph>
551+
<Divider />
552+
<Line amount={cpu} desc={"CPU"} indent={false} />
553+
<Line amount={ram} desc={"RAM"} indent={false} />
554+
<Line amount={disk} desc={"Disk space"} indent={false} />
555+
<Line
556+
amount={displaySiteLicense(uptime)}
557+
desc={renderIdleTimeoutWithHelp("Idle timeout")}
558+
indent={false}
559+
/>
560+
<Divider />
561+
<Paragraph>
562+
<Text type="secondary">
563+
In each project, you will be able to:
564+
</Text>
565+
<ul>
566+
{expect.map((what, idx) => (
567+
<li key={idx}>{what}</li>
568+
))}
569+
</ul>
570+
</Paragraph>
571+
{active && note != null ? (
572+
<>
573+
<Divider />
574+
<Paragraph type="secondary">{note}</Paragraph>
575+
</>
576+
) : undefined}
577+
<Paragraph style={{ marginTop: "20px", textAlign: "center" }}>
578+
<Button
579+
onClick={() => onPresetChange(SITE_LICENSE, p)}
580+
size="large"
581+
type={active ? "primary" : undefined}
582+
>
583+
{name}
584+
</Button>
585+
</Paragraph>
586+
</PricingItem>
587+
);
588+
},
589+
);
585590
return (
586591
<Flex
587592
style={{ width: "100%" }}

src/packages/next/components/store/quota-query-params.ts

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
* License: MS-RSL – see LICENSE.md for details
44
*/
55

6+
import dayjs from "dayjs";
7+
import { clamp, isDate } from "lodash";
8+
import { NextRouter } from "next/router";
9+
610
import { testDedicatedDiskNameBasic } from "@cocalc/util/licenses/check-disk-name-basics";
711
import { BOOST, REGULAR } from "@cocalc/util/upgrades/consts";
812
import {
@@ -14,11 +18,7 @@ import {
1418
PRICES,
1519
} from "@cocalc/util/upgrades/dedicated";
1620
import type { DateRange } from "@cocalc/util/upgrades/shopping";
17-
import { clamp, isDate } from "lodash";
18-
import dayjs from "dayjs";
19-
import { NextRouter } from "next/router";
2021
import { MAX_ALLOWED_RUN_LIMIT } from "./run-limit";
21-
2222
// Various support functions for storing quota parameters as a query parameter in the browser URL
2323

2424
export function encodeRange(
@@ -93,11 +93,21 @@ export const ALL_FIELDS: Set<string> = new Set(
9393
] as any),
9494
);
9595

96+
// Global flag to prevent URL encoding during initial page load
97+
let allowUrlEncoding = false;
98+
99+
export function setAllowUrlEncoding(allow: boolean) {
100+
allowUrlEncoding = allow;
101+
}
102+
96103
export function encodeFormValues(
97104
router: NextRouter,
98105
vals: any,
99106
type: "regular" | "boost" | "dedicated",
100107
): void {
108+
if (!allowUrlEncoding) {
109+
return;
110+
}
101111
const { query } = router;
102112
for (const key in vals) {
103113
if (!getFormFields(type).includes(key)) continue;
@@ -149,9 +159,19 @@ export function decodeFormValues(
149159
const data = {};
150160
for (const key in router.query) {
151161
const val = router.query[key];
152-
if (!fields.includes(key)) continue;
153-
if (typeof val !== "string") continue;
154-
data[key] = key === "range" ? decodeRange(val) : decodeValue(val);
162+
if (!fields.includes(key)) {
163+
continue;
164+
}
165+
if (typeof val !== "string") {
166+
// Handle non-string values by converting them to string first
167+
const stringVal = String(val);
168+
const decoded =
169+
key === "range" ? decodeRange(stringVal) : decodeValue(stringVal);
170+
data[key] = decoded;
171+
continue;
172+
}
173+
const decoded = key === "range" ? decodeRange(val) : decodeValue(val);
174+
data[key] = decoded;
155175
}
156176

157177
// we also have to sanitize the values

0 commit comments

Comments
 (0)