Skip to content

Commit 2b8f29b

Browse files
committed
More stuff
1 parent e42bc2e commit 2b8f29b

11 files changed

Lines changed: 733 additions & 14 deletions
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { createModel } from "cx/data";
2+
import { Controller, LabelsTopLayout } from "cx/ui";
3+
import { LookupField } from "cx/widgets";
4+
5+
// @model
6+
interface User {
7+
id: number;
8+
os: string;
9+
browser: string;
10+
fullName: string;
11+
}
12+
13+
interface Model {
14+
user: number;
15+
userOptions: User[];
16+
$group: {
17+
os: string;
18+
browser: string;
19+
};
20+
}
21+
22+
const m = createModel<Model>();
23+
// @model-end
24+
25+
const browsers = ["Chrome", "Firefox", "Internet Explorer", "Opera", "Safari", "Edge"];
26+
const operatingSystems = ["Windows", "Mac OS", "Ubuntu", "Android", "iOS"];
27+
const firstNames = ["Alice", "Bob", "Charlie", "Diana", "Edward", "Fiona", "George", "Hannah", "Ivan", "Julia"];
28+
const lastNames = ["Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Wilson", "Taylor"];
29+
30+
// @controller
31+
class PageController extends Controller<typeof m> {
32+
onInit() {
33+
this.store.set(
34+
m.userOptions,
35+
Array.from({ length: 50 }).map((_, i) => ({
36+
id: i + 1,
37+
os: operatingSystems[i % operatingSystems.length],
38+
browser: browsers[i % browsers.length],
39+
fullName: `${firstNames[i % firstNames.length]} ${lastNames[Math.floor(i / 10) % lastNames.length]}`,
40+
})),
41+
);
42+
}
43+
}
44+
// @controller-end
45+
46+
// @index
47+
export default () => (
48+
<div layout={{ type: LabelsTopLayout, vertical: true }} controller={PageController}>
49+
<LookupField
50+
label="User"
51+
value={m.user}
52+
options={m.userOptions}
53+
optionTextField="fullName"
54+
listOptions={{
55+
grouping: [
56+
{
57+
key: {
58+
os: {
59+
value: { bind: "$option.os" },
60+
direction: "ASC",
61+
},
62+
},
63+
header: <div text={m.$group.os} class="font-bold p-2" />,
64+
},
65+
{
66+
key: {
67+
browser: {
68+
value: { bind: "$option.browser" },
69+
direction: "ASC",
70+
},
71+
},
72+
header: <div text={m.$group.browser} class="text-xs uppercase font-semibold text-gray-500 py-2 pl-6" />,
73+
},
74+
],
75+
itemStyle: "padding-left: 40px;",
76+
}}
77+
/>
78+
</div>
79+
);
80+
// @index-end
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { createModel } from "cx/data";
2+
import {
3+
Controller,
4+
equal,
5+
FirstVisibleChildLayout,
6+
LabelsTopLayout,
7+
tpl,
8+
truthy,
9+
} from "cx/ui";
10+
import { Icon, LookupField, PureContainer } from "cx/widgets";
11+
import "../../icons/lucide";
12+
13+
// @model
14+
interface Browser {
15+
id: string;
16+
text: string;
17+
favorite: boolean;
18+
}
19+
20+
interface Model {
21+
browser: string;
22+
browserOptions: Browser[];
23+
$group: {
24+
group: string;
25+
count: number;
26+
};
27+
}
28+
29+
const m = createModel<Model>();
30+
31+
const browsers = [
32+
"Chrome",
33+
"Firefox",
34+
"Internet Explorer",
35+
"Opera",
36+
"Safari",
37+
"Edge",
38+
];
39+
40+
// @model-end
41+
42+
// @controller
43+
class PageController extends Controller<typeof m> {
44+
onInit() {
45+
this.store.set(
46+
m.browserOptions,
47+
browsers.map((b) => ({
48+
id: b,
49+
text: b,
50+
favorite: b == "Chrome",
51+
})),
52+
);
53+
}
54+
}
55+
// @controller-end
56+
57+
// @index
58+
export default () => (
59+
<LabelsTopLayout controller={PageController}>
60+
<LookupField
61+
label="Browser"
62+
value={m.browser}
63+
options={m.browserOptions}
64+
listOptions={{
65+
grouping: {
66+
key: {
67+
group: {
68+
value: { expr: "{$option.favorite} ? 'Favorites' : 'Other'" },
69+
direction: "ASC",
70+
},
71+
},
72+
header: (
73+
<FirstVisibleChildLayout>
74+
<div class="flex items-center gap-1.5 text-xs uppercase font-semibold text-gray-500 p-2">
75+
<Icon
76+
name="star"
77+
visible={equal(m.$group.group, "Favorites")}
78+
/>
79+
<div text={m.$group.group} />
80+
</div>
81+
</FirstVisibleChildLayout>
82+
),
83+
},
84+
itemStyle: "padding-left: 24px;",
85+
}}
86+
/>
87+
</LabelsTopLayout>
88+
);
89+
// @index-end
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import { createModel } from "cx/data";
2+
import { Controller, LabelsTopLayout } from "cx/ui";
3+
import { Checkbox, Grid, LabeledContainer, LookupField } from "cx/widgets";
4+
5+
// @model
6+
interface Country {
7+
name: string;
8+
code: string;
9+
capital: string;
10+
continent: string;
11+
active: boolean;
12+
}
13+
14+
interface Model {
15+
countries: Country[];
16+
selectedCountry: string;
17+
$record: Country;
18+
allowOnlyActiveCountries: boolean;
19+
}
20+
21+
const m = createModel<Model>();
22+
// @model-end
23+
24+
// @controller
25+
class PageController extends Controller<typeof m> {
26+
onInit() {
27+
this.store.init(m.countries, [
28+
{
29+
name: "Austria",
30+
code: "AT",
31+
capital: "Vienna",
32+
continent: "Europe",
33+
active: true,
34+
},
35+
{
36+
name: "Cyprus",
37+
code: "CY",
38+
capital: "Nicosia",
39+
continent: "Europe",
40+
active: true,
41+
},
42+
{
43+
name: "Bosnia and Herzegovina",
44+
code: "BA",
45+
capital: "Sarajevo",
46+
continent: "Europe",
47+
active: false,
48+
},
49+
{
50+
name: "Nicaragua",
51+
code: "NI",
52+
capital: "Managua",
53+
continent: "North America",
54+
active: true,
55+
},
56+
{
57+
name: "Morocco",
58+
code: "MA",
59+
capital: "Rabat",
60+
continent: "Africa",
61+
active: true,
62+
},
63+
]);
64+
}
65+
}
66+
// @controller-end
67+
68+
// @index
69+
export default () => (
70+
<div controller={PageController} class="space-y-6">
71+
<LabelsTopLayout vertical>
72+
<LabeledContainer label="Allowed Countries">
73+
<Grid
74+
records={m.countries}
75+
recordAlias={m.$record}
76+
columns={[
77+
{
78+
field: "active",
79+
header: "Active",
80+
items: <Checkbox value={m.$record.active} />,
81+
align: "center",
82+
defaultWidth: 70,
83+
pad: false,
84+
},
85+
{ field: "name", header: "Country", defaultWidth: 200 },
86+
{ field: "code", header: "Code", defaultWidth: 100 },
87+
{ field: "continent", header: "Continent", defaultWidth: 120 },
88+
]}
89+
scrollable
90+
/>
91+
</LabeledContainer>
92+
<Checkbox
93+
value={m.allowOnlyActiveCountries}
94+
text="Allow only countries marked Active"
95+
/>
96+
<LookupField
97+
label="Domicile"
98+
value={m.selectedCountry}
99+
options={m.countries}
100+
optionIdField="code"
101+
optionTextField="name"
102+
filterParams={{
103+
allowOnlyActiveCountries: m.allowOnlyActiveCountries,
104+
selection: m.selectedCountry,
105+
}}
106+
onCreateVisibleOptionsFilter={({
107+
allowOnlyActiveCountries,
108+
selection,
109+
}) => {
110+
if (allowOnlyActiveCountries)
111+
return (option: Country) =>
112+
option.code == selection || option.active;
113+
return () => true;
114+
}}
115+
minOptionsForSearchField={2}
116+
/>
117+
</LabelsTopLayout>
118+
</div>
119+
);
120+
// @index-end

0 commit comments

Comments
 (0)