Explorar o código

Improve Minion Pool feature layout

Sergiu Miclea %!s(int64=5) %!d(string=hai) anos
pai
achega
7de8207520
Modificáronse 28 ficheiros con 407 adicións e 386 borrados
  1. 1 1
      README.md
  2. 5 2
      src/@types/MinionPool.ts
  3. 5 8
      src/components/atoms/StatusIcon/StatusIcon.tsx
  4. 0 17
      src/components/atoms/StatusIcon/images/triangle.svg
  5. 82 0
      src/components/atoms/StatusIcon/images/warning-hollow.svg
  6. 2 2
      src/components/atoms/StatusIcon/story.tsx
  7. 1 1
      src/components/atoms/StatusPill/StatusPill.tsx
  8. 1 1
      src/components/molecules/MinionPoolListItem/MinionPoolListItem.tsx
  9. 19 56
      src/components/molecules/MinionPoolListItem/images/minion-pool-list-item.svg
  10. 1 1
      src/components/molecules/NewItemDropdown/NewItemDropdown.tsx
  11. 63 0
      src/components/molecules/NewItemDropdown/images/minion-pool.svg
  12. 0 70
      src/components/molecules/NewItemDropdown/images/minionPool.svg
  13. 9 2
      src/components/organisms/MinionPoolDetailsContent/MinionPoolDetailsContent.tsx
  14. 13 28
      src/components/organisms/MinionPoolDetailsContent/MinionPoolEvents.tsx
  15. 55 19
      src/components/organisms/MinionPoolDetailsContent/MinionPoolMachines.tsx
  16. 6 0
      src/components/organisms/MinionPoolDetailsContent/MinionPoolMainDetails.tsx
  17. 1 0
      src/components/organisms/MinionPoolModal/MinionPoolModal.tsx
  18. 2 1
      src/components/organisms/MinionPoolModal/MinionPoolModalContent.tsx
  19. 14 42
      src/components/organisms/MinionPoolModal/images/minion-pool.svg
  20. 1 1
      src/components/organisms/Navigation/Navigation.tsx
  21. 61 0
      src/components/organisms/Navigation/images/minion-pool-menu.svg
  22. 0 15
      src/components/organisms/Navigation/images/minion-pools-menu.svg
  23. 12 4
      src/components/pages/MinionPoolDetailsPage/MinionPoolDetailsPage.tsx
  24. 19 75
      src/components/pages/MinionPoolDetailsPage/images/minion-pool.svg
  25. 17 34
      src/components/pages/MinionPoolsPage/images/minion-pool-empty-list.svg
  26. 9 0
      src/sources/MinionPoolSource.ts
  27. 4 6
      src/sources/WizardSource.ts
  28. 4 0
      src/stores/MinionPoolStore.ts

+ 1 - 1
README.md

@@ -26,7 +26,7 @@ Your server will be running at `http://localhost:3000/` (the port is configurabl
 ## Development mode
 
 - set env. variable `NODE_MODE='development'`
-- run `yarn ui-dev` to start local development server (starts on port 3001)
+- run `yarn client-dev` to start local development server (starts on port 3001)
 - run `yarn server-dev` to start the express server in development mode
 
 To debug the client code using VS Code, simply run the project's launch configuration from the 'Run' menu (Ctrl+Shift+D).

+ 5 - 2
src/@types/MinionPool.ts

@@ -16,9 +16,12 @@ export type MinionMachine = {
   id: string
   created_at: string
   updated_at: string
-  status: string
+  allocation_status: string
   connection_info?: any
+  power_status: string
   provider_properties: any
+  last_used_at?: string
+  allocated_action: string | null
 }
 export type MinionPoolEvent = {
   id: string
@@ -39,7 +42,7 @@ export type MinionPool = {
   created_at: string
   updated_at: string | null
   name: string
-  os_type: string
+  os_type: 'linux' | 'windows'
   status: string
   minimum_minions: number
   maximum_minions: number

+ 5 - 8
src/components/atoms/StatusIcon/StatusIcon.tsx

@@ -26,7 +26,7 @@ import warningImage from './images/warning'
 import pendingImage from './images/pending.svg'
 import successHollowImage from './images/success-hollow.svg'
 import errorHollowImage from './images/error-hollow.svg'
-import triangleImage from './images/triangle.svg'
+import warningHollowImage from './images/warning-hollow.svg'
 
 type Props = {
   status: string,
@@ -34,7 +34,7 @@ type Props = {
   hollow?: boolean,
   secondary?: boolean,
   style?: React.CSSProperties
-  triangle?: boolean
+  outlined?: boolean
   onClick?: (e: React.MouseEvent<HTMLDivElement>) => void
   title?: string
 }
@@ -51,11 +51,7 @@ const getRunningImageUrl = (props: Props) => {
 
 const getWarningUrl = (background: string) => `url('data:image/svg+xml;utf8,${encodeURIComponent(warningImage(background))}')`
 
-const statuses = (status: any, props: any) => {
-  if (props.triangle) {
-    return css`background-image: url('${triangleImage}');`
-  }
-
+const statuses = (status: any, props: Props) => {
   switch (status) {
     case 'COMPLETED':
       return css`
@@ -99,10 +95,11 @@ const statuses = (status: any, props: any) => {
       return css`
         background-image: ${getWarningUrl('#424242')};
       `
+    case 'INFO':
     case 'UNSCHEDULED':
     case 'UNEXECUTED':
       return css`
-        background-image: ${getWarningUrl(Palette.grayscale[2])};
+        background-image: ${props.hollow ? `url('${warningHollowImage}')` : getWarningUrl(Palette.grayscale[2])};
       `
     default:
       return null

+ 0 - 17
src/components/atoms/StatusIcon/images/triangle.svg

@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<svg version="1.1" id="Layer_1"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="16"
- height="16"
-	 viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
-	<g>
-		<path
-    fill="#dedfe6"
-    d="M501.362,383.95L320.497,51.474c-29.059-48.921-99.896-48.986-128.994,0L10.647,383.95
-			c-29.706,49.989,6.259,113.291,64.482,113.291h361.736C495.039,497.241,531.068,433.99,501.362,383.95z M256,437.241
-			c-16.538,0-30-13.462-30-30c0-16.538,13.462-30,30-30c16.538,0,30,13.462,30,30C286,423.779,272.538,437.241,256,437.241z
-			 M286,317.241c0,16.538-13.462,30-30,30c-16.538,0-30-13.462-30-30v-150c0-16.538,13.462-30,30-30c16.538,0,30,13.462,30,30
-			V317.241z"/>
-	</g>
-</svg>

+ 82 - 0
src/components/atoms/StatusIcon/images/warning-hollow.svg

@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   sodipodi:docname="warning-hollow.svg"
+   inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+   id="svg8"
+   version="1.1"
+   viewBox="0 0 4.2333332 4.2333335"
+   height="16"
+   width="16">
+  <defs
+     id="defs2" />
+  <sodipodi:namedview
+     inkscape:window-maximized="0"
+     inkscape:window-y="0"
+     inkscape:window-x="147"
+     inkscape:window-height="1040"
+     inkscape:window-width="1274"
+     units="px"
+     showgrid="false"
+     inkscape:document-rotation="0"
+     inkscape:current-layer="Icon/Warning-8"
+     inkscape:document-units="mm"
+     inkscape:cy="4.0021626"
+     inkscape:cx="-0.059492155"
+     inkscape:zoom="22.4"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     borderopacity="1.0"
+     bordercolor="#666666"
+     pagecolor="#ffffff"
+     id="base" />
+  <metadata
+     id="metadata5">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:groupmode="layer"
+     inkscape:label="Layer 1">
+    <g
+       transform="matrix(0.26428837,0,0,0.26428837,0.00235971,0.00235971)"
+       id="Icon/Warning-8"
+       style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:1">
+      <circle
+         style="fill:none;stroke:#c8ccd7;stroke-width:1.451;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+         id="circle833-0"
+         r="7.2834306"
+         cy="8"
+         cx="8"
+         fill-rule="evenodd"
+         fill="#0000ff" />
+      <path
+         style="stroke:#c8ccd7;stroke-opacity:1"
+         stroke-linecap="round"
+         stroke-width="2"
+         stroke="#ffffff"
+         id="Line-Copy-5"
+         d="M 8,8 V 4" />
+      <path
+         style="fill:#c8ccd7;fill-opacity:1"
+         fill-rule="evenodd"
+         fill="#ffffff"
+         id="Oval-3-5"
+         d="m 8,12.5 c 0.6903559,0 1.25,-0.559644 1.25,-1.25 C 9.25,10.559644 8.6903559,10 8,10 7.3096441,10 6.75,10.559644 6.75,11.25 6.75,11.940356 7.3096441,12.5 8,12.5 Z" />
+    </g>
+  </g>
+</svg>

+ 2 - 2
src/components/atoms/StatusIcon/story.tsx

@@ -70,8 +70,8 @@ storiesOf('StatusIcon', module)
       <StatusIcon status="CANCELLING" useBackground />
     </Wrapper>
   ))
-  .add('triangle', () => (
+  .add('info hollow', () => (
     <Wrapper>
-      <StatusIcon status="INFO" triangle />
+      <StatusIcon status="INFO" hollow />
     </Wrapper>
   ))

+ 1 - 1
src/components/atoms/StatusPill/StatusPill.tsx

@@ -45,7 +45,7 @@ const LABEL_MAP: { [status: string]: string } = {
   POWERING_ON: 'POWERING ON',
   POWERED_ON: 'POWERED ON',
   POWERED_OFF: 'POWERED OFF',
-  POWER_ERROR: 'ERROR'
+  POWER_ERROR: 'ERROR',
 }
 
 const statuses = (status: any) => {

+ 1 - 1
src/components/molecules/MinionPoolListItem/MinionPoolListItem.tsx

@@ -59,7 +59,7 @@ const Wrapper = styled.div<any>`
   }
 `
 
-const Image = styled.div<any>`
+const Image = styled.div`
   min-width: 48px;
   height: 48px;
   background: url('${itemImage}') no-repeat center;

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 19 - 56
src/components/molecules/MinionPoolListItem/images/minion-pool-list-item.svg


+ 1 - 1
src/components/molecules/NewItemDropdown/NewItemDropdown.tsx

@@ -30,7 +30,7 @@ import replicaImage from './images/replica.svg'
 import endpointImage from './images/endpoint.svg'
 import userImage from './images/user.svg'
 import projectImage from './images/project.svg'
-import minionPoolImage from './images/minionPool.svg'
+import minionPoolImage from './images/minion-pool.svg'
 
 import { navigationMenu } from '../../../constants'
 

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 63 - 0
src/components/molecules/NewItemDropdown/images/minion-pool.svg


+ 0 - 70
src/components/molecules/NewItemDropdown/images/minionPool.svg

@@ -1,70 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   sodipodi:docname="minionPool.svg"
-   inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
-   id="svg858"
-   version="1.1"
-   viewBox="0 0 12.170833 12.170834"
-   height="46"
-   width="46">
-  <defs
-     id="defs852">
-    <linearGradient
-       osb:paint="solid"
-       id="linearGradient1457">
-      <stop
-         id="stop1455"
-         offset="0"
-         style="stop-color:#0044ca;stop-opacity:1;" />
-    </linearGradient>
-  </defs>
-  <sodipodi:namedview
-     inkscape:window-maximized="0"
-     inkscape:window-y="0"
-     inkscape:window-x="403"
-     inkscape:window-height="1040"
-     inkscape:window-width="1274"
-     units="px"
-     showgrid="false"
-     inkscape:document-rotation="0"
-     inkscape:current-layer="layer1"
-     inkscape:document-units="mm"
-     inkscape:cy="6.7745742"
-     inkscape:cx="9.8898401"
-     inkscape:zoom="5.6"
-     inkscape:pageshadow="2"
-     inkscape:pageopacity="0.0"
-     borderopacity="1.0"
-     bordercolor="#666666"
-     pagecolor="#ffffff"
-     id="base" />
-  <metadata
-     id="metadata855">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     id="layer1"
-     inkscape:groupmode="layer"
-     inkscape:label="Layer 1">
-    <path
-       d="M 7.5316674,2.8742546 V 1.4229441 H 4.628978 V 2.8742627 Z M 1.0921959,4.3702397 v 5.8499833 c 0,0.324205 0.2652822,0.589487 0.5894863,0.589487 h 8.7972798 c 0.324206,0 0.589485,-0.265282 0.589485,-0.589487 V 4.3702397 c 0,-0.324205 -0.265279,-0.5894871 -0.589485,-0.5894871 H 1.6816822 c -0.3242041,0 -0.5894863,0.2652821 -0.5894863,0.5894871 z m 9.7038161,-1.495977 c 0.654305,0 1.178927,0.5246217 1.178927,1.1789256 V 10.53728 c 0,0.654302 -0.524622,1.178926 -1.178927,1.178926 H 1.3646085 c -0.65430385,0 -1.17892609,-0.524624 -1.17892609,-1.178926 l 0.005892,-6.4840917 c 0,-0.6543039 0.5187271,-1.1789256 1.17303099,-1.1789256 h 2.357851 V 1.695337 c 0,-0.6543033 0.5246217,-1.17892568 1.1789258,-1.17892568 h 2.357851 c 0.6543032,0 1.1789251,0.52462238 1.1789251,1.17892568 v 1.1789257 z"
-       style="fill:none;fill-opacity:1;stroke:#0044ca;stroke-width:0.371364;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path10" />
-  </g>
-</svg>

+ 9 - 2
src/components/organisms/MinionPoolDetailsContent/MinionPoolDetailsContent.tsx

@@ -74,6 +74,7 @@ const NavigationItems = [
 
 type Props = {
   item?: MinionPoolDetails | null,
+  itemId: string
   replicas: ReplicaItem[],
   migrations: MigrationItem[]
   endpoints: Endpoint[],
@@ -139,7 +140,13 @@ class MinionPoolDetailsContent extends React.Component<Props> {
       return null
     }
 
-    return <MinionPoolMachines item={this.props.item} />
+    return (
+      <MinionPoolMachines
+        item={this.props.item}
+        replicas={this.props.replicas}
+        migrations={this.props.migrations}
+      />
+    )
   }
 
   renderEvents() {
@@ -174,7 +181,7 @@ class MinionPoolDetailsContent extends React.Component<Props> {
         <DetailsNavigation
           items={NavigationItems}
           selectedValue={this.props.page}
-          itemId={this.props.item ? this.props.item.id : ''}
+          itemId={this.props.itemId}
           itemType="minion-pool"
         />
         <DetailsBody>

+ 13 - 28
src/components/organisms/MinionPoolDetailsContent/MinionPoolEvents.tsx

@@ -39,7 +39,7 @@ const EventsTable = styled.div`
   border-radius: ${StyleProps.borderRadius};
   margin-bottom: 16px;
 `
-const Header = styled.div<any>`
+const Header = styled.div`
   display: flex;
   border-bottom: 1px solid ${Palette.grayscale[5]};
   padding: 4px 8px;
@@ -132,7 +132,7 @@ class MinionPoolEvents extends React.Component<Props, State> {
     return this.state.allEvents
       .filter((event: any) => shouldFilterByEventType(event) && shouldFilterByLevel(event))
       .sort((a: any, b: any) => {
-        if (a.index && b.index) {
+        if (a.index && b.index && this.state.filterBy !== 'all') {
           return this.state.orderDir === 'asc' ? a.index - b.index : b.index - a.index
         }
         const aTime = new Date(a.created_at).getTime()
@@ -203,18 +203,12 @@ class MinionPoolEvents extends React.Component<Props, State> {
     return (
       <Body>
         {this.filteredEvents.map((event: any) => {
-          let status: string | null = null
-          if (event.level) {
-            if (event.level === 'DEBUG') {
-              status = 'WARNING'
-            }
-            if (event.level === 'INFO') {
-              status = 'UNEXECUTED'
-            }
-            if (event.level === 'ERROR') {
-              status = 'ERROR'
-            }
+          let status = 'INFO'
+          status = event.level || status
+          if (event.level === 'DEBUG') {
+            status = 'WARNING'
           }
+          const title = event.current_step ? 'Progress Update' : 'Event'
           return (
             <Row key={event.id}>
               <RowData
@@ -225,21 +219,12 @@ class MinionPoolEvents extends React.Component<Props, State> {
                   paddingRight: '8px',
                 }}
               >
-                {status ? (
-                  <StatusIcon
-                    style={{ marginRight: '8px' }}
-                    status={status}
-                    title="Event"
-                  />
-                ) : null}
-                {event.current_step ? (
-                  <StatusIcon
-                    style={{ marginRight: '8px' }}
-                    status="INFO"
-                    title="Progress Update"
-                    triangle
-                  />
-                ) : null}
+                <StatusIcon
+                  style={{ marginRight: '8px' }}
+                  status={status}
+                  title={title}
+                  hollow={event.current_step != null}
+                />
                 <Message>{event.message}</Message>
               </RowData>
               <RowData width="192px" secondary>{moment(event.created_at).format('YYYY-MM-DD HH:mm:ss')}</RowData>

+ 55 - 19
src/components/organisms/MinionPoolDetailsContent/MinionPoolMachines.tsx

@@ -17,14 +17,17 @@ import styled, { createGlobalStyle, css } from 'styled-components'
 import moment from 'moment'
 import { Collapse } from 'react-collapse'
 
+import { Link } from 'react-router-dom'
 import { MinionMachine, MinionPool } from '../../../@types/MinionPool'
 import DropdownLink from '../../molecules/DropdownLink/DropdownLink'
+import { ItemReplicaBadge } from '../../molecules/NotificationDropdown'
 import Palette from '../../styleUtils/Palette'
 import StyleProps from '../../styleUtils/StyleProps'
 import Arrow from '../../atoms/Arrow/Arrow'
 
 import networkImage from './images/network.svg'
 import StatusPill from '../../atoms/StatusPill/StatusPill'
+import { MigrationItem, ReplicaItem, TransferItem } from '../../../@types/MainItem'
 
 const GlobalStyle = createGlobalStyle`
   .ReactCollapse--collapse {
@@ -120,15 +123,27 @@ const MachineTitle = styled.div`
 const MachineBody = styled.div`
   padding: 16px;
 `
-const MachineRow = styled.div<{secondary?: boolean}>`
+const MachineRow = styled.div<{ secondary?: boolean }>`
+  display: flex;
+  margin-bottom: 8px;
+  align-items: center;
   ${props => (props.secondary ? css`
     color: ${Palette.grayscale[5]};
+    margin-bottom: 4px;
   ` : '')}
 `
+const ValueLink = styled(Link)`
+  display: flex;
+  color: ${Palette.primary};
+  text-decoration: none;
+  cursor: pointer;
+`
 
 type FilterType = 'all' | 'allocated' | 'not-allocated'
 type Props = {
   item?: MinionPool | null,
+  replicas: ReplicaItem[]
+  migrations: MigrationItem[]
 }
 type State = {
   filterStatus: FilterType
@@ -240,24 +255,45 @@ class MinionPoolMachines extends React.Component<Props, State> {
 
     return (
       <MachinesWrapper>
-        {this.filteredMachines.map(machine => (
-          <MachineWrapper key={machine.id}>
-            <MachineTitle>ID: {machine.id}</MachineTitle>
-            <MachineBody>
-              <MachineRow style={{ marginBottom: '8px', display: 'flex' }}>
-                Power Status: <StatusPill style={{ marginLeft: '8px' }} status={machine.power_status} />
-              </MachineRow>
-              <MachineRow style={{ marginBottom: '8px', display: 'flex' }}>
-                Allocation Status: <StatusPill style={{ marginLeft: '8px' }} status={machine.allocation_status} />
-              </MachineRow>
-              <MachineRow secondary>Created At: {moment(machine.created_at).format('YYYY-MM-DD HH:mm:ss')}</MachineRow>
-              {machine.updated_at ? <MachineRow secondary>Updated At: {moment(machine.updated_at).format('YYYY-MM-DD HH:mm:ss')}</MachineRow> : null}
-              {machine.last_used_at ? <MachineRow secondary>Last Used At: {moment(machine.last_used_at).format('YYYY-MM-DD HH:mm:ss')}</MachineRow> : null}
-              <MachineRow secondary>Allocated Action: {machine.allocated_action}</MachineRow>
-            </MachineBody>
-            {machine.connection_info ? this.renderConnectionInfo(machine) : null}
-          </MachineWrapper>
-        ))}
+        {this.filteredMachines.map(machine => {
+          const findTransferItem = (transferItems: TransferItem[]) => transferItems
+            .find(i => i.id === machine.allocated_action)
+          const allocatedAction = machine.allocated_action ? (
+            findTransferItem(this.props.replicas) || findTransferItem(this.props.migrations)
+          ) : null
+          return (
+            <MachineWrapper key={machine.id}>
+              <MachineTitle>ID: {machine.id}</MachineTitle>
+              <MachineBody>
+                <MachineRow>
+                  Allocation Status: <StatusPill style={{ marginLeft: '8px' }} status={machine.allocation_status} />
+                </MachineRow>
+                <MachineRow style={{ marginBottom: '16px' }}>
+                  <span style={{ width: '114px' }}>Power Status:</span> <StatusPill style={{ marginLeft: '8px' }} status={machine.power_status} />
+                </MachineRow>
+                <MachineRow secondary>Created At: {moment(machine.created_at).format('YYYY-MM-DD HH:mm:ss')}</MachineRow>
+                {machine.updated_at ? <MachineRow secondary>Updated At: {moment(machine.updated_at).format('YYYY-MM-DD HH:mm:ss')}</MachineRow> : null}
+                {machine.last_used_at ? <MachineRow secondary>Last Used At: {moment(machine.last_used_at).format('YYYY-MM-DD HH:mm:ss')}</MachineRow> : null}
+                {machine.allocated_action ? (
+                  <MachineRow secondary>
+                    Allocated Action:
+                    {allocatedAction ? (
+                      <>
+                        <ItemReplicaBadge style={{ margin: '0px 4px 0 5px' }}>{allocatedAction.type === 'replica' ? 'RE' : 'MI'}</ItemReplicaBadge>
+                        <ValueLink
+                          to={`/${allocatedAction.type}s/${allocatedAction.id}`}
+                        >
+                          {allocatedAction.instances[0]}
+                        </ValueLink>
+                      </>
+                    ) : <span>&nbsp;{machine.allocated_action}</span>}
+                  </MachineRow>
+                ) : null}
+              </MachineBody>
+              {machine.connection_info ? this.renderConnectionInfo(machine) : null}
+            </MachineWrapper>
+          )
+        })}
         <GlobalStyle />
       </MachinesWrapper>
     )

+ 6 - 0
src/components/organisms/MinionPoolDetailsContent/MinionPoolMainDetails.tsx

@@ -258,6 +258,12 @@ class MinionPoolMainDetails extends React.Component<Props> {
               {this.renderValue(this.props.item?.platform || '-', true)}
             </Field>
           </Row>
+          <Row>
+            <Field>
+              <Label>Pool OS Type</Label>
+              {this.renderValue(this.props.item?.os_type || '-', true)}
+            </Field>
+          </Row>
           <Row>
             <Field>
               <Label>Created</Label>

+ 1 - 0
src/components/organisms/MinionPoolModal/MinionPoolModal.tsx

@@ -304,6 +304,7 @@ class MinionPoolModal extends React.Component<Props, State> {
       <Content>
         <MinionPoolModalContent
           endpoint={this.props.endpoint}
+          platform={this.props.platform}
           envOptionsDisabled={this.props.minionPool != null && this.props.minionPool.status !== 'DEALLOCATED'}
           defaultSchema={minionPoolStore.minionPoolDefaultSchema}
           envSchema={minionPoolStore.minionPoolEnvSchema}

+ 2 - 1
src/components/organisms/MinionPoolModal/MinionPoolModalContent.tsx

@@ -123,6 +123,7 @@ type Props = {
   envSchema: Field[],
   invalidFields: string[],
   endpoint: Endpoint
+  platform: 'source' | 'destination'
   getFieldValue: (field: Field | null | undefined) => any,
   onFieldChange: (field: Field | null, value: any) => void,
   disabled: boolean,
@@ -202,7 +203,7 @@ class MinionPoolModalContent extends React.Component<Props, State> {
       let currentField
       if (field.name === 'endpoint_id') {
         currentField = this.renderEndpoint()
-      } else if (field.name === 'platform' || field.name === 'os_type') {
+      } else if (field.name === 'platform' || (field.name === 'os_type' && this.props.platform === 'source')) {
         currentField = this.renderReadOnlyField(field)
       } else {
         currentField = (

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 14 - 42
src/components/organisms/MinionPoolModal/images/minion-pool.svg


+ 1 - 1
src/components/organisms/Navigation/Navigation.tsx

@@ -37,7 +37,7 @@ import projectImage from './images/project-menu.svg'
 import userImage from './images/user-menu.svg'
 import logsImage from './images/logs-menu.svg'
 import dashboardImage from './images/dashboard-menu.svg'
-import minionPoolsImage from './images/minion-pools-menu.svg'
+import minionPoolsImage from './images/minion-pool-menu.svg'
 
 const isCollapsed = (props: any) => props.collapsed
   || (window.outerWidth <= StyleProps.mobileMaxWidth)

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 61 - 0
src/components/organisms/Navigation/images/minion-pool-menu.svg


+ 0 - 15
src/components/organisms/Navigation/images/minion-pools-menu.svg

@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns="http://www.w3.org/2000/svg"
-   viewBox="0 0 6.3499999 6.3500002"
-   height="24"
-   width="24">
-  <g
-     transform="scale(0.89) translate(0.5 0.2)"
-     >
-    <path
-       id="path833"
-       style="fill:#feffff;fill-opacity:1;stroke-width:0.3175"
-       d="M 3.9567384,1.4287455 V 0.64703203 H 2.3932744 V 1.42875 Z M 0.48827166,2.234522 v 3.1509535 c 0,0.1746256 0.1428877,0.3175127 0.31751267,0.3175127 H 5.5442279 c 0.174625,0 0.3175127,-0.1428871 0.3175127,-0.3175127 V 2.234522 c 0,-0.1746251 -0.1428877,-0.3175128 -0.3175127,-0.3175128 H 0.80578433 c -0.17462497,0 -0.31751267,0.1428877 -0.31751267,0.3175128 z M 5.715,1.42875 c 0.352425,0 0.635,0.282575 0.635,0.635 v 3.4925001 c 0,0.3524247 -0.282575,0.635 -0.635,0.635 H 0.63500003 C 0.28257503,6.1912501 0,5.9086748 0,5.5562501 L 0.00317498,2.06375 c 0,-0.352425 0.27940005,-0.635 0.63182505,-0.635 H 1.9050001 V 0.79375013 C 1.9050001,0.44132511 2.1875751,0.15875 2.5400002,0.15875 H 3.8100003 C 4.162425,0.15875 4.445,0.44132511 4.445,0.79375013 V 1.42875 Z" />
-  </g>
-</svg>

+ 12 - 4
src/components/pages/MinionPoolDetailsPage/MinionPoolDetailsPage.tsx

@@ -78,6 +78,7 @@ class MinionPoolDetailsPage extends React.Component<Props, State> {
   }
 
   componentWillUnmount() {
+    minionPoolStore.clearMinionPoolDetails()
     this.stopPolling = true
   }
 
@@ -101,6 +102,8 @@ class MinionPoolDetailsPage extends React.Component<Props, State> {
     await Promise.all([
       endpointStore.getEndpoints({ showLoading: true }),
       minionPoolStore.loadMinionPoolDetails(this.minionPoolId, { showLoading: true }),
+      replicaStore.getReplicas(),
+      migrationStore.getMigrations(),
     ])
     const minionPool = this.minionPool
     if (!minionPool) {
@@ -158,10 +161,14 @@ class MinionPoolDetailsPage extends React.Component<Props, State> {
       return
     }
 
-    await minionPoolStore.loadMinionPoolDetails(this.minionPoolId, {
-      showLoading,
-      skipLog: true,
-    })
+    await Promise.all([
+      minionPoolStore.loadMinionPoolDetails(this.minionPoolId, {
+        showLoading,
+        skipLog: true,
+      }),
+      replicaStore.getReplicas(),
+      migrationStore.getMigrations(),
+    ])
 
     setTimeout(() => { this.pollData(false) }, configLoader.config.requestPollTimeout)
   }
@@ -312,6 +319,7 @@ class MinionPoolDetailsPage extends React.Component<Props, State> {
           contentComponent={(
             <MinionPoolDetailsContent
               item={this.minionPool}
+              itemId={this.minionPoolId}
               replicas={replicaStore.replicas
                 .filter(r => r.origin_minion_pool_id === this.minionPool?.id
                   || r.destination_minion_pool_id === this.minionPool?.id)}

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 19 - 75
src/components/pages/MinionPoolDetailsPage/images/minion-pool.svg


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 17 - 34
src/components/pages/MinionPoolsPage/images/minion-pool-empty-list.svg


+ 9 - 0
src/sources/MinionPoolSource.ts

@@ -64,6 +64,15 @@ class MinionPoolSource {
         required: true,
         title: 'Pool OS Type',
         default: 'linux',
+        enum: [
+          {
+            label: 'Linux',
+            value: 'linux',
+          }, {
+            label: 'Windows',
+            value: 'windows',
+          },
+        ],
       },
       {
         name: 'minimum_minions',

+ 4 - 6
src/sources/WizardSource.ts

@@ -53,17 +53,15 @@ class WizardSource {
 
     if (data.sourceOptions) {
       const sourceEnv = sourceParser.getDestinationEnv(data.sourceOptions)
-      if (sourceEnv.minion_pool_id) {
-        payload[type].origin_minion_pool_id = sourceEnv.minion_pool_id
-        delete sourceEnv.minion_pool_id
+      if (data.sourceOptions.minion_pool_id) {
+        payload[type].origin_minion_pool_id = data.sourceOptions.minion_pool_id
       }
       payload[type].source_environment = sourceEnv
     }
 
     const destEnv = destParser.getDestinationEnv(data.destOptions)
-    if (destEnv.minion_pool_id) {
-      payload[type].destination_minion_pool_id = destEnv.minion_pool_id
-      delete destEnv.minion_pool_id
+    if (data.destOptions?.minion_pool_id) {
+      payload[type].destination_minion_pool_id = data.destOptions.minion_pool_id
     }
 
     const poolMappings = destEnv[INSTANCE_OSMORPHING_MINION_POOL_MAPPINGS]

+ 4 - 0
src/stores/MinionPoolStore.ts

@@ -98,6 +98,10 @@ class MinionPoolStore {
     }
   }
 
+  @action clearMinionPoolDetails() {
+    this.minionPoolDetails = null
+  }
+
   @action
   async loadMinionPoolSchema(provider: ProviderTypes, platform: 'source' | 'destination') {
     this.loadingMinionPoolSchema = true

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio