Просмотр исходного кода

Merge pull request #2207 from porter-dev/nico/stacks-fe-fixes

Stacks Fixes
abelanger5 3 лет назад
Родитель
Сommit
50a91396bb

+ 9 - 6
api/types/stacks.go

@@ -71,6 +71,9 @@ type Stack struct {
 	// The display name of the stack
 	Name string `json:"name"`
 
+	// The namespace that the stack was deployed to
+	Namespace string `json:"namespace"`
+
 	// A unique id for the stack
 	ID string `json:"id"`
 
@@ -190,13 +193,13 @@ type StackSourceConfig struct {
 // swagger:model
 type CreateStackSourceConfigRequest struct {
 	// required: true
-	Name string `json:"name"`
+	Name string `json:"name" form:"required"`
 
 	// required: true
-	ImageRepoURI string `json:"image_repo_uri"`
+	ImageRepoURI string `json:"image_repo_uri" form:"required"`
 
 	// required: true
-	ImageTag string `json:"image_tag"`
+	ImageTag string `json:"image_tag" form:"required"`
 
 	// If this field is empty, the resource is deployed directly from the image repo uri
 	StackSourceConfigBuild *StackSourceConfigBuild `json:"build,omitempty"`
@@ -205,13 +208,13 @@ type CreateStackSourceConfigRequest struct {
 // swagger:model
 type UpdateStackSourceConfigRequest struct {
 	// required: true
-	Name string `json:"name"`
+	Name string `json:"name" form:"required"`
 
 	// required: true
-	ImageRepoURI string `json:"image_repo_uri"`
+	ImageRepoURI string `json:"image_repo_uri" form:"required"`
 
 	// required: true
-	ImageTag string `json:"image_tag"`
+	ImageTag string `json:"image_tag" form:"required"`
 }
 
 type StackSourceConfigBuild struct {

+ 26 - 7
dashboard/src/main/home/cluster-dashboard/stacks/ExpandedStack/ExpandedStack.tsx

@@ -17,6 +17,7 @@ import {
   InfoWrapper,
   LastDeployed,
   LineBreak,
+  NamespaceTag,
   SepDot,
   Text,
 } from "../components/styles";
@@ -79,13 +80,19 @@ const ExpandedStack = () => {
 
   return (
     <div>
-      <TitleSection
-        materialIconClass="material-icons-outlined"
-        icon={"lan"}
-        capitalize
-      >
-        {stack.name}
-      </TitleSection>
+      <StackTitleWrapper>
+        <TitleSection
+          materialIconClass="material-icons-outlined"
+          icon={"lan"}
+          capitalize
+        >
+          {stack.name}
+        </TitleSection>
+        <NamespaceTag.Wrapper>
+          Namespace
+          <NamespaceTag.Tag>{stack.namespace}</NamespaceTag.Tag>
+        </NamespaceTag.Wrapper>
+      </StackTitleWrapper>
       <RevisionList
         revisions={stack.revisions}
         currentRevision={currentRevision}
@@ -222,3 +229,15 @@ const StackErrorMessageStyles = {
     font-weight: bold;
   `,
 };
+
+const StackTitleWrapper = styled.div`
+  width: 100%;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+
+  // Hotfix to make sure the title section and the namespace tag are aligned
+  ${NamespaceTag.Wrapper} {
+    margin-bottom: 15px;
+  }
+`;

+ 4 - 1
dashboard/src/main/home/cluster-dashboard/stacks/ExpandedStack/_RevisionList.tsx

@@ -168,6 +168,8 @@ const _RevisionList = ({
 export default _RevisionList;
 
 const StyledRevisionSection = styled.div`
+  display: flex;
+  flex-direction: column;
   position: relative;
   width: 100%;
   max-height: ${(props: { showRevisions: boolean }) =>
@@ -195,7 +197,7 @@ const RevisionHeader = styled.div`
   display: flex;
   justify-content: space-between;
   align-items: center;
-  height: 40px;
+  min-height: 40px;
   font-size: 13px;
   width: 100%;
   padding-left: 15px;
@@ -228,6 +230,7 @@ const RevisionPreview = styled.div`
 
 const TableWrapper = styled.div`
   padding-bottom: 20px;
+  overflow-y: auto;
 `;
 
 const RevisionsTable = styled.table`

+ 11 - 5
dashboard/src/main/home/cluster-dashboard/stacks/ExpandedStack/components/Select.tsx

@@ -75,6 +75,16 @@ const Select = <T extends unknown>({
     );
   }
 
+  const isSelected = (option: T, value: T) => {
+    if (!value) {
+      return false;
+    }
+
+    if (isOptionEqualToValue) {
+      return isOptionEqualToValue(option, value);
+    }
+  };
+
   return (
     <div>
       {getLabel()}
@@ -107,11 +117,7 @@ const Select = <T extends unknown>({
                     key={i}
                     onClick={() => !readOnly && handleOptionClick(option)}
                     lastItem={i === options.length - 1}
-                    selected={
-                      isOptionEqualToValue
-                        ? isOptionEqualToValue(option, value)
-                        : option === value
-                    }
+                    selected={isSelected(option, value)}
                     height={dropdown?.option?.height}
                   >
                     {accessor(option)}

+ 1 - 1
dashboard/src/main/home/cluster-dashboard/stacks/ExpandedStack/components/SourceEditorDocker.tsx

@@ -148,7 +148,7 @@ const _DockerRepositorySelector = ({
         accessor={(val) => val.name}
         label="Docker Registry"
         placeholder="Select a registry"
-        isOptionEqualToValue={(a, b) => a.url === b.url}
+        isOptionEqualToValue={(a, b) => a?.url === b?.url}
         readOnly={readOnly}
         isLoading={isLoading}
         dropdown={{

+ 25 - 9
dashboard/src/main/home/cluster-dashboard/stacks/_StackList.tsx

@@ -13,6 +13,7 @@ import {
   Flex,
   InfoWrapper,
   LastDeployed,
+  NamespaceTag,
   SepDot,
   Text,
 } from "./components/styles";
@@ -80,6 +81,10 @@ const StackList = ({ namespace }: { namespace: string }) => {
           setIsLoading(false);
         }
       });
+
+    return () => {
+      isSubscribed = false;
+    };
   }, [namespace]);
 
   if (isLoading) {
@@ -104,16 +109,22 @@ const StackList = ({ namespace }: { namespace: string }) => {
           <StackCard
             as={DynamicLink}
             key={stack?.id}
-            to={`/stacks/${namespace}/${stack?.id}`}
+            to={`/stacks/${stack?.namespace}/${stack?.id}`}
           >
             <DataContainer>
-              <StackName>
-                <StackIcon>
-                  <i className="material-icons-outlined">lan</i>
-                </StackIcon>
-                <span>{stack.name}</span>
-              </StackName>
-
+              <Top>
+                <StackName>
+                  <StackIcon>
+                    <i className="material-icons-outlined">lan</i>
+                  </StackIcon>
+                  <span>{stack.name}</span>
+                </StackName>
+                <SepDot>•</SepDot>
+                <NamespaceTag.Wrapper>
+                  Namespace
+                  <NamespaceTag.Tag>{stack.namespace}</NamespaceTag.Tag>
+                </NamespaceTag.Wrapper>
+              </Top>
               <InfoWrapper>
                 <LastDeployed>
                   <Status
@@ -200,7 +211,6 @@ const StackName = styled.div`
   display: flex;
   font-size: 14px;
   align-items: center;
-  margin-bottom: 10px;
 `;
 
 const DataContainer = styled.div`
@@ -215,3 +225,9 @@ const StackCard = styled(Card)`
   font-size: 13px;
   font-weight: 500;
 `;
+
+const Top = styled.div`
+  display: flex;
+  align-items: center;
+  margin-bottom: 10px;
+`;

+ 33 - 0
dashboard/src/main/home/cluster-dashboard/stacks/components/styles.ts

@@ -96,3 +96,36 @@ export const Flex = styled.div`
   display: flex;
   align-items: center;
 `;
+
+export const NamespaceTag = {
+  Wrapper: styled.div`
+    height: 20px;
+    font-size: 12px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    color: #ffffff44;
+    border: 1px solid #ffffff44;
+    border-radius: 3px;
+    padding-left: 5px;
+  `,
+
+  Tag: styled.div`
+    height: 20px;
+    margin-left: 6px;
+    color: #aaaabb;
+    background: #ffffff22;
+    border-radius: 3px;
+    font-size: 12px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding: 0px 6px;
+    padding-left: 7px;
+    border-top-left-radius: 0px;
+    border-bottom-left-radius: 0px;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+  `,
+};

+ 1 - 0
dashboard/src/main/home/cluster-dashboard/stacks/types.ts

@@ -31,6 +31,7 @@ export type Stack = {
   name: string;
   created_at: string;
   updated_at: string;
+  namespace: string;
 
   revisions: StackRevision[];
 

+ 1 - 0
internal/models/stack.go

@@ -39,6 +39,7 @@ func (s *Stack) ToStackType() *types.Stack {
 		CreatedAt:      s.CreatedAt,
 		UpdatedAt:      s.UpdatedAt,
 		Name:           s.Name,
+		Namespace:      s.Namespace,
 		ID:             s.UID,
 		LatestRevision: latestRevision,
 		Revisions:      revisions,

+ 16 - 0
internal/repository/gorm/stack.go

@@ -74,6 +74,22 @@ func (repo *StackRepository) ListStacks(projectID, clusterID uint, namespace str
 	return stacks, nil
 }
 
+func (repo *StackRepository) ReadStackByID(projectID, stackID uint) (*models.Stack, error) {
+	stack := &models.Stack{}
+
+	if err := repo.db.
+		Preload("Revisions", func(db *gorm.DB) *gorm.DB {
+			return db.Order("stack_revisions.revision_number DESC").Limit(100)
+		}).
+		Preload("Revisions.Resources").
+		Preload("Revisions.SourceConfigs").
+		Where("stacks.project_id = ? AND stacks.id = ?", projectID, stackID).First(&stack).Error; err != nil {
+		return nil, err
+	}
+
+	return stack, nil
+}
+
 // ReadStack gets a stack specified by its string id
 func (repo *StackRepository) ReadStackByStringID(projectID uint, stackID string) (*models.Stack, error) {
 	stack := &models.Stack{}

+ 1 - 0
internal/repository/stack.go

@@ -5,6 +5,7 @@ import "github.com/porter-dev/porter/internal/models"
 // StackRepository represents the set of queries on the Stack model
 type StackRepository interface {
 	CreateStack(stack *models.Stack) (*models.Stack, error)
+	ReadStackByID(projectID, stackID uint) (*models.Stack, error)
 	ReadStackByStringID(projectID uint, stackID string) (*models.Stack, error)
 	ListStacks(projectID uint, clusterID uint, namespace string) ([]*models.Stack, error)
 	DeleteStack(stack *models.Stack) (*models.Stack, error)

+ 4 - 0
internal/repository/test/stack.go

@@ -21,6 +21,10 @@ func (repo *StackRepository) ListStacks(projectID, clusterID uint, namespace str
 	panic("unimplemented")
 }
 
+func (repo *StackRepository) ReadStackByID(projectID, stackID uint) (*models.Stack, error) {
+	panic("unimplemented")
+}
+
 // ReadStack gets a stack specified by its string id
 func (repo *StackRepository) ReadStackByStringID(projectID uint, stackID string) (*models.Stack, error) {
 	panic("unimplemented")

+ 18 - 2
internal/stacks/hooks.go

@@ -1,6 +1,8 @@
 package stacks
 
 import (
+	"fmt"
+
 	"github.com/porter-dev/porter/api/server/shared/config"
 	"gorm.io/gorm"
 	"helm.sh/helm/v3/pkg/release"
@@ -24,13 +26,27 @@ func UpdateHelmRevision(config *config.Config, projID, clusterID uint, rel *rele
 		return err
 	}
 
-	// read the revision number and create a new revision of the stack
-	stackRevision, err := config.Repo.Stack().ReadStackRevision(stackResource.StackRevisionID)
+	// read the revision number corresponding and create a new revision of the stack
+	oldStackRevision, err := config.Repo.Stack().ReadStackRevision(stackResource.StackRevisionID)
 
 	if err != nil {
 		return err
 	}
 
+	// get the latest revision for that stack
+	stack, err := config.Repo.Stack().ReadStackByID(projID, oldStackRevision.StackID)
+
+	if err != nil {
+		return err
+	}
+
+	if len(stack.Revisions) == 0 {
+		return fmt.Errorf("length of stack revision list was 0")
+	}
+
+	currStackRevision := stack.Revisions[0]
+	stackRevision := &currStackRevision
+
 	clonedSourceConfigs, err := CloneSourceConfigs(stackRevision.SourceConfigs)
 
 	if err != nil {