Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show user group in overview #395

Merged
merged 12 commits into from
Jun 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions src/client/routes/users/pw-users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,21 @@ export class PwUsers<X extends string> extends PwEntityList<
})}
</th>

<th class="table-cell-hover p-0" scope="col">
${pwOrder({
url: "/api/v1/users",
name: ["sorting", "group"],
orderBy: "group",
prefix: this.prefix,
title: msg("Group"),
value: null,
get: (o) => o.sorting,
set: (o, v) => (o.sorting = v),
initial,
defaultValue: [],
})}
</th>

<th class="table-cell-hover">${msg("Show deleted")}</th>

<th class="table-cell-hover">${msg("Actions")}</th>
Expand Down Expand Up @@ -244,6 +259,22 @@ export class PwUsers<X extends string> extends PwEntityList<
})}
</th>

<th scope="col">
${pwInputText<"/api/v1/users", string | null | undefined>({
enabled: true,
url: this.url,
label: null,
name: ["filters", "group"],
get: (o) => o.filters.group,
set: (o, v) => (o.filters.group = v),
task: this._task,
type: "text",
initial,
defaultValue: undefined,
resettable: false,
})}
</th>

${pwInputCheckbox<"/api/v1/users">({
url: this.url,
label: null,
Expand Down Expand Up @@ -326,6 +357,13 @@ export class PwUsers<X extends string> extends PwEntityList<
: msg("Schüler")}`}
</p>
</td>
<td>
<p>
${value.deleted
? html`<del>${value.group} </del>`
: html`${value.group} `}
</p>
</td>
<td>
<p>${value.deleted ? msg("deleted") : ""}</p>
</td>
Expand Down
6 changes: 6 additions & 0 deletions src/lib/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,11 @@ export const routes = {
z.enum(["ASC", "DESC"] as const),
z.null(),
]),
z.tuple([
z.literal("group" as const),
z.enum(["ASC", "DESC"] as const),
z.null(),
]),
z.tuple([
z.literal("project_leader_id" as const),
z.enum(["ASC", "DESC"] as const),
Expand All @@ -351,6 +356,7 @@ export const routes = {
project_leader_id: true,
force_in_project_id: true,
deleted: true,
group: true,
})
.strict()
.partial()
Expand Down
4 changes: 2 additions & 2 deletions src/server/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ export const sql = postgres(process.env["DATABASE_URL"], {
//onnotice: () => {
// empty
//}, // TODO FIXME
/*debug: (conn, query, params) => {
debug: (conn, query, params) => {
console.log(conn, query, params);
},*/ // this seems to be a MAJOR performance issue
}, // this seems to be a MAJOR performance issue
});

export async function retryableBegin<T>(
Expand Down
81 changes: 66 additions & 15 deletions src/server/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ export async function fetchData<R extends keyof typeof entityRoutes>(
sorting.push([tiebreaker, "ASC", null]);
}

// TODO FIXME id tiebreaker lost
console.log(sorting);

const orderByQueryParts = mappedFunctionCall2(
sorting,
(v: entitiesType4[R]) => {
Expand Down Expand Up @@ -150,24 +153,72 @@ export async function fetchData<R extends keyof typeof entityRoutes>(
})`}`;
});
} else {
// TODO test with pagination step 10 and 11 null values
// test group,type
// test type,group
// test group,id
// test id,group

const queries = sorting.map((value, index) => {
const part = sorting.slice(0, index + 1);

const parts = part
.flatMap((value, index) => {
return [
sql` AND `,
// @ts-expect-error this seems impossible to type - we probably need to unify this to the indexed type before
sql`${paginationCursor ? paginationCursor[value[0]] : null} ${
index === part.length - 1
? (value[1] === "ASC") !==
(query.paginationDirection === "backwards")
? sql`<`
: sql`>`
: sql`IS NOT DISTINCT FROM`
} ${sql.unsafe(value[0] ?? null)}`,
];
})
const partsTmp = part.flatMap((value, index) => {
let order;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const cursorValue = paginationCursor
? // @ts-expect-error this seems impossible to type - we probably need to unify this to the indexed type before
paginationCursor[value[0]]
: null;
const column = sql.unsafe(`"${value[0]}"`);
if (index === part.length - 1) {
switch (value[1]) {
case "ASC":
// ASC is NULLS LAST by default
switch (query.paginationDirection) {
case "forwards":
order = sql`(${cursorValue} < ${column} ${
paginationCursor == null || cursorValue !== null
? sql`OR ${column} IS NULL`
: sql``
})`;
break;
case "backwards":
order = sql`(${cursorValue} > ${column} ${
paginationCursor == null || cursorValue === null
? sql`OR ${column} IS NULL`
: sql``
})`;
break;
}
break;
case "DESC":
// DESC is NULLS FIRST by default
switch (query.paginationDirection) {
case "forwards":
order = sql`(${cursorValue} > ${column} ${
paginationCursor == null || cursorValue === null
? sql`OR ${column} IS NULL`
: sql``
})`;
break;
case "backwards":
order = sql` (${cursorValue} < ${column} ${
paginationCursor == null || cursorValue !== null
? sql`OR ${column} IS NULL`
: sql``
})`;
break;
}
break;
}
} else {
// this is probably not compatible with the checks above
order = sql`${cursorValue} IS NOT DISTINCT FROM ${column}`;
}
return [sql` AND `, order];
});

const parts = partsTmp
.slice(1)
.reduce((prev, curr) => sql`${prev}${curr}`);

Expand Down
53 changes: 40 additions & 13 deletions src/server/routes/users/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export const usersHandler = requestHandler(
project_leader_id,
force_in_project_id,
deleted,
group,
...rest
} = query.filters;
let _ = rest;
Expand All @@ -88,24 +89,40 @@ export const usersHandler = requestHandler(
? sql`"force_in_project_id",`
: sql``
}
"deleted" FROM users_with_deleted WHERE (${
id === undefined
} OR id = ${id ?? null}) AND username LIKE ${
"%" + (username ?? "") + "%"
"deleted" FROM users_with_deleted WHERE TRUE ${
id === undefined ? sql`` : sql`AND id = ${id ?? null}`
} ${
username === undefined
? sql``
: sql`AND username LIKE ${"%" + username + "%"}`
}
AND (${
${
project_leader_id === undefined
} OR project_leader_id IS NOT DISTINCT FROM ${
? sql``
: sql`
AND project_leader_id IS NOT DISTINCT FROM ${
project_leader_id ?? null
})
AND (${deleted === undefined} OR deleted = ${deleted ?? null})
AND (${
}`
}
${
deleted === undefined
? sql``
: sql`AND deleted = ${deleted ?? null}`
}
${
force_in_project_id === undefined ||
!(loggedInUser.type === "admin" || loggedInUser.type === "helper")
} OR force_in_project_id IS NOT DISTINCT FROM ${
force_in_project_id ?? null
})
AND (${type === undefined} OR type = ${type ?? null})`;
? sql``
: sql`AND force_in_project_id IS NOT DISTINCT FROM ${
force_in_project_id ?? null
}`
}
${
group === undefined
? sql``
: sql` AND "group" LIKE ${`${group ?? ""}%`}`
}
${type === undefined ? sql`` : sql`AND type = ${type ?? null}`}`;
},
{
id: (q, o) => {
Expand Down Expand Up @@ -139,6 +156,16 @@ export const usersHandler = requestHandler(
? "ASC"
: "DESC"
)}`,
group: (q, o) =>
sql`"group" ${sql.unsafe(
o === "backwards"
? q === "ASC"
? "DESC"
: "ASC"
: q === "ASC"
? "ASC"
: "DESC"
)}`,
force_in_project_id: (q, o, v) =>
sql`(users_with_deleted.force_in_project_id IS NOT DISTINCT FROM ${
v ?? null
Expand Down