A political conference and discussion platform, in Rust and Dioxus
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484//! The schema, as Rust: the fragments and input objects the queries are built//! from. No operations live here — this is the shape of the data, and the//! modules beside it are what the app asks for.
use super::*;
// Custom scalar types#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Hash, Eq)]pub struct Uuid(pub String);
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]pub struct Timestamptz(pub String);
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]pub struct Jsonb(pub serde_json::Value);
// --- Node fields (basic — no children, no data) ---
#[derive(cynic::QueryFragment, Debug, Clone, PartialEq)]#[cynic(schema_path = "graphql/schema.graphql", graphql_type = "nodes")]pub struct SearchNodeFields { pub id: Uuid, pub name: String, pub key: String, pub path: Option<String>, pub mime_id: Option<String>, pub parent_id: Option<Uuid>, pub context_id: Option<Uuid>, pub owner_id: Option<Uuid>, pub mutable: bool, pub index: i32, pub get_index: Option<i32>, /// The one thing a result row needs out of the document: a file's content /// `type`, which picks its icon. /// /// `data(path: "type")` rather than `data` — Hasura will select INSIDE a /// jsonb column, and the difference is the whole point of this fragment. A /// search for three letters was answering 1.5 MB because thirty rows each /// carried a complete document to be thrown away except for one string. /// With the path it is 23 KB, and the icons still work. #[arguments(path: "type")] pub data: Option<Jsonb>, pub mime: Option<MimeFields>, pub is_owner: Option<bool>, pub is_context_owner: Option<bool>, pub created_at: Option<Timestamptz>, /// The lean parent: a result prints its name and nothing else. pub parent: Option<ParentNameRef>,}
#[derive(cynic::QueryFragment, Debug, Clone, PartialEq)]#[cynic(schema_path = "graphql/schema.graphql", graphql_type = "nodes")]pub struct NodeFields { pub id: Uuid, pub name: String, pub key: String, /// Slash-joined keys from the root (`ru/lm2026/dagsorden`), maintained by a /// database trigger. Null for a node whose parent row is missing. pub path: Option<String>, pub mime_id: Option<String>, pub parent_id: Option<Uuid>, pub context_id: Option<Uuid>, pub owner_id: Option<Uuid>, pub mutable: bool, pub index: i32, // Computed ordinal among same-type siblings (1-based) — drives the A/B/C and // 1/2/3 avatar labels for policies / change proposals. pub get_index: Option<i32>, // The node's data blob; for files it carries the content `type`, used to pick // a format-specific icon in the drawer tree. pub data: Option<Jsonb>, pub mime: Option<MimeFields>, pub is_owner: Option<bool>, pub is_context_owner: Option<bool>, pub created_at: Option<Timestamptz>, // The parent node, for the search-result secondary line ("in <parent>"). pub parent: Option<ParentNodeFields>,}
/// A parent reduced to what a LIST needs: the name of the thing this sits under.////// `ParentNodeFields` below carries the parent's whole document and its author's/// avatar, which the feed needs because its rows are ABOUT their parent. A/// search result only prints the parent's name, and paying a document per hit/// for it is how thirty results became 147 KB.#[derive(cynic::QueryFragment, Debug, Clone, PartialEq)]#[cynic(schema_path = "graphql/schema.graphql", graphql_type = "nodes")]pub struct ParentNameRef { pub id: Uuid, pub name: String, pub key: String, pub mime_id: Option<String>,}
#[derive(cynic::QueryFragment, Debug, Clone, PartialEq)]#[cynic(schema_path = "graphql/schema.graphql", graphql_type = "nodes")]pub struct ParentNodeFields { pub id: Uuid, pub name: String, pub key: String, pub mime_id: Option<String>, // What the parent says, for a feed row that is ABOUT its parent: a reaction // shows the comment it is on, a reply the comment it answers. pub data: Option<Jsonb>, // And who wrote it. The computed field, not the `owner` relationship, so the // face still appears for a comment in a context the reader is not in. pub author_avatar: Option<String>, // The grandparent, name only. A reply's parent is the comment it answers, so // the page hosting the thread is one level further up; fetching it with the // row is what lets the feed say where a reply happened without a climb. pub parent: Option<ParentNameRef>,}
#[derive(cynic::QueryFragment, Debug, Clone, PartialEq)]#[cynic(schema_path = "graphql/schema.graphql", graphql_type = "nodes")]pub struct ChildNodeFields { pub id: Uuid, pub name: String, pub key: String, pub mime_id: Option<String>, pub mutable: bool, pub index: i32, pub created_at: Option<Timestamptz>, pub owner_id: Option<Uuid>, pub data: Option<Jsonb>, pub mime: Option<MimeFields>, pub is_owner: Option<bool>, pub is_context_owner: Option<bool>, // Creating user (fallback label for questions/candidates/comments/amendments). pub owner: Option<UserRef>, // The author's name and avatar as computed fields, which see past the row // rule on `users` that `owner` above is subject to. That rule only reveals // someone you share a context with, so on the home page — which lists // content from public contexts you may not belong to — `owner` is null and // the post looked anonymous. These carry the name and picture only; the // email stays behind the users rule. pub author_name: Option<String>, pub author_avatar: Option<String>, // The parent node, for the "Newest" list's secondary line ("in <parent>"), // matching how search results show their context. pub parent: Option<ParentNodeFields>,}
// --- Mime type ---// Schema: context: Boolean!, hidden: Boolean!, icon: String!, id: String!, unique: Boolean!
#[derive(cynic::QueryFragment, Debug, Clone, PartialEq)]#[cynic(schema_path = "graphql/schema.graphql", graphql_type = "mimes")]pub struct MimeFields { pub id: String, pub icon: String, pub hidden: bool, pub context: bool,}
// --- Context nodes (groups / events) for the home list ---
#[derive(cynic::QueryFragment, Debug, Clone, PartialEq)]#[cynic(schema_path = "graphql/schema.graphql", graphql_type = "nodes")]pub struct ContextNodeFields { pub id: Uuid, pub name: String, pub key: String, pub mime_id: Option<String>, pub parent_id: Option<Uuid>, pub created_at: Option<Timestamptz>, // A file's content `type`, so orphan file nodes (missing-parents app) show a // format-specific icon instead of the generic file glyph. Selected by path: // the icon is the ONLY thing read from a context row's data, and the whole // document would otherwise ride along for nothing. #[arguments(path: "type")] pub data: Option<Jsonb>,}
// --- Ordering (for the drawer child tree) ---
#[derive(cynic::Enum, Clone, Copy, Debug)]#[cynic( schema_path = "graphql/schema.graphql", graphql_type = "order_by", rename_all = "snake_case")]pub enum OrderBy { Asc, AscNullsFirst, AscNullsLast, Desc, DescNullsFirst, DescNullsLast,}
#[derive(cynic::InputObject, Debug, Default)]#[cynic( schema_path = "graphql/schema.graphql", graphql_type = "nodes_order_by")]pub struct NodesOrderBy { #[cynic(skip_serializing_if = "Option::is_none")] pub index: Option<OrderBy>, #[cynic(skip_serializing_if = "Option::is_none")] pub created_at: Option<OrderBy>, // A tiebreaker, so a paged query is deterministic. Rows created in the same // instant (a burst of reactions, an import) have no inherent order, and // Postgres is free to return them differently per query — which makes // offset paging repeat some rows and skip others. #[cynic(skip_serializing_if = "Option::is_none")] pub id: Option<OrderBy>,}
/// One drawer-tree row: just enough to render the node, plus a count of the/// node's visible children so the expander chevron only shows when there is/// something to expand (mirrors the React `DrawerElement`'s `children_aggregate`/// gate). Kept separate from `ChildNodeFields` so the `$child_visible` variable/// stays local to the drawer query.#[derive(cynic::QueryFragment, Debug, Clone, PartialEq)]#[cynic( schema_path = "graphql/schema.graphql", graphql_type = "nodes", variables = "DrawerChildrenVariables")]pub struct DrawerChildFields { pub id: Uuid, pub name: String, pub key: String, pub mime_id: Option<String>, pub mutable: bool, // Only the file-type icon is read from a drawer row, so only that is asked // for: on a 48-child folder the whole-document form was 54 KB, this is 11 KB. #[arguments(path: "type")] pub data: Option<Jsonb>, #[cynic(rename = "children_aggregate")] #[arguments(where: $child_visible)] pub children_aggregate: NodesAggregate,}
impl DrawerChildFields { /// Whether this node has at least one child visible to the caller — the gate /// for showing the drawer expander. Matches React's `childrenCount > 0`. pub fn has_children(&self) -> bool { self.children_aggregate .aggregate .as_ref() .map(|a| a.count) .unwrap_or(0) > 0 }}
/// Just an id — for walking a subtree, where nothing else is needed.#[derive(cynic::QueryFragment, Debug, Clone)]#[cynic(schema_path = "graphql/schema.graphql", graphql_type = "nodes")]pub struct NodeIdFields { pub id: Uuid,}
// --- Input types ---
#[derive(cynic::InputObject, Debug, Default, Clone)]#[cynic( schema_path = "graphql/schema.graphql", graphql_type = "nodes_bool_exp")]pub struct NodesBoolExp { #[cynic(rename = "_and", skip_serializing_if = "Option::is_none")] pub and: Option<Vec<NodesBoolExp>>, #[cynic(skip_serializing_if = "Option::is_none")] pub id: Option<UuidComparisonExp>, #[cynic(rename = "_or", skip_serializing_if = "Option::is_none")] pub or: Option<Vec<NodesBoolExp>>, #[cynic(skip_serializing_if = "Option::is_none")] pub key: Option<StringComparisonExp>, #[cynic(skip_serializing_if = "Option::is_none")] pub name: Option<StringComparisonExp>, // Full-text of the document body (Slate content extracted to plain text by a // Postgres generated column); lets search match inside content, not just the // title. Snake-case in the API (unlike the camelCased columns), so renamed. #[cynic(rename = "content_text", skip_serializing_if = "Option::is_none")] pub content_text: Option<StringComparisonExp>, #[cynic(skip_serializing_if = "Option::is_none")] pub parent_id: Option<UuidComparisonExp>, /// The materialised ancestor path. `_eq` resolves a whole URL in one query; /// `_in` fetches a whole breadcrumb trail in one; `_like 'x/%'` is a subtree. #[cynic(skip_serializing_if = "Option::is_none")] pub path: Option<StringComparisonExp>, #[cynic(skip_serializing_if = "Option::is_none")] pub context_id: Option<UuidComparisonExp>, /// Every node above this one, by id. `_contains [x]` is "anywhere under x", /// exactly and without escaping — which a `path _like 'x/%'` is not, since /// keys contain the underscore that LIKE reads as a wildcard. #[cynic(skip_serializing_if = "Option::is_none")] pub ancestors: Option<UuidArrayComparisonExp>, #[cynic(skip_serializing_if = "Option::is_none")] pub mime_id: Option<StringComparisonExp>, #[cynic(skip_serializing_if = "Option::is_none")] pub owner_id: Option<UuidComparisonExp>, #[cynic(skip_serializing_if = "Option::is_none")] pub mutable: Option<BooleanComparisonExp>, #[cynic(skip_serializing_if = "Option::is_none")] pub members: Option<MembersBoolExp>, #[cynic(skip_serializing_if = "Option::is_none")] pub mime: Option<MimesBoolExp>, // The node's context (nearest group/event). Boxed for the self-reference. // Used to keep the "Newest" list to contexts the user belongs to. #[cynic(skip_serializing_if = "Option::is_none")] pub context: Option<Box<NodesBoolExp>>, #[cynic(rename = "_not", skip_serializing_if = "Option::is_none")] pub not: Option<Box<NodesBoolExp>>, // The node's parent row. `_not: { parent: {} }` is how an orphan is found: // `parent_id` still holds the deleted parent's id (there is no foreign key // on it), so the id is not null — the row it points at simply is not there. #[cynic(skip_serializing_if = "Option::is_none")] pub parent: Option<Box<NodesBoolExp>>,}
#[derive(cynic::InputObject, Debug, Default, Clone)]#[cynic( schema_path = "graphql/schema.graphql", graphql_type = "mimes_bool_exp")]pub struct MimesBoolExp { #[cynic(skip_serializing_if = "Option::is_none")] pub hidden: Option<BooleanComparisonExp>, #[cynic(skip_serializing_if = "Option::is_none")] pub context: Option<BooleanComparisonExp>,}
#[derive(cynic::InputObject, Debug, Default, Clone)]#[cynic( schema_path = "graphql/schema.graphql", graphql_type = "String_comparison_exp")]pub struct StringComparisonExp { #[cynic(rename = "_eq", skip_serializing_if = "Option::is_none")] pub eq: Option<String>, #[cynic(rename = "_ilike", skip_serializing_if = "Option::is_none")] pub ilike: Option<String>, #[cynic(rename = "_in", skip_serializing_if = "Option::is_none")] pub in_: Option<Vec<String>>, #[cynic(rename = "_neq", skip_serializing_if = "Option::is_none")] pub neq: Option<String>, /// "none of these", for naming the few mimes a rule understands and letting /// every other one past (see `drafts_are_private`). #[cynic(rename = "_nin", skip_serializing_if = "Option::is_none")] pub nin: Option<Vec<String>>, #[cynic(rename = "_is_null", skip_serializing_if = "Option::is_none")] pub is_null: Option<bool>,}
#[derive(cynic::InputObject, Debug, Default, Clone)]#[cynic( schema_path = "graphql/schema.graphql", graphql_type = "uuid_comparison_exp")]pub struct UuidComparisonExp { #[cynic(rename = "_eq", skip_serializing_if = "Option::is_none")] pub eq: Option<Uuid>, /// "any but this one", for a query that must not match the very row the /// caller is holding. #[cynic(rename = "_neq", skip_serializing_if = "Option::is_none")] pub neq: Option<Uuid>, /// "these ones", for fetching exactly the rows a stream said had changed /// rather than a whole page to find them. #[cynic(rename = "_in", skip_serializing_if = "Option::is_none")] pub in_: Option<Vec<Uuid>>, #[cynic(rename = "_is_null", skip_serializing_if = "Option::is_none")] pub is_null: Option<bool>,}
/// Comparison on a `uuid[]` column. Only containment is used: "is x among this/// node's ancestors", which is the subtree test the feed rolls a group up with.#[derive(cynic::InputObject, Debug, Default, Clone)]#[cynic( schema_path = "graphql/schema.graphql", graphql_type = "uuid_array_comparison_exp")]pub struct UuidArrayComparisonExp { #[cynic(rename = "_contains", skip_serializing_if = "Option::is_none")] pub contains: Option<Vec<Uuid>>,}
#[derive(cynic::InputObject, Debug, Default, Clone)]#[cynic( schema_path = "graphql/schema.graphql", graphql_type = "Boolean_comparison_exp")]pub struct BooleanComparisonExp { #[cynic(rename = "_eq", skip_serializing_if = "Option::is_none")] pub eq: Option<bool>,}
#[derive(cynic::InputObject, Debug)]#[cynic( schema_path = "graphql/schema.graphql", graphql_type = "nodes_insert_input")]pub struct NodesInsertInput { // Unset fields must be omitted, not sent as `null`: Hasura rejects an // explicit null for the non-null columns (e.g. `mutable`), which silently // broke every insert that left a field unset (votes, speaker entries, …). #[cynic(skip_serializing_if = "Option::is_none")] pub name: Option<String>, #[cynic(skip_serializing_if = "Option::is_none")] pub key: Option<String>, #[cynic(skip_serializing_if = "Option::is_none")] pub mime_id: Option<String>, #[cynic(skip_serializing_if = "Option::is_none")] pub parent_id: Option<Uuid>, #[cynic(skip_serializing_if = "Option::is_none")] pub context_id: Option<Uuid>, #[cynic(skip_serializing_if = "Option::is_none")] pub data: Option<Jsonb>, #[cynic(skip_serializing_if = "Option::is_none")] pub mutable: Option<bool>, #[cynic(skip_serializing_if = "Option::is_none")] pub index: Option<i32>, // Only a copy sets this: it carries the original's date so a pasted node // keeps its age instead of surfacing as the newest thing in the folder. // Left unset everywhere else, where the column default (now()) is right. #[cynic(skip_serializing_if = "Option::is_none")] pub created_at: Option<Timestamptz>,}
#[derive(cynic::InputObject, Debug, Default)]#[cynic( schema_path = "graphql/schema.graphql", graphql_type = "relations_bool_exp")]pub struct RelationsBoolExp { #[cynic(skip_serializing_if = "Option::is_none")] pub name: Option<StringComparisonExp>, #[cynic(skip_serializing_if = "Option::is_none")] pub parent_id: Option<UuidComparisonExp>,}
#[derive(cynic::QueryFragment, Debug)]#[cynic(schema_path = "graphql/schema.graphql", graphql_type = "relations")]pub struct RelationRef { pub id: Uuid,}
#[derive(cynic::InputObject, Debug)]#[cynic( schema_path = "graphql/schema.graphql", graphql_type = "nodes_pk_columns_input")]pub struct NodesPkColumnsInput { pub id: Uuid,}
#[derive(cynic::InputObject, Debug, Default)]#[cynic( schema_path = "graphql/schema.graphql", graphql_type = "nodes_set_input")]pub struct NodesSetInput { #[cynic(skip_serializing_if = "Option::is_none")] pub name: Option<String>, #[cynic(skip_serializing_if = "Option::is_none")] pub data: Option<Jsonb>, #[cynic(skip_serializing_if = "Option::is_none")] pub mutable: Option<bool>, #[cynic(skip_serializing_if = "Option::is_none")] pub index: Option<i32>, #[cynic(skip_serializing_if = "Option::is_none")] pub attachable: Option<bool>, #[cynic(skip_serializing_if = "Option::is_none")] pub context_id: Option<Uuid>, #[cynic(skip_serializing_if = "Option::is_none")] pub owner_id: Option<Uuid>, #[cynic(skip_serializing_if = "Option::is_none")] pub parent_id: Option<Uuid>, #[cynic(skip_serializing_if = "Option::is_none")] pub created_at: Option<Timestamptz>,}
#[derive(cynic::QueryFragment, Debug, Clone, PartialEq)]#[cynic( schema_path = "graphql/schema.graphql", graphql_type = "nodes_aggregate_fields")]pub struct NodesAggregateFields { pub count: i32,}