edc-web-components 0.4.10

A Rust Web Components with patternfly-yew client for EDC
Documentation
use crate::models::CommonExpressionLanguageItem;
use patternfly_yew::prelude::*;
use std::rc::Rc;
use yew::prelude::*;

#[derive(Clone, Debug, PartialEq, Properties)]
pub struct ListCommonExpressionLanguageProps {
  pub common_expression_language_items: Vec<CommonExpressionLanguageItem>,
  pub offset: usize,
  pub limit: usize,
  pub onoffset: Callback<usize>,
  pub onlimit: Callback<usize>,
  pub ondelete: Callback<String>,
}

#[component]
pub fn ListCommonExpressionLanguage(props: &ListCommonExpressionLanguageProps) -> Html {
  let header = html_nested! {
    <TableHeader<Columns>>
      <TableColumn<Columns> label="ID" index={Columns::Id} />
      <TableColumn<Columns> label="Left Operand" index={Columns::LeftOperand} />
      <TableColumn<Columns> label="Description" index={Columns::Description} />
      <TableColumn<Columns> label="Scopes" index={Columns::Scopes} />
      <TableColumn<Columns> label="Expression" index={Columns::Expression} />
      <TableColumn<Columns> label="" index={Columns::Actions} />
    </TableHeader<Columns>>
  };

  let total_entries: Option<usize> = None;

  let nav_callback = use_callback(
    (
      props.offset,
      props.limit,
      total_entries,
      props.onoffset.clone(),
    ),
    |page: Navigation, (offset, limit, total_entries, onoffset)| {
      let offset = match page {
        Navigation::First => 0,
        Navigation::Last => (total_entries.unwrap_or_default().saturating_sub(1) / limit) * limit,
        Navigation::Previous => *offset - limit,
        Navigation::Next => *offset + limit,
        Navigation::Page(n) => n * limit,
      };

      onoffset.emit(offset);
    },
  );

  let rows = props
    .common_expression_language_items
    .iter()
    .map(
      |common_expression_language_item| ListCommonExpressionLanguageRenderer {
        common_expression_language: common_expression_language_item.clone(),
        ondelete: props.ondelete.clone(),
      },
    )
    .collect();

  let (entries, _) = use_table_data(MemoizedTableModel::new(Rc::new(rows)));

  html!(
    <>
      <Toolbar>
        <ToolbarContent>
          <ToolbarItem r#type={ToolbarItemType::Pagination}>
            <Pagination
              offset={props.offset}
              entries_per_page_choices={vec![5, 10, 25, 50, 100]}
              selected_choice={props.limit}
              onlimit={&props.onlimit}
              onnavigation={&nav_callback}
            />
          </ToolbarItem>
        </ToolbarContent>
      </Toolbar>
      <Table<Columns, UseTableData<Columns, MemoizedTableModel<ListCommonExpressionLanguageRenderer>>> mode={TableMode::Compact} {header} {entries} />
    </>
  )
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum Columns {
  Id,
  LeftOperand,
  Description,
  Scopes,
  Expression,
  Actions,
}

#[derive(Clone, Debug)]
struct ListCommonExpressionLanguageRenderer {
  common_expression_language: CommonExpressionLanguageItem,
  ondelete: Callback<String>,
}

impl TableEntryRenderer<Columns> for ListCommonExpressionLanguageRenderer {
  fn render_cell(&self, context: CellContext<'_, Columns>) -> Cell {
    match context.column {
      Columns::Id => html! { self.common_expression_language.id.to_owned() },
      Columns::LeftOperand => html!(self.common_expression_language.left_operand.to_owned()),
      Columns::Description => html!(
        self
          .common_expression_language
          .description
          .clone()
          .unwrap_or_default()
      ),
      Columns::Scopes => html!(self.common_expression_language.scopes.to_owned().join(", ")),
      Columns::Expression => html!(
        <ShowExpression expression={self.common_expression_language.expression.to_owned()} />
      ),
      Columns::Actions => {
        let common_expression_language_id = self.common_expression_language.id.to_string();

        html!(
          <DeleteCommonExpressionLanguage
            {common_expression_language_id}
            ondelete={self.ondelete.clone()}
          />
        )
      }
    }
    .into()
  }
}

#[derive(Clone, PartialEq, Properties)]
pub struct ShowExpressionProps {
  pub expression: String,
}

#[function_component]
pub fn ShowExpression(props: &ShowExpressionProps) -> Html {
  let backdropper = use_backdrop();

  let onclick = use_callback(
    (backdropper.clone(), props.expression.clone()),
    |_, (backdropper, expression)| {
      let expression = expression.clone();
      if let Some(backdropper) = backdropper {
        backdropper.open(html!(
          <Bullseye>
            <Modal variant={ModalVariant::Large} title="Common Expression Language">
              <CodeBlock>
                <CodeBlockCode>{ expression }</CodeBlockCode>
              </CodeBlock>
            </Modal>
          </Bullseye>
        ))
      }
    },
  );

  html!(<Button variant={ButtonVariant::Primary} icon={Icon::Eye} {onclick}>{ "Show" }</Button>)
}

#[derive(Clone, PartialEq, Properties)]
pub struct DeleteCommonExpressionLanguageProps {
  pub common_expression_language_id: String,
  pub ondelete: Callback<String>,
}

#[function_component]
pub fn DeleteCommonExpressionLanguage(props: &DeleteCommonExpressionLanguageProps) -> Html {
  let onclick = use_callback(
    (
      props.common_expression_language_id.clone(),
      props.ondelete.clone(),
    ),
    |_, (common_expression_language_id, ondelete)| {
      ondelete.emit(common_expression_language_id.to_string());
    },
  );

  html!(<Button variant={ButtonVariant::Danger} icon={Icon::Trash} {onclick}>{ "Delete" }</Button>)
}