github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ui/src/views/shared/components/expandableString/index.tsx (about)

     1  // Copyright 2018 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  import _ from "lodash";
    12  import React from "react";
    13  
    14  import { trustIcon } from "src/util/trust";
    15  
    16  import collapseIcon from "!!raw-loader!assets/collapse.svg";
    17  import expandIcon from "!!raw-loader!assets/expand.svg";
    18  
    19  import "./expandable.styl";
    20  
    21  const truncateLength = 50;
    22  
    23  interface ExpandableStringProps {
    24    short?: string;
    25    long: string;
    26  }
    27  
    28  interface ExpandableStringState {
    29    expanded: boolean;
    30  }
    31  
    32  // ExpandableString displays a short string with a clickable ellipsis. When
    33  // clicked, the component displays long. If short is not specified, it uses
    34  // the first 50 chars of long.
    35  export class ExpandableString extends React.Component<ExpandableStringProps, ExpandableStringState> {
    36    state: ExpandableStringState = {
    37      expanded: false,
    38    };
    39  
    40    onClick = (ev: any) => {
    41      ev.preventDefault();
    42      this.setState({ expanded: !this.state.expanded });
    43    }
    44  
    45    renderText(expanded: boolean) {
    46      if (expanded) {
    47        return (
    48          <span className="expandable__text expandable__text--expanded">{ this.props.long }</span>
    49        );
    50      }
    51  
    52      const short = this.props.short || this.props.long.substr(0, truncateLength).trim();
    53      return (
    54        <span className="expandable__text">{ short }&nbsp;&hellip;</span>
    55      );
    56    }
    57  
    58    render() {
    59      const { short, long } = this.props;
    60  
    61      const neverCollapse = _.isNil(short) && long.length <= truncateLength + 2;
    62      if (neverCollapse) {
    63        return <span className="expandable__long">{ this.props.long }</span>;
    64      }
    65  
    66      const { expanded } = this.state;
    67      const icon = expanded ? collapseIcon : expandIcon;
    68      return (
    69        <div className="expandable" onClick={ this.onClick }>
    70          <span className="expandable__long">{ this.renderText(expanded) }</span>
    71          <span className="expandable__icon" dangerouslySetInnerHTML={ trustIcon(icon) } />
    72        </div>
    73      );
    74    }
    75  }