Commit 6eac6924 authored by Ryo Yamashita's avatar Ryo Yamashita Committed by Yas Naoi
Browse files

Issue #3261046 by Ryo Yamashita, yas: Add skeleton parts for Operation links in SPA

parent 292f4037
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ type ButtonProps = Omit<


type GroupProps = {
  className?: string;
  children: React.ReactNode;
};

@@ -19,9 +20,9 @@ type GroupProps = {
 * @param children Children Node.
 * @param className Added text of className.
 */
const Group = ({ children }: GroupProps) => {
const Group = ({ children, className }: GroupProps) => {

  return <div className={'btn-group'} role="group">{children}</div>;
  return <div className={`btn-group${className ? ' ' + className : ''}`} role="group">{children}</div>;

}

@@ -32,7 +33,7 @@ const Group = ({ children }: GroupProps) => {
 * @param className Added text of className.
 */
const Button: (({ children, className, ...props }: ButtonProps) => JSX.Element) & {
  Group: ({ children }: GroupProps) => JSX.Element
  Group: ({ children, className }: GroupProps) => JSX.Element
} = ({ children, className, ...props }) => {

  return <button type="button"
+1 −0
Original line number Diff line number Diff line
interface DataRecord {
  id: string,
  entityTypeId: string,
  value: { [key: string]: string }
};

+175 −0
Original line number Diff line number Diff line
import Button from 'bootstrap3-components/Button';
import GlyphIcon from 'bootstrap3-components/GlyphIcon';
import DataColumn from 'model/DataColumn';
import DataRecord from 'model/DataRecord';
import React from 'react';
import { Link } from 'react-router-dom';

/**
 * TD tag of DataTable.
 *
 * @param text Message.
 */
const DataTableData = ({ text, link }: {
  text: string | number,
  link?: string
}) => {
  // For the text to be displayed, split the text at the line break position beforehand
  // so that any text is always processed to be enclosed in a "one line at a time" tag.
  const records = typeof text === 'string' && text.includes('\n')
    ? text.split('\n')
    : [`${text}`];

  // If you need to set a link, enclose the entire group of <span> tags in an <a> tag.
  // If not, do not use the <a> tag.
  const textSpanTagList = records.map((r, index) => {
    return index === 0
      ? <span key={index}>{r}</span>
      : <span key={index}><br />{r}</span>;
  });
  return typeof link === 'string'
    ? <Link to={link}>
      {textSpanTagList}
    </Link>
    : <>
      {textSpanTagList}
    </>;
}

/**
 * Find and return the list of items to be added to Operation links.
 *
 * @param dataRecord Record of data.
 * @returns The list of items.
 */
const getOperations = (dataRecord: DataRecord): [string, string][] => {
  switch (dataRecord.entityTypeId) {
    case 'aws_cloud_instance': {
      // TODO: support 'Associate Elastic IP' menu.
      const list: [string, string][] = [['Create Image', '']];
      if (dataRecord.value['instance_state'] === 'running') {
        list.push(['Stop', 'stop']);
        list.push(['Reboot', 'repeat']);
      } else if (dataRecord.value['instance_state'] === 'stopped') {
        list.push(['Start', 'play']);
      }
      return list;
    }
    case 'aws_cloud_volume': {
      const list: [string, string][] = [['Create Snapshot', '']];
      if (dataRecord.value['state'] === 'available') {
        list.push(['Attach', 'tag']);
      } else if (dataRecord.value['state'] === 'in-use') {
        list.push(['Detach', 'tags']);
      }
      return list;
    }
    case 'aws_cloud_elastic_ip':
      return dataRecord.value['allocation_id'] === ''
        || dataRecord.value['allocation_id'] === null
        ? [['Associate', 'ok']]
        : [['Disassociate', 'remove']];
    case 'aws_cloud_snapshot':
      return [['Create Volume', '']];
    case 'aws_cloud_security_group':
      return [['Copy', 'duplicate']];
    case 'aws_cloud_vpc_peering_connection':
      return dataRecord.value['status_code'] === 'pending-acceptance'
        ? [['Accept', '']] : [];
    case 'aws_cloud_internet_gateway':
      return dataRecord.value['vpc_id'] === ''
        || dataRecord.value['vpc_id'] === null
        ? [['Attach', '']]
        : [['Detach', '']];
    case 'k8s_deployment':
      return [['Scale', '']];
    case 'cloud_launch_template': {
      const list: [string, string][] = [];
      if (dataRecord.value['field_workflow_status'] === 'Approved') {
        list.push(['Launch', 'play']);
      }
      list.push(['Copy', 'duplicate']);
      if (dataRecord.value['field_workflow_status'] === 'Review') {
        list.push(['Approve', '']);
      }
      if (dataRecord.value['field_workflow_status'] === 'Draft') {
        list.push(['Review', 'comment']);
      }
      return list;
    }
    case 'cloud_project':
      return [['Launch', 'play'], ['Copy', 'duplicate']];
    case 'k8s_cost_store':
      return [['Copy', 'duplicate']];
    case 'k8s_namespace_resource_store':
      return [['Copy', 'duplicate']];
    case 'k8s_node_resource_store':
      return [['Copy', 'duplicate']];
    case 'k8s_pod_resource_store':
      return [['Copy', 'duplicate']];
  }
  return [];
}

/**
 * Row data of DataTable.
 * Note: The OperationLinks column is added.
 *
 * @param dataRecord Record of data.
 * @param dataColumn List of DataColumn.
 * @param className Parameter of className.
 * @param detailInfo Information required to create a link to more information.
*/
const DataTableRowWithOperationLinks = ({ dataRecord, dataColumnList, className, detailInfo }: {
  dataRecord: DataRecord,
  dataColumnList: DataColumn[],
  className?: string,
  detailInfo?: {
    column: string,
    path: string,
  },
}) => {

  return <tr key={dataRecord.id} className={className}>
    {dataColumnList.map((dataColumn) => {
      return <td key={dataColumn.key} className="word-break-all">
        <DataTableData text={
          dataColumn.key in dataRecord.value
            ? dataRecord.value[dataColumn.key]
            : ''
        } link={dataColumn.key === detailInfo?.column
          ? `${detailInfo.path}/${dataRecord.id}`
          : undefined} />
      </td>;
    })}
    <td>
      <Button.Group>
        <Button><GlyphIcon iconName='wrench' /> Edit</Button>
        <Button className='dropdown-toggle' data-toggle="dropdown">
          <span className="caret" />
        </Button>
        <ul className="dropdown-menu" role="menu">
          {
            getOperations(dataRecord).map((menuInfo) => {
              return <li role="presentation" key={menuInfo[0]}>
                {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
                <a role="menuitem" href="#">
                  {menuInfo[1] !== '' ? <GlyphIcon iconName={menuInfo[1]} /> : <></>}
                  {' '}
                  {menuInfo[0]}
                </a>
              </li>;
            })
          }
          <li role="presentation">
            {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
            <a role="menuitem" href="#"><GlyphIcon iconName='trash' /> Delete</a>
          </li>
        </ul>
      </Button.Group>
    </td>
  </tr>;

}

export default DataTableRowWithOperationLinks;
+2 −0
Original line number Diff line number Diff line
@@ -35,12 +35,14 @@ const CloudServiceProviderTable = () => {
          .map((r) => {
            return {
              id: `${r.cloudServiceProvider}_${r.name}`,
              entityTypeId: '',
              value: { 'labelName': r.labelName }
            };
          })
      }
      sortInfo={sortInfo}
      setSortInfo={setSortInfo}
      hasOperationLinks={false}
    />
  </Form>;

+23 −7
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ import DataRecord from 'model/DataRecord';
import SortInfo from 'model/SortInfo';
import DataTableHeader from 'molecules/DataTableHeader';
import DataTableRow from 'molecules/DataTableRow';
import DataTableRowWithOperationLinks from 'molecules/DataTableRowWithOperationLinks';
import React from 'react';

/**
@@ -15,11 +16,12 @@ import React from 'react';
 * @param setSortInfo Setter of sortInfo.
 * @param detailInfo Information required to create a link to more information.
*/
const DataTable = ({ dataColumnList, dataRecordList, sortInfo, setSortInfo, detailInfo }: {
const DataTable = ({ dataColumnList, dataRecordList, sortInfo, setSortInfo, hasOperationLinks, detailInfo }: {
  dataColumnList: DataColumn[],
  dataRecordList: DataRecord[],
  sortInfo: SortInfo,
  setSortInfo: (s: SortInfo) => void,
  hasOperationLinks: boolean,
  detailInfo?: {
    column: string,
    path: string,
@@ -32,12 +34,26 @@ const DataTable = ({ dataColumnList, dataRecordList, sortInfo, setSortInfo, deta
        {dataColumnList.map((dataColumn) => {
          return <DataTableHeader dataColumn={dataColumn} sortInfo={sortInfo} setSortInfo={setSortInfo} />
        })}
        {
          hasOperationLinks
            ? <th>
              Operation links
            </th>
            : <></>
        }
      </tr>
    </thead>
    <tbody>
      {
        dataRecordList.map((dataRecord, index) => {
          return <DataTableRow
          return hasOperationLinks
            ? <DataTableRowWithOperationLinks
              dataRecord={dataRecord}
              dataColumnList={dataColumnList}
              className={index % 2 === 0 ? 'odd' : 'even'}
              detailInfo={detailInfo}
            />
            : <DataTableRow
              dataRecord={dataRecord}
              dataColumnList={dataColumnList}
              className={index % 2 === 0 ? 'odd' : 'even'}
Loading