Skip to content

Commit 6e21abd

Browse files
chore: update tags list
Signed-off-by: Henry Gressmann <[email protected]>
1 parent 23fe322 commit 6e21abd

File tree

10 files changed

+94
-138
lines changed

10 files changed

+94
-138
lines changed

Cargo.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version="0.0.0"
44
edition="2021"
55
rust-version="1.80"
66
repository="https://github.com/explodingcamera/liwan"
7-
license="(AGPL-3.0-only AND Apache-2.0 AND MIT) OR LicenseRef-Liwan"
7+
license="AGPL-3.0-only OR LicenseRef-Liwan"
88

99
[lib]
1010
path="src/lib.rs"

src/app/core/reports.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,31 @@ use time::OffsetDateTime;
1818

1919
#[derive(Object)]
2020
pub struct DateRange {
21-
pub start: OffsetDateTime,
22-
pub end: OffsetDateTime,
21+
pub start: u64,
22+
pub end: u64,
2323
}
2424

25-
impl Display for DateRange {
26-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27-
write!(f, "{} - {}", self.start, self.end)
25+
impl DateRange {
26+
pub fn start(&self) -> OffsetDateTime {
27+
OffsetDateTime::from_unix_timestamp(self.start as i64).unwrap_or(OffsetDateTime::UNIX_EPOCH)
28+
}
29+
30+
pub fn end(&self) -> OffsetDateTime {
31+
OffsetDateTime::from_unix_timestamp(self.end as i64).unwrap_or(OffsetDateTime::UNIX_EPOCH)
2832
}
29-
}
3033

31-
impl DateRange {
3234
pub fn prev(&self) -> DateRange {
3335
let duration = self.end - self.start;
3436
DateRange { start: self.start - duration, end: self.start }
3537
}
3638
}
3739

40+
impl Display for DateRange {
41+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42+
write!(f, "{} - {}", self.start, self.end)
43+
}
44+
}
45+
3846
#[derive(Debug, Enum)]
3947
#[oai(rename_all = "snake_case")]
4048
pub enum Metric {
@@ -205,7 +213,7 @@ pub fn overall_report(
205213
");
206214

207215
let mut stmt = conn.prepare_cached(&query)?;
208-
let params = params![range.start, range.end, data_points, data_points, event, range.end];
216+
let params = params![range.start(), range.end(), data_points, data_points, event, range.end()];
209217

210218
match metric {
211219
Metric::Views | Metric::UniqueVisitors | Metric::Sessions => {
@@ -280,7 +288,7 @@ pub fn overall_stats(
280288
");
281289

282290
let mut stmt = conn.prepare_cached(&query)?;
283-
let params = params![range.start, range.end, event];
291+
let params = params![range.start(), range.end(), event];
284292

285293
let result = stmt.query_row(duckdb::params_from_iter(params), |row| {
286294
Ok(ReportStats {
@@ -365,7 +373,7 @@ pub fn dimension_report(
365373
);
366374

367375
let mut stmt = conn.prepare_cached(&query)?;
368-
let params = params![range.start, range.end, event];
376+
let params = params![range.start(), range.end(), event];
369377

370378
match metric {
371379
Metric::Views | Metric::UniqueVisitors | Metric::Sessions => {

web/src/api/dashboard.ts

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

web/src/components/dialog.module.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
.title {
3030
white-space: preserve-breaks;
31+
font-size: 1.6rem;
3132
}
3233

3334
.content {

web/src/components/settings/dialogs.module.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
transform: translateY(-100%);
99
}
1010

11+
.new {
12+
padding: 0.4rem 0.5rem;
13+
height: fit-content;
14+
}
15+
1116
.danger {
1217
--pico-background-color: var(--pico-del-color);
1318
--pico-border-color: var(--pico-del-color);

web/src/components/settings/dialogs.tsx

Lines changed: 26 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
useProjects,
2020
} from "../../api";
2121
import { createToast } from "../toast";
22+
import { cls } from "../../utils";
2223

2324
const toTitleCase = (str: string) => str[0].toUpperCase() + str.slice(1);
2425

@@ -97,90 +98,14 @@ export const DeleteDialog = ({
9798
);
9899
};
99100

100-
export const EditProjectEntities = ({ project, trigger }: { project: ProjectResponse; trigger: JSX.Element }) => {
101+
export const EditProject = ({ project, trigger }: { project: ProjectResponse; trigger: JSX.Element }) => {
101102
const closeRef = useRef<HTMLButtonElement>(null);
102103
const { role } = useMe();
103104

104105
const { entities } = useEntities();
105106
const entityTags = useMemo(() => entities.map((p) => ({ value: p.id, label: p.displayName })), [entities]);
106107
const [selectedEntities, setSelectedEntities] = useState<Tag[]>([]);
107108

108-
useEffect(() => {
109-
setSelectedEntities(
110-
project.entities.map((entity) => ({
111-
value: entity.id,
112-
label: entity.displayName,
113-
})),
114-
);
115-
}, [project.entities]);
116-
117-
const { mutate, error, reset } = useMutation({
118-
mutationFn: api["/api/dashboard/project/{project_id}"].put,
119-
onSuccess: () => {
120-
closeRef?.current?.click();
121-
createToast("Entities updated successfully", "success");
122-
invalidateProjects();
123-
},
124-
onError: console.error,
125-
});
126-
127-
const handleSubmit = (e: React.FormEvent) => {
128-
e.preventDefault();
129-
e.stopPropagation();
130-
const submitEntities = selectedEntities.map((tag) => tag.value as string);
131-
const updateEntities =
132-
project.entities
133-
.map((p) => p.id)
134-
.sort()
135-
.join() === submitEntities.sort().join();
136-
137-
mutate({
138-
params: { project_id: project.id },
139-
json: { entities: updateEntities ? undefined : submitEntities },
140-
});
141-
};
142-
143-
return (
144-
<Dialog
145-
onOpenChange={() => reset()}
146-
title={`Edit Entities: ${project.displayName}`}
147-
description="Edit the entities associated with this project."
148-
hideDescription
149-
trigger={role === "admin" && trigger}
150-
>
151-
<form onSubmit={handleSubmit}>
152-
<Tags
153-
labelText="Associated Entities"
154-
selected={selectedEntities}
155-
suggestions={entityTags}
156-
onAdd={(tag) => setSelectedEntities((rest) => [...rest, tag])}
157-
onDelete={(i) => setSelectedEntities(selectedEntities.filter((_, index) => index !== i))}
158-
noOptionsText="No matching entities"
159-
/>
160-
<div className="grid">
161-
<Dialog.Close asChild>
162-
<button className="secondary outline" type="button" ref={closeRef}>
163-
Cancel
164-
</button>
165-
</Dialog.Close>
166-
<button type="submit">Save Changes</button>
167-
</div>
168-
{error && (
169-
<article role="alert" className={styles.error}>
170-
{"An error occurred while editing the project's entities:"}
171-
<br />
172-
{error?.message ?? "Unknown error"}
173-
</article>
174-
)}
175-
</form>
176-
</Dialog>
177-
);
178-
};
179-
180-
export const EditProject = ({ project, trigger }: { project: ProjectResponse; trigger: JSX.Element }) => {
181-
const closeRef = useRef<HTMLButtonElement>(null);
182-
const { role } = useMe();
183-
184109
const { mutate, error, reset } = useMutation({
185110
mutationFn: api["/api/dashboard/project/{project_id}"].put,
186111
onSuccess: () => {
@@ -191,6 +116,15 @@ export const EditProject = ({ project, trigger }: { project: ProjectResponse; tr
191116
onError: console.error,
192117
});
193118

119+
useEffect(() => {
120+
setSelectedEntities(
121+
project.entities.map((entity) => ({
122+
value: entity.id,
123+
label: entity.displayName,
124+
})),
125+
);
126+
}, [project.entities]);
127+
194128
const handleSubmit = (e: React.FormEvent) => {
195129
e.preventDefault();
196130
e.stopPropagation();
@@ -207,6 +141,7 @@ export const EditProject = ({ project, trigger }: { project: ProjectResponse; tr
207141
displayName,
208142
public: isPublic === "on",
209143
},
144+
entities: selectedEntities.map((tag) => tag.value as string),
210145
},
211146
});
212147
};
@@ -224,6 +159,14 @@ export const EditProject = ({ project, trigger }: { project: ProjectResponse; tr
224159
Project Name <small>(Used in the dashboard)</small>
225160
<input required name="displayName" type="text" defaultValue={project.displayName} />
226161
</label>
162+
<Tags
163+
labelText="Associated Entities"
164+
selected={selectedEntities}
165+
suggestions={entityTags}
166+
onAdd={(tag) => setSelectedEntities((rest) => [...rest, tag])}
167+
onDelete={(i) => setSelectedEntities(selectedEntities.filter((_, index) => index !== i))}
168+
noOptionsText="No matching entities"
169+
/>
227170
<label>
228171
{/* biome-ignore lint/a11y/useAriaPropsForRole: this is an uncontrolled component */}
229172
<input type="checkbox" role="switch" name="isPublic" defaultChecked={project.public} />
@@ -289,8 +232,8 @@ export const CreateProject = () => {
289232
sources together."
290233
trigger={
291234
role === "admin" && (
292-
<button type="button" className="contrast">
293-
New
235+
<button type="button" className={cls("contrast", styles.new)}>
236+
Create
294237
</button>
295238
)
296239
}
@@ -452,8 +395,8 @@ export const CreateEntity = () => {
452395
description="Entities are individual clients or services that you want to track, like distinct websites or mobile apps. The entity id is used in the tracking snippet to identify the source of the data."
453396
trigger={
454397
role === "admin" && (
455-
<button type="button" className="contrast">
456-
New
398+
<button type="button" className={cls("contrast", styles.new)}>
399+
Create
457400
</button>
458401
)
459402
}
@@ -657,8 +600,8 @@ export const CreateUser = () => {
657600
description="Non-admin users can only view data of projects they are members of, and cannot create or edit projects, entities, or users."
658601
trigger={
659602
role === "admin" && (
660-
<button type="button" className="contrast">
661-
New
603+
<button type="button" className={cls("contrast", styles.new)}>
604+
Create
662605
</button>
663606
)
664607
}

0 commit comments

Comments
 (0)