242 lines
9.5 KiB
Rust
242 lines
9.5 KiB
Rust
use super::*;
|
|
|
|
impl AppRoot {
|
|
pub(super) fn render_documents(&self, cx: &mut Context<Self>) -> impl IntoElement + '_ {
|
|
let selected = self
|
|
.state
|
|
.selected_document_id
|
|
.as_ref()
|
|
.and_then(|id| self.snapshot.documents.iter().find(|item| &item.id == id));
|
|
let work_products = self.snapshot.artifacts.iter().take(12).collect::<Vec<_>>();
|
|
let total_count = self.snapshot.documents.len() + work_products.len();
|
|
|
|
div()
|
|
.flex()
|
|
.flex_col()
|
|
.gap_6()
|
|
.child(
|
|
div()
|
|
.flex()
|
|
.justify_between()
|
|
.items_center()
|
|
.child(
|
|
div()
|
|
.child(
|
|
div()
|
|
.text_2xl()
|
|
.text_color(theme::text_primary())
|
|
.child("Document Center"),
|
|
)
|
|
.child(
|
|
div()
|
|
.mt(px(6.0))
|
|
.text_sm()
|
|
.text_color(theme::text_muted())
|
|
.child(format!("{} items", total_count)),
|
|
),
|
|
)
|
|
.child(primary_button("Save draft", cx, |this, cx| {
|
|
this.create_document(cx)
|
|
})),
|
|
)
|
|
.child(document_section_label("DOCUMENTS PROSE"))
|
|
.child(self.render_document_prose_list(cx, selected))
|
|
.when(!work_products.is_empty(), |container| {
|
|
container
|
|
.child(document_section_label("WORK PRODUCTS"))
|
|
.child(render_work_products(work_products.as_slice()))
|
|
})
|
|
.child(self.render_document_editor(selected))
|
|
}
|
|
|
|
fn render_document_prose_list(
|
|
&self,
|
|
cx: &mut Context<Self>,
|
|
selected: Option<&domain::Document>,
|
|
) -> impl IntoElement + '_ {
|
|
div()
|
|
.rounded_lg()
|
|
.border_1()
|
|
.border_color(theme::panel_border())
|
|
.bg(theme::panel())
|
|
.when(self.snapshot.documents.is_empty(), |container| {
|
|
container.child(
|
|
div()
|
|
.min_h(px(180.0))
|
|
.flex()
|
|
.items_center()
|
|
.justify_center()
|
|
.text_color(theme::text_muted())
|
|
.child("No documents yet. Create the first company document to start the knowledge base."),
|
|
)
|
|
})
|
|
.when(!self.snapshot.documents.is_empty(), |container| {
|
|
container.children(self.snapshot.documents.iter().map(|document| {
|
|
let active =
|
|
selected.map(|item| item.id.as_str()) == Some(document.id.as_str());
|
|
let document_id = document.id.clone();
|
|
div()
|
|
.id(SharedString::from(format!("document-{}", document.id)))
|
|
.cursor_pointer()
|
|
.hover(|style| style.bg(theme::panel_hover()))
|
|
.bg(if active {
|
|
theme::selection_fill()
|
|
} else {
|
|
theme::panel()
|
|
})
|
|
.on_click(cx.listener(move |this, _, _, cx| {
|
|
this.state.selected_document_id = Some(document_id.clone());
|
|
cx.notify();
|
|
}))
|
|
.px_5()
|
|
.py_4()
|
|
.border_b_1()
|
|
.border_color(theme::panel_border())
|
|
.child(
|
|
div()
|
|
.flex()
|
|
.justify_between()
|
|
.items_center()
|
|
.child(
|
|
div()
|
|
.flex_1()
|
|
.child(
|
|
div()
|
|
.text_base()
|
|
.text_color(theme::text_primary())
|
|
.child(document.title.clone()),
|
|
)
|
|
.child(
|
|
div()
|
|
.mt(px(4.0))
|
|
.text_sm()
|
|
.text_color(theme::text_muted())
|
|
.child(format!(
|
|
"{} · v{} · {}",
|
|
document.document_type.replace('_', " "),
|
|
document.version,
|
|
short_date(document.updated_at.as_str())
|
|
)),
|
|
),
|
|
)
|
|
.child(document_status(document.status.as_str())),
|
|
)
|
|
}))
|
|
})
|
|
}
|
|
|
|
fn render_document_editor(&self, selected: Option<&domain::Document>) -> impl IntoElement + '_ {
|
|
div()
|
|
.rounded_lg()
|
|
.border_1()
|
|
.border_color(theme::panel_border())
|
|
.bg(theme::panel())
|
|
.p_5()
|
|
.child(
|
|
div().text_lg().text_color(theme::text_primary()).child(
|
|
selected
|
|
.map(|item| item.title.clone())
|
|
.unwrap_or_else(|| "New document".to_string()),
|
|
),
|
|
)
|
|
.child(self.document_title_input.clone())
|
|
.child(self.document_body_input.clone())
|
|
.when_some(selected, |container, document| {
|
|
container.child(
|
|
div()
|
|
.mt(px(12.0))
|
|
.rounded_lg()
|
|
.border_1()
|
|
.border_color(theme::panel_inset_border())
|
|
.bg(theme::panel_inset())
|
|
.p_4()
|
|
.text_sm()
|
|
.line_height(px(22.0))
|
|
.text_color(theme::text_secondary())
|
|
.child(document.content.clone()),
|
|
)
|
|
})
|
|
}
|
|
}
|
|
|
|
fn document_section_label(label: &'static str) -> impl IntoElement {
|
|
div().text_xs().text_color(theme::text_muted()).child(label)
|
|
}
|
|
|
|
fn render_work_products<'a>(products: &'a [&'a domain::ArtifactRecord]) -> impl IntoElement + 'a {
|
|
div()
|
|
.rounded_lg()
|
|
.border_1()
|
|
.border_color(theme::panel_border())
|
|
.bg(theme::panel())
|
|
.children(products.iter().map(|artifact| {
|
|
div()
|
|
.px_5()
|
|
.py_4()
|
|
.border_b_1()
|
|
.border_color(theme::panel_border())
|
|
.child(
|
|
div()
|
|
.flex()
|
|
.justify_between()
|
|
.items_center()
|
|
.child(
|
|
div()
|
|
.flex_1()
|
|
.child(
|
|
div()
|
|
.text_base()
|
|
.text_color(theme::text_primary())
|
|
.child(artifact.title.clone()),
|
|
)
|
|
.child(
|
|
div()
|
|
.mt(px(4.0))
|
|
.text_sm()
|
|
.text_color(theme::text_muted())
|
|
.child(format!(
|
|
"{} · {} · {}",
|
|
artifact.provider,
|
|
artifact.external_id,
|
|
short_date(artifact.created_at.as_str())
|
|
)),
|
|
),
|
|
)
|
|
.child(
|
|
div()
|
|
.px_3()
|
|
.py_2()
|
|
.rounded_full()
|
|
.bg(theme::accent_blue_soft())
|
|
.text_xs()
|
|
.text_color(theme::accent_blue())
|
|
.child("ARTIFACT"),
|
|
),
|
|
)
|
|
}))
|
|
}
|
|
|
|
fn document_status(status: &str) -> impl IntoElement {
|
|
div()
|
|
.flex()
|
|
.items_center()
|
|
.gap_2()
|
|
.child(
|
|
div()
|
|
.w(px(8.0))
|
|
.h(px(8.0))
|
|
.rounded_full()
|
|
.bg(theme::badge_dark()),
|
|
)
|
|
.child(
|
|
div()
|
|
.text_xs()
|
|
.text_color(theme::text_secondary())
|
|
.child(status.to_uppercase()),
|
|
)
|
|
}
|
|
|
|
fn short_date(value: &str) -> &str {
|
|
value.get(..10).unwrap_or(value)
|
|
}
|