Add language editing and filtering.

This commit is contained in:
Gareth Latty
2020-06-01 00:41:04 +01:00
parent f12902b6d8
commit c1cdb2579c
37 changed files with 937 additions and 141 deletions
+27
View File
@@ -0,0 +1,27 @@
DROP VIEW manydecks.summaries;
CREATE VIEW manydecks.summaries AS
SELECT
decks.id,
users.name as author,
users.id as author_id,
decks.version,
decks.deck->>'name' as name,
decks.deck->>'language' as language,
jsonb_array_length(decks.deck->'calls') as calls,
jsonb_array_length(decks.deck->'responses') as responses,
((decks.deck ? 'public') and (decks.deck->'public')::bool) as public,
(setweight(to_tsvector('english', coalesce(decks.deck->>'name', '')), 'A') ||
setweight(to_tsvector('english', decks.deck->'calls'), 'D') ||
setweight(to_tsvector('english', decks.deck->'responses'), 'D')
) as deck_search
FROM
manydecks.decks INNER JOIN manydecks.users ON users.id = decks.author;
CREATE OR REPLACE VIEW manydecks.languages AS
SELECT decks.deck->>'language' AS code
FROM manydecks.decks
WHERE ((decks.deck ? 'public') AND (decks.deck->'public')::bool)
GROUP BY code
ORDER BY count(*) DESC
+8 -3
View File
@@ -98,6 +98,10 @@ const main = async (): Promise<void> => {
});
});
app.get("/api/languages", async (req, res) => {
res.json(await store.languages());
});
app.post("/api/users", async (req, res) => {
if (req.body.token !== undefined) {
const claims = auth.validate(req.body.token);
@@ -153,9 +157,10 @@ const main = async (): Promise<void> => {
app.get("/api/decks/browse", async (req, res) => {
const page = req.query.p as string;
const language = req.query.l as string;
const query = req.query.q as string;
const decks = await store.browse(query, parseInt(page));
res.json(Array.from(decks));
const decks = await store.browse(query, language, parseInt(page));
res.json([...decks]);
});
app.get("/api/decks/:deckCode", async (req, res) => {
@@ -193,7 +198,7 @@ const main = async (): Promise<void> => {
}
const userId = req.params.userId;
const decks = await store.getSummariesForUser(userId, requester !== userId);
res.json(Array.from(decks));
res.json([...decks]);
});
app.post("/api/backup", async (req, res) => {
+16 -6
View File
@@ -58,6 +58,14 @@ export class Store {
this.issuer = issuer;
}
public languages: () => Promise<string[]> = async () =>
await this.withClient(async (client) => {
const result = await client.query(
`SELECT code FROM manydecks.languages;`
);
return result.rows.map((row) => row.code);
});
public findOrCreateUser: (
googleId: string,
googleName?: string
@@ -282,34 +290,36 @@ export class Store {
public browse: (
query?: string,
language?: string,
page?: number
) => Promise<Iterable<Deck.CodeAndSummary>> = async (query, page) =>
) => Promise<Iterable<Deck.CodeAndSummary>> = async (query, language, page) =>
await this.withClient(async (client) => {
const pageSize = 20;
const p = page === undefined ? 0 : page;
const l = language === undefined ? null : language;
let result;
if (query === undefined) {
result = await client.query(
`
SELECT id, name, author_id, author, language, calls, responses, public, version
FROM manydecks.summaries
WHERE summaries.public
WHERE summaries.public AND ($3::text IS NULL OR summaries.language = $3::text)
ORDER BY id DESC
OFFSET $1::int * $2::int LIMIT $2
`,
[p, pageSize]
[p, pageSize, l]
);
} else {
result = await client.query(
`
SELECT id, name, author_id, author, language, calls, responses, public, version, ts_rank_cd(deck_search , query) AS rank
FROM manydecks.summaries, to_tsquery($3) query
WHERE summaries.public
FROM manydecks.summaries, to_tsquery($4) query
WHERE summaries.public AND ($3::text IS NULL OR summaries.language = $3::text)
AND query @@ summaries.deck_search
ORDER BY rank DESC
OFFSET $1::int * $2::int LIMIT $2
`,
[p, pageSize, query]
[p, pageSize, l, query]
);
}
return Store.summariesFromRows(result);