From cd12a0ecf9aafc7ad673edfc76826369b6854efe Mon Sep 17 00:00:00 2001 From: "jan.hajek@zerops.io" Date: Wed, 21 Feb 2024 17:22:56 +0100 Subject: [PATCH] new styles --- .golangci.yaml | 2 - Makefile | 6 +- go.sum | 4 + src/archiveClient/handler_findFilesByRules.go | 7 +- .../handler_findFilesByRules_test.go | 2 +- src/archiveClient/handler_tarFile.go | 1 + src/cmd/login.go | 3 +- src/cmd/projectImport.go | 9 +- src/cmd/projectServiceImport.go | 7 +- src/cmd/root.go | 16 +- src/cmd/scopeProject.go | 7 +- src/cmd/scopeReset.go | 3 +- src/cmd/serviceDeploy.go | 5 +- src/cmd/servicePush.go | 9 +- src/cmd/servicePushDeployShared.go | 3 +- src/cmd/statusInfo.go | 3 +- src/cmd/statusShowDebugLogs.go | 3 +- src/cmdBuilder/cmdBuilderCreateRunFunc.go | 40 ++-- src/cmdBuilder/cmdBuilderExecuteRootCmd.go | 32 +++ src/cmdBuilder/dependencyTreeProject.go | 5 +- src/cmdBuilder/dependencyTreeService.go | 4 +- src/constants/darwin.go | 34 +--- src/constants/linux.go | 34 +--- src/constants/windows.go | 33 +--- src/constants/zerops.go | 72 +++++-- src/i18n/en.go | 15 +- src/i18n/i18n.go | 5 + src/logger/handler.go | 11 +- src/params/handler.go | 18 +- src/storage/handler.go | 4 +- src/uxBlock/blocks.go | 11 +- src/uxBlock/logs.go | 42 ++-- src/uxBlock/mocks/blocks.go | 172 ++++++---------- src/uxBlock/prompt.go | 32 +-- src/uxBlock/select.go | 59 +++--- src/uxBlock/showcase/main.go | 57 +++--- src/uxBlock/spinner.go | 21 +- src/uxBlock/styles.go | 108 ---------- src/uxBlock/styles/helpers.go | 47 +++++ src/uxBlock/styles/line.go | 50 +++++ src/uxBlock/styles/styles.go | 186 ++++++++++++++++++ src/uxBlock/table.go | 30 +-- src/uxHelpers/org.go | 3 +- src/uxHelpers/project.go | 3 +- src/uxHelpers/service.go | 3 +- src/uxHelpers/spinner.go | 7 +- src/yamlReader/readYaml.go | 5 +- 47 files changed, 672 insertions(+), 561 deletions(-) delete mode 100644 src/uxBlock/styles.go create mode 100644 src/uxBlock/styles/helpers.go create mode 100644 src/uxBlock/styles/line.go create mode 100644 src/uxBlock/styles/styles.go diff --git a/.golangci.yaml b/.golangci.yaml index 8e2a1795..cd6e5101 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -68,7 +68,6 @@ linters: - ifshort - importas - ineffassign - - interfacebloat - interfacer - loggercheck - maintidx @@ -80,7 +79,6 @@ linters: - nestif - nilerr - noctx - - nolintlint - nosprintfhostport - perfsprint - prealloc diff --git a/Makefile b/Makefile index e469439f..9c52e7e5 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,9 @@ help: @printf "possible values: test, lint" test: - go test -v ./cmd/... ./src/... + go test -v ./cmd/... ./src/... lint: - gomodrun golangci-lint run ./cmd/... ./src/... --verbose \ No newline at end of file + GOOS=darwin GOARCH=arm64 gomodrun golangci-lint run ./cmd/... ./src/... --verbose + GOOS=linux GOARCH=amd64 gomodrun golangci-lint run ./cmd/... ./src/... --verbose + GOOS=windows GOARCH=amd64 gomodrun golangci-lint run ./cmd/... ./src/... --verbose \ No newline at end of file diff --git a/go.sum b/go.sum index 9aa81e4e..6584cc30 100644 --- a/go.sum +++ b/go.sum @@ -116,6 +116,8 @@ golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= @@ -145,6 +147,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/src/archiveClient/handler_findFilesByRules.go b/src/archiveClient/handler_findFilesByRules.go index 1aa1a0ef..89d841a8 100644 --- a/src/archiveClient/handler_findFilesByRules.go +++ b/src/archiveClient/handler_findFilesByRules.go @@ -8,6 +8,7 @@ import ( "github.com/zeropsio/zcli/src/i18n" "github.com/zeropsio/zcli/src/uxBlock" + "github.com/zeropsio/zcli/src/uxBlock/styles" ) func (h *Handler) FindFilesByRules(uxBlocks uxBlock.UxBlocks, workingDir string, sources []string) ([]File, error) { @@ -16,7 +17,7 @@ func (h *Handler) FindFilesByRules(uxBlocks uxBlock.UxBlocks, workingDir string, return nil, err } - uxBlocks.PrintLine(i18n.T(i18n.ArchClientWorkingDirectory, workingDir)) + uxBlocks.PrintInfo(styles.InfoLine(i18n.T(i18n.ArchClientWorkingDirectory, workingDir))) // resulting function returns File from provided path // if file shouldn't be included in the result, File.ArchivePath will be empty @@ -56,9 +57,9 @@ func (h *Handler) FindFilesByRules(uxBlocks uxBlock.UxBlocks, workingDir string, if fileInfo.IsDir() { source = strings.TrimSuffix(source, string(os.PathSeparator)) + string(os.PathSeparator) - uxBlocks.PrintLine(i18n.T(i18n.ArchClientPackingDirectory, source)) + uxBlocks.PrintInfo(styles.InfoLine(i18n.T(i18n.ArchClientPackingDirectory, source))) } else { - uxBlocks.PrintLine(i18n.T(i18n.ArchClientPackingFile, source)) + uxBlocks.PrintInfo(styles.InfoLine(i18n.T(i18n.ArchClientPackingFile, source))) } trimPath, err := filepath.Abs(filepath.Join(workingDir, parts[0])) diff --git a/src/archiveClient/handler_findFilesByRules_test.go b/src/archiveClient/handler_findFilesByRules_test.go index c19e63c7..6de1eae7 100644 --- a/src/archiveClient/handler_findFilesByRules_test.go +++ b/src/archiveClient/handler_findFilesByRules_test.go @@ -223,7 +223,7 @@ var testErrorResponseDataProvider = []struct { func TestValidation(t *testing.T) { ctrl := gomock.NewController(t) uxBlocks := mocks.NewMockUxBlocks(ctrl) - uxBlocks.EXPECT().PrintLine(gomock.Any()).AnyTimes() + uxBlocks.EXPECT().PrintInfo(gomock.Any()).AnyTimes() for _, test := range testErrorResponseDataProvider { test := test // scope lint diff --git a/src/archiveClient/handler_tarFile.go b/src/archiveClient/handler_tarFile.go index 7bd9f187..8c9b6c7c 100644 --- a/src/archiveClient/handler_tarFile.go +++ b/src/archiveClient/handler_tarFile.go @@ -32,6 +32,7 @@ func tarFile(archive *tar.Writer, file File, info os.FileInfo) error { return err } + //nolint:exhaustive // Why: Other file types are not supported switch mode := info.Mode(); mode & os.ModeType { case os.ModeDir, os.ModeSymlink: return nil diff --git a/src/cmd/login.go b/src/cmd/login.go index 0fd65cc7..f6e3a70e 100644 --- a/src/cmd/login.go +++ b/src/cmd/login.go @@ -12,6 +12,7 @@ import ( "github.com/zeropsio/zcli/src/i18n" "github.com/zeropsio/zcli/src/region" "github.com/zeropsio/zcli/src/uxBlock" + "github.com/zeropsio/zcli/src/uxBlock/styles" "github.com/zeropsio/zcli/src/zeropsRestApiClient" ) @@ -59,7 +60,7 @@ func loginCmd() *cmdBuilder.Cmd { return err } - uxBlocks.PrintSuccessLine(i18n.T(i18n.LoginSuccess, output.FullName, output.Email)) + uxBlocks.PrintInfo(styles.SuccessLine(i18n.T(i18n.LoginSuccess, output.FullName, output.Email))) return nil }) diff --git a/src/cmd/projectImport.go b/src/cmd/projectImport.go index 0428bf37..bbdb382a 100644 --- a/src/cmd/projectImport.go +++ b/src/cmd/projectImport.go @@ -6,6 +6,7 @@ import ( "github.com/zeropsio/zcli/src/cmdBuilder" "github.com/zeropsio/zcli/src/entity/repository" "github.com/zeropsio/zcli/src/i18n" + "github.com/zeropsio/zcli/src/uxBlock/styles" "github.com/zeropsio/zcli/src/uxHelpers" "github.com/zeropsio/zcli/src/yamlReader" "github.com/zeropsio/zerops-go/dto/input/body" @@ -69,16 +70,16 @@ func projectImportCmd() *cmdBuilder.Cmd { } } - uxBlocks.PrintLine(i18n.T(i18n.ServiceCount, len(responseOutput.ServiceStacks))) - uxBlocks.PrintLine(i18n.T(i18n.QueuedProcesses, len(processes))) - uxBlocks.PrintLine(i18n.T(i18n.CoreServices)) + uxBlocks.PrintInfo(styles.InfoLine(i18n.T(i18n.ServiceCount, len(responseOutput.ServiceStacks)))) + uxBlocks.PrintInfo(styles.InfoLine(i18n.T(i18n.QueuedProcesses, len(processes)))) + uxBlocks.PrintInfo(styles.InfoLine(i18n.T(i18n.CoreServices))) err = uxHelpers.ProcessCheckWithSpinner(ctx, cmdData.UxBlocks, processes) if err != nil { return err } - uxBlocks.PrintInfoLine(i18n.T(i18n.ProjectImported)) + uxBlocks.PrintInfo(styles.InfoLine(i18n.T(i18n.ProjectImported))) return nil }) diff --git a/src/cmd/projectServiceImport.go b/src/cmd/projectServiceImport.go index 6e984ec7..73889886 100644 --- a/src/cmd/projectServiceImport.go +++ b/src/cmd/projectServiceImport.go @@ -5,6 +5,7 @@ import ( "github.com/zeropsio/zcli/src/cmdBuilder" "github.com/zeropsio/zcli/src/i18n" + "github.com/zeropsio/zcli/src/uxBlock/styles" "github.com/zeropsio/zcli/src/uxHelpers" "github.com/zeropsio/zcli/src/yamlReader" "github.com/zeropsio/zerops-go/dto/input/body" @@ -56,15 +57,15 @@ func projectServiceImportCmd() *cmdBuilder.Cmd { } } - uxBlocks.PrintLine(i18n.T(i18n.ServiceCount, len(responseOutput.ServiceStacks))) - uxBlocks.PrintLine(i18n.T(i18n.QueuedProcesses, len(processes))) + uxBlocks.PrintInfo(styles.InfoLine(i18n.T(i18n.ServiceCount, len(responseOutput.ServiceStacks)))) + uxBlocks.PrintInfo(styles.InfoLine(i18n.T(i18n.QueuedProcesses, len(processes)))) err = uxHelpers.ProcessCheckWithSpinner(ctx, cmdData.UxBlocks, processes) if err != nil { return err } - uxBlocks.PrintInfoLine(i18n.T(i18n.ServiceImported)) + uxBlocks.PrintInfo(styles.InfoLine(i18n.T(i18n.ServiceImported))) return nil }) diff --git a/src/cmd/root.go b/src/cmd/root.go index 2e6c18cf..33cb2bdd 100644 --- a/src/cmd/root.go +++ b/src/cmd/root.go @@ -5,14 +5,14 @@ import ( ) func ExecuteCmd() error { - cmdBuilder := cmdBuilder.NewCmdBuilder() + builder := cmdBuilder.NewCmdBuilder() - cmdBuilder.AddCommand(loginCmd()) - cmdBuilder.AddCommand(versionCmd()) - cmdBuilder.AddCommand(scopeCmd()) - cmdBuilder.AddCommand(projectCmd()) - cmdBuilder.AddCommand(serviceCmd()) - cmdBuilder.AddCommand(statusCmd()) + builder.AddCommand(loginCmd()) + builder.AddCommand(versionCmd()) + builder.AddCommand(scopeCmd()) + builder.AddCommand(projectCmd()) + builder.AddCommand(serviceCmd()) + builder.AddCommand(statusCmd()) - return cmdBuilder.CreateAndExecuteRootCobraCmd() + return builder.CreateAndExecuteRootCobraCmd() } diff --git a/src/cmd/scopeProject.go b/src/cmd/scopeProject.go index 0a7f8007..91890fc6 100644 --- a/src/cmd/scopeProject.go +++ b/src/cmd/scopeProject.go @@ -9,6 +9,7 @@ import ( "github.com/zeropsio/zcli/src/entity/repository" "github.com/zeropsio/zcli/src/errorsx" "github.com/zeropsio/zcli/src/i18n" + "github.com/zeropsio/zcli/src/uxBlock/styles" "github.com/zeropsio/zcli/src/uxHelpers" "github.com/zeropsio/zerops-go/types/uuid" ) @@ -26,9 +27,9 @@ func scopeProjectCmd() *cmdBuilder.Cmd { if !errorsx.IsUserError(err) { return err } - cmdData.UxBlocks.PrintWarningLine(i18n.T(i18n.ScopedProjectNotFound)) + cmdData.UxBlocks.PrintWarning(styles.WarningLine(i18n.T(i18n.ScopedProjectNotFound))) } else { - cmdData.UxBlocks.PrintInfoLine(i18n.T(i18n.PreviouslyScopedProject, project.Name.String())) + cmdData.UxBlocks.PrintInfo(styles.InfoWithValueLine(i18n.T(i18n.PreviouslyScopedProject), project.Name.String())) } } @@ -57,7 +58,7 @@ func scopeProjectCmd() *cmdBuilder.Cmd { return err } - cmdData.UxBlocks.PrintInfoLine(i18n.T(infoText, project.Name.String())) + cmdData.UxBlocks.PrintInfo(styles.InfoWithValueLine(i18n.T(infoText), project.Name.String())) return nil }) diff --git a/src/cmd/scopeReset.go b/src/cmd/scopeReset.go index bfb23dcc..2efdcddc 100644 --- a/src/cmd/scopeReset.go +++ b/src/cmd/scopeReset.go @@ -6,6 +6,7 @@ import ( "github.com/zeropsio/zcli/src/cliStorage" "github.com/zeropsio/zcli/src/cmdBuilder" "github.com/zeropsio/zcli/src/i18n" + "github.com/zeropsio/zcli/src/uxBlock/styles" "github.com/zeropsio/zerops-go/types/uuid" ) @@ -22,7 +23,7 @@ func scopeResetCmd() *cmdBuilder.Cmd { return err } - cmdData.UxBlocks.PrintInfoLine(i18n.T(i18n.ScopeReset)) + cmdData.UxBlocks.PrintInfo(styles.InfoLine(i18n.T(i18n.ScopeReset))) return nil }) diff --git a/src/cmd/serviceDeploy.go b/src/cmd/serviceDeploy.go index 8cc8e3ca..1f08bbac 100644 --- a/src/cmd/serviceDeploy.go +++ b/src/cmd/serviceDeploy.go @@ -10,6 +10,7 @@ import ( "github.com/zeropsio/zcli/src/cmdBuilder" "github.com/zeropsio/zcli/src/httpClient" "github.com/zeropsio/zcli/src/i18n" + "github.com/zeropsio/zcli/src/uxBlock/styles" "github.com/zeropsio/zcli/src/uxHelpers" "github.com/zeropsio/zerops-go/dto/input/body" "github.com/zeropsio/zerops-go/dto/input/path" @@ -50,7 +51,7 @@ func serviceDeployCmd() *cmdBuilder.Cmd { return err } - uxBlocks.PrintInfoLine(i18n.T(i18n.BuildDeployCreatingPackageStart)) + uxBlocks.PrintInfo(styles.InfoLine(i18n.T(i18n.BuildDeployCreatingPackageStart))) files, err := arch.FindFilesByRules( uxBlocks, @@ -127,7 +128,7 @@ func serviceDeployCmd() *cmdBuilder.Cmd { return err } - uxBlocks.PrintInfoLine(i18n.T(i18n.BuildDeployDeployingStart)) + uxBlocks.PrintInfo(styles.InfoLine(i18n.T(i18n.BuildDeployDeployingStart))) deployResponse, err := cmdData.RestApiClient.PutAppVersionDeploy( ctx, diff --git a/src/cmd/servicePush.go b/src/cmd/servicePush.go index 55670695..18579931 100644 --- a/src/cmd/servicePush.go +++ b/src/cmd/servicePush.go @@ -10,6 +10,7 @@ import ( "github.com/zeropsio/zcli/src/cmdBuilder" "github.com/zeropsio/zcli/src/httpClient" "github.com/zeropsio/zcli/src/i18n" + "github.com/zeropsio/zcli/src/uxBlock/styles" "github.com/zeropsio/zcli/src/uxHelpers" "github.com/zeropsio/zerops-go/dto/input/body" "github.com/zeropsio/zerops-go/dto/input/path" @@ -36,7 +37,7 @@ func servicePushCmd() *cmdBuilder.Cmd { DeployGitFolder: cmdData.Params.GetBool("deployGitFolder"), }) - uxBlocks.PrintInfoLine(i18n.T(i18n.BuildDeployCreatingPackageStart)) + uxBlocks.PrintInfo(styles.InfoLine(i18n.T(i18n.BuildDeployCreatingPackageStart))) configContent, err := getValidConfigContent( uxBlocks, @@ -123,13 +124,13 @@ func servicePushCmd() *cmdBuilder.Cmd { return err } - uxBlocks.PrintInfoLine(i18n.T(i18n.BuildDeployCreatingPackageDone)) + uxBlocks.PrintInfo(styles.InfoLine(i18n.T(i18n.BuildDeployCreatingPackageDone))) if cmdData.Params.GetString("archiveFilePath") != "" { - uxBlocks.PrintInfoLine(i18n.T(i18n.BuildDeployPackageSavedInto, cmdData.Params.GetString("archiveFilePath"))) + uxBlocks.PrintInfo(styles.InfoLine(i18n.T(i18n.BuildDeployPackageSavedInto, cmdData.Params.GetString("archiveFilePath")))) } - uxBlocks.PrintInfoLine(i18n.T(i18n.BuildDeployDeployingStart)) + uxBlocks.PrintInfo(styles.InfoLine(i18n.T(i18n.BuildDeployDeployingStart))) sourceName := cmdData.Params.GetString("source") if sourceName == "" { diff --git a/src/cmd/servicePushDeployShared.go b/src/cmd/servicePushDeployShared.go index 4cb37dcf..6acc2d11 100644 --- a/src/cmd/servicePushDeployShared.go +++ b/src/cmd/servicePushDeployShared.go @@ -12,6 +12,7 @@ import ( "github.com/zeropsio/zcli/src/httpClient" "github.com/zeropsio/zcli/src/i18n" "github.com/zeropsio/zcli/src/uxBlock" + "github.com/zeropsio/zcli/src/uxBlock/styles" "github.com/zeropsio/zcli/src/zeropsRestApiClient" "github.com/zeropsio/zerops-go/dto/input/body" "github.com/zeropsio/zerops-go/dto/output" @@ -111,7 +112,7 @@ func getValidConfigContent(uxBlocks uxBlock.UxBlocks, workingDir string, zeropsY return nil, err } - uxBlocks.PrintLine(i18n.T(i18n.BuildDeployZeropsYamlFound, zeropsYamlPath)) + uxBlocks.PrintInfo(styles.InfoLine(i18n.T(i18n.BuildDeployZeropsYamlFound, zeropsYamlPath))) if zeropsYamlStat.Size() == 0 { return nil, errors.New(i18n.T(i18n.BuildDeployZeropsYamlEmpty)) diff --git a/src/cmd/statusInfo.go b/src/cmd/statusInfo.go index 3d010fdc..d26d6e52 100644 --- a/src/cmd/statusInfo.go +++ b/src/cmd/statusInfo.go @@ -10,6 +10,7 @@ import ( "github.com/zeropsio/zcli/src/errorsx" "github.com/zeropsio/zcli/src/i18n" "github.com/zeropsio/zcli/src/uxBlock" + "github.com/zeropsio/zcli/src/uxBlock/styles" ) func statusInfoCmd() *cmdBuilder.Cmd { @@ -38,7 +39,7 @@ func statusInfoCmd() *cmdBuilder.Cmd { project, err := repository2.GetProjectById(ctx, cmdData.RestApiClient, projectId) if err != nil { if errorsx.IsUserError(err) { - cmdData.UxBlocks.PrintWarningLine(i18n.T(i18n.ScopedProjectNotFound)) + cmdData.UxBlocks.PrintWarning(styles.WarningLine(i18n.T(i18n.ScopedProjectNotFound))) } return err diff --git a/src/cmd/statusShowDebugLogs.go b/src/cmd/statusShowDebugLogs.go index 5bfdb6e9..70725390 100644 --- a/src/cmd/statusShowDebugLogs.go +++ b/src/cmd/statusShowDebugLogs.go @@ -9,6 +9,7 @@ import ( "github.com/zeropsio/zcli/src/cmdBuilder" "github.com/zeropsio/zcli/src/constants" "github.com/zeropsio/zcli/src/i18n" + "github.com/zeropsio/zcli/src/uxBlock/styles" ) func statusShowDebugLogsCmd() *cmdBuilder.Cmd { @@ -33,7 +34,7 @@ func statusShowDebugLogsCmd() *cmdBuilder.Cmd { filesize := stat.Size() if filesize == 0 { - cmdData.UxBlocks.PrintLine(i18n.T(i18n.DebugLogsNotFound)) + cmdData.UxBlocks.PrintInfo(styles.InfoLine(i18n.T(i18n.DebugLogsNotFound))) return nil } diff --git a/src/cmdBuilder/cmdBuilderCreateRunFunc.go b/src/cmdBuilder/cmdBuilderCreateRunFunc.go index ff70cc62..8d13b4cf 100644 --- a/src/cmdBuilder/cmdBuilderCreateRunFunc.go +++ b/src/cmdBuilder/cmdBuilderCreateRunFunc.go @@ -20,6 +20,7 @@ import ( "github.com/zeropsio/zcli/src/storage" "github.com/zeropsio/zcli/src/support" "github.com/zeropsio/zcli/src/uxBlock" + "github.com/zeropsio/zcli/src/uxBlock/styles" "github.com/zeropsio/zcli/src/zeropsRestApiClient" "github.com/zeropsio/zerops-go/apiError" "golang.org/x/term" @@ -78,11 +79,6 @@ func (b *CmdBuilder) createCmdRunFunc(cmd *Cmd, params *params.Handler) func(*co regSignals(cancel) ctx = support.Context(ctx) - loggerFilePath, err := constants.LogFilePath() - if err != nil { - return errors.New(i18n.T(i18n.LoggerUnableToOpenLogFileWarning)) - } - isTerminal, err := isTerminal() if err != nil { return err @@ -93,11 +89,11 @@ func (b *CmdBuilder) createCmdRunFunc(cmd *Cmd, params *params.Handler) func(*co width = 100 } - outputLogger, debugFileLogger := createLoggers(isTerminal, loggerFilePath) + outputLogger, debugFileLogger := createLoggers(isTerminal) uxBlocks := uxBlock.NewBlock(outputLogger, debugFileLogger, isTerminal, width, cancel) - uxBlocks.PrintDebugLine(fmt.Sprintf("Command: %s", cobraCmd.CommandPath())) + uxBlocks.LogDebug(fmt.Sprintf("Command: %s", cobraCmd.CommandPath())) defer func() { if err != nil { @@ -106,10 +102,8 @@ func (b *CmdBuilder) createCmdRunFunc(cmd *Cmd, params *params.Handler) func(*co } }() - err = params.InitViper() - if err != nil { - return err - } + // TODO - janhajek move somewhere else? + params.InitViper() cliStorage, err := createCliStorage() if err != nil { @@ -195,28 +189,28 @@ func convertArgs(cmd *Cmd, args []string) (map[string][]string, error) { } func printError(err error, uxBlocks uxBlock.UxBlocks) { - uxBlocks.PrintDebugLine(fmt.Sprintf("error: %+v", err)) + uxBlocks.LogDebug(fmt.Sprintf("error: %+v", err)) if userErr := errorsx.AsUserError(err); userErr != nil { - uxBlocks.PrintErrorLine(err.Error()) + uxBlocks.PrintError(styles.ErrorLine(err.Error())) return } var apiErr apiError.Error if errors.As(err, &apiErr) { - uxBlocks.PrintErrorLine(apiErr.GetMessage()) + uxBlocks.PrintError(styles.ErrorLine(apiErr.GetMessage())) if apiErr.GetMeta() != nil { meta, err := yaml.Marshal(apiErr.GetMeta()) if err != nil { - uxBlocks.PrintErrorLine(fmt.Sprintf("couldn't parse meta of error: %s", apiErr.GetMessage())) + uxBlocks.PrintError(styles.ErrorLine(fmt.Sprintf("couldn't parse meta of error: %s", apiErr.GetMessage()))) } - uxBlocks.PrintErrorLine(string(meta)) + uxBlocks.PrintError(styles.ErrorLine(string(meta))) } return } - uxBlocks.PrintErrorLine(err.Error()) + uxBlocks.PrintError(styles.ErrorLine(err.Error())) } func isTerminal() (bool, error) { @@ -228,18 +222,22 @@ func isTerminal() (bool, error) { case TerminalModeEnabled: return true, nil default: - // TODO - janhajek message - return false, errors.New("unknown terminal mode") + return false, errors.New(i18n.T(i18n.UnknownTerminalMode, TerminalFlag)) } } -func createLoggers(isTerminal bool, logFilePathFlag string) (*logger.Handler, *logger.Handler) { +func createLoggers(isTerminal bool) (*logger.Handler, *logger.Handler) { outputLogger := logger.NewOutputLogger(logger.OutputConfig{ IsTerminal: isTerminal, }) + loggerFilePath, err := constants.LogFilePath() + if err != nil { + outputLogger.Warning(styles.WarningLine(err.Error())) + } + debugFileLogger := logger.NewDebugFileLogger(logger.DebugFileConfig{ - FilePath: logFilePathFlag, + FilePath: loggerFilePath, }) return outputLogger, debugFileLogger diff --git a/src/cmdBuilder/cmdBuilderExecuteRootCmd.go b/src/cmdBuilder/cmdBuilderExecuteRootCmd.go index c7e59bf6..b4cb3e34 100644 --- a/src/cmdBuilder/cmdBuilderExecuteRootCmd.go +++ b/src/cmdBuilder/cmdBuilderExecuteRootCmd.go @@ -7,6 +7,7 @@ import ( "github.com/spf13/cobra" "github.com/zeropsio/zcli/src/i18n" "github.com/zeropsio/zcli/src/params" + "github.com/zeropsio/zcli/src/uxBlock/styles" ) type TerminalMode string @@ -63,5 +64,36 @@ func createRootCommand() *cobra.Command { rootCmd.PersistentFlags().StringVar(&TerminalFlag, "terminal", "auto", i18n.T(i18n.TerminalFlag)) + rootCmd.SetHelpTemplate(`` + styles.CobraSectionColor().SetString("Usage:").String() + `{{if .Runnable}} + {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}} + {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}} + +` + styles.CobraSectionColor().SetString("Aliases:").String() + ` + {{.NameAndAliases}}{{end}}{{if .HasExample}} + +` + styles.CobraSectionColor().SetString("Examples:").String() + ` +{{.Example}}{{end}}{{if .HasAvailableSubCommands}}{{$cmds := .Commands}}{{if eq (len .Groups) 0}} + +` + styles.CobraSectionColor().SetString("Available Commands:").String() + `{{range $cmds}}{{if (or .IsAvailableCommand (eq .Name "help"))}} + ` + styles.CobraItemNameColor().SetString("{{rpad .Name .NamePadding }}").String() + ` {{.Short}}{{end}}{{end}}{{else}}{{range $group := .Groups}} + +{{.Title}}{{range $cmds}}{{if (and (eq .GroupID $group.ID) (or .IsAvailableCommand (eq .Name "help")))}} + ` + styles.CobraItemNameColor().SetString("{{rpad .Name .NamePadding }}").String() + ` {{.Short}}{{end}}{{end}}{{end}}{{if not .AllChildCommandsHaveGroup}} + +` + styles.CobraSectionColor().SetString("Additional Commands:").String() + `{{range $cmds}}{{if (and (eq .GroupID "") (or .IsAvailableCommand (eq .Name "help")))}} + ` + styles.CobraItemNameColor().SetString("{{rpad .Name .NamePadding }}").String() + ` {{.Short}}{{end}}{{end}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}} + +` + styles.CobraSectionColor().SetString("Flags:").String() + ` +{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}} + +` + styles.CobraSectionColor().SetString("Global Flags:").String() + ` +{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}} + +` + styles.CobraSectionColor().SetString("Additional help topics:").String() + `{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}} + ` + styles.CobraItemNameColor().SetString("{{rpad .CommandPath .CommandPathPadding}}").String() + ` {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}} + +Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}} +`) + return rootCmd } diff --git a/src/cmdBuilder/dependencyTreeProject.go b/src/cmdBuilder/dependencyTreeProject.go index 43f6eab2..4a682270 100644 --- a/src/cmdBuilder/dependencyTreeProject.go +++ b/src/cmdBuilder/dependencyTreeProject.go @@ -7,6 +7,7 @@ import ( "github.com/zeropsio/zcli/src/entity/repository" "github.com/zeropsio/zcli/src/errorsx" "github.com/zeropsio/zcli/src/i18n" + "github.com/zeropsio/zcli/src/uxBlock/styles" "github.com/zeropsio/zcli/src/uxHelpers" "github.com/zeropsio/zerops-go/types/uuid" ) @@ -33,7 +34,7 @@ func (p *project) LoadSelectedScope(ctx context.Context, cmd *Cmd, cmdData *Logg project, err = repository.GetProjectById(ctx, cmdData.RestApiClient, projectId) if err != nil { if errorsx.IsUserError(err) { - cmdData.UxBlocks.PrintWarningLine(i18n.T(i18n.ScopedProjectNotFound)) + cmdData.UxBlocks.PrintWarning(styles.WarningLine(i18n.T(i18n.ScopedProjectNotFound))) } return err @@ -70,7 +71,7 @@ func (p *project) LoadSelectedScope(ctx context.Context, cmd *Cmd, cmdData *Logg } cmdData.Project = project - cmdData.UxBlocks.PrintInfoLine(i18n.T(infoText, cmdData.Project.Name.String())) + cmdData.UxBlocks.PrintInfo(styles.InfoWithValueLine(i18n.T(infoText), cmdData.Project.Name.String())) return nil } diff --git a/src/cmdBuilder/dependencyTreeService.go b/src/cmdBuilder/dependencyTreeService.go index 7d5083d0..d71dc6e2 100644 --- a/src/cmdBuilder/dependencyTreeService.go +++ b/src/cmdBuilder/dependencyTreeService.go @@ -6,6 +6,7 @@ import ( "github.com/zeropsio/zcli/src/entity" "github.com/zeropsio/zcli/src/entity/repository" "github.com/zeropsio/zcli/src/i18n" + "github.com/zeropsio/zcli/src/uxBlock/styles" "github.com/zeropsio/zcli/src/uxHelpers" "github.com/zeropsio/zerops-go/types/uuid" ) @@ -54,7 +55,6 @@ func (s *service) LoadSelectedScope(ctx context.Context, _ *Cmd, cmdData *Logged } cmdData.Service = service - cmdData.UxBlocks.PrintInfoLine(i18n.T(infoText, cmdData.Service.Name.String())) - + cmdData.UxBlocks.PrintInfo(styles.InfoWithValueLine(i18n.T(infoText), cmdData.Service.Name.String())) return nil } diff --git a/src/constants/darwin.go b/src/constants/darwin.go index 6c8032f5..76bfe572 100644 --- a/src/constants/darwin.go +++ b/src/constants/darwin.go @@ -6,37 +6,21 @@ package constants import ( "os" "path" - - "github.com/pkg/errors" ) -func getDataFilePaths() []pathReceiver { +func getDataFilePathsReceivers() []pathReceiver { return []pathReceiver{ - func() (string, error) { - env := os.Getenv(cliDataFilePathEnvVar) - if env != "" { - return env, nil - } - return "", errors.New("env is empty") - }, - receiverWithPath(os.UserConfigDir, zeropsDir, cliDataFileName), - receiverWithPath(os.UserHomeDir, zeropsDir, cliDataFileName), + receiverFromEnv(cliDataFilePathEnvVar), + receiverFromOsFunc(os.UserConfigDir, zeropsDir, cliDataFileName), + receiverFromOsFunc(os.UserHomeDir, zeropsDir, cliDataFileName), } } -func getLogFilePath() []pathReceiver { +func getLogFilePathReceivers() []pathReceiver { return []pathReceiver{ - func() (string, error) { - env := os.Getenv(cliLogFilePathEnvVar) - if env != "" { - return env, nil - } - return "", errors.New("env is empty") - }, - func() (string, error) { - return path.Join("/usr/local/var/log/", zeropsLogFile), nil - }, - receiverWithPath(os.UserConfigDir, zeropsDir, zeropsLogFile), - receiverWithPath(os.UserHomeDir, zeropsDir, zeropsLogFile), + receiverFromEnv(cliLogFilePathEnvVar), + receiverFromPath(path.Join("/usr/local/var/log/", zeropsLogFile)), + receiverFromOsFunc(os.UserConfigDir, zeropsDir, zeropsLogFile), + receiverFromOsFunc(os.UserHomeDir, zeropsDir, zeropsLogFile), } } diff --git a/src/constants/linux.go b/src/constants/linux.go index 989649e9..7836fb3d 100644 --- a/src/constants/linux.go +++ b/src/constants/linux.go @@ -6,37 +6,21 @@ package constants import ( "os" "path" - - "github.com/pkg/errors" ) -func getDataFilePaths() []pathReceiver { +func getDataFilePathsReceivers() []pathReceiver { return []pathReceiver{ - func() (string, error) { - env := os.Getenv(cliDataFilePathEnvVar) - if env != "" { - return env, nil - } - return "", errors.New("env is empty") - }, - receiverWithPath(os.UserConfigDir, zeropsDir, cliDataFileName), - receiverWithPath(os.UserHomeDir, zeropsDir, cliDataFileName), + receiverFromEnv(cliDataFilePathEnvVar), + receiverFromOsFunc(os.UserConfigDir, zeropsDir, cliDataFileName), + receiverFromOsFunc(os.UserHomeDir, zeropsDir, cliDataFileName), } } -func getLogFilePath() []pathReceiver { +func getLogFilePathReceivers() []pathReceiver { return []pathReceiver{ - func() (string, error) { - env := os.Getenv(cliLogFilePathEnvVar) - if env != "" { - return env, nil - } - return "", errors.New("env is empty") - }, - func() (string, error) { - return path.Join("/var/log/", zeropsDir, zeropsLogFile), nil - }, - receiverWithPath(os.UserConfigDir, zeropsDir, zeropsLogFile), - receiverWithPath(os.UserHomeDir, zeropsDir, zeropsLogFile), + receiverFromEnv(cliLogFilePathEnvVar), + receiverFromPath(path.Join("/var/log/", zeropsLogFile)), + receiverFromOsFunc(os.UserConfigDir, zeropsDir, zeropsLogFile), + receiverFromOsFunc(os.UserHomeDir, zeropsDir, zeropsLogFile), } } diff --git a/src/constants/windows.go b/src/constants/windows.go index ec8e705c..9c20367e 100644 --- a/src/constants/windows.go +++ b/src/constants/windows.go @@ -5,37 +5,24 @@ package constants import ( "os" - - "github.com/pkg/errors" ) -// this line is here to make linter happy +// this is here to make linter happy var _ = zeropsDir +var _ = receiverFromPath -func getDataFilePaths() []pathReceiver { +func getDataFilePathsReceivers() []pathReceiver { return []pathReceiver{ - func() (string, error) { - env := os.Getenv(cliDataFilePathEnvVar) - if env != "" { - return env, nil - } - return "", errors.New("env is empty") - }, - receiverWithPath(os.UserConfigDir, "Zerops", cliDataFileName), - receiverWithPath(os.UserHomeDir, "Zerops", cliDataFileName), + receiverFromEnv(cliDataFilePathEnvVar), + receiverFromOsFunc(os.UserConfigDir, "Zerops", cliDataFileName), + receiverFromOsFunc(os.UserHomeDir, "Zerops", cliDataFileName), } } -func getLogFilePath() []pathReceiver { +func getLogFilePathReceivers() []pathReceiver { return []pathReceiver{ - func() (string, error) { - env := os.Getenv(cliLogFilePathEnvVar) - if env != "" { - return env, nil - } - return "", errors.New("env is empty") - }, - receiverWithPath(os.UserConfigDir, "Zerops", zeropsLogFile), - receiverWithPath(os.UserHomeDir, "Zerops", zeropsLogFile), + receiverFromEnv(cliLogFilePathEnvVar), + receiverFromOsFunc(os.UserConfigDir, "Zerops", zeropsLogFile), + receiverFromOsFunc(os.UserHomeDir, "Zerops", zeropsLogFile), } } diff --git a/src/constants/zerops.go b/src/constants/zerops.go index cebbf10e..f644c590 100644 --- a/src/constants/zerops.go +++ b/src/constants/zerops.go @@ -4,8 +4,10 @@ import ( "os" "path" "path/filepath" + "strings" "github.com/pkg/errors" + "github.com/zeropsio/zcli/src/i18n" ) const ( @@ -17,19 +19,55 @@ const ( cliLogFilePathEnvVar = "ZEROPS_CLI_LOG_FILE_PATH" ) -type pathReceiver func() (string, error) +type pathReceiver func() (path string, err error) func CliDataFilePath() (string, error) { - return findFirstWritablePath(getDataFilePaths()) + pathReceivers := getDataFilePathsReceivers() + path := findFirstWritablePath(pathReceivers) + if path == "" { + paths := make([]string, 0, len(pathReceivers)) + for _, p := range pathReceivers { + _, err := p() + paths = append(paths, err.Error()) + } + return "", errors.New(i18n.T(i18n.UnableToWriteCliData, "\n"+strings.Join(paths, "\n"))) + } + return path, nil } func LogFilePath() (string, error) { - return findFirstWritablePath(getLogFilePath()) + pathReceivers := getLogFilePathReceivers() + path := findFirstWritablePath(pathReceivers) + if path == "" { + paths := make([]string, 0, len(pathReceivers)) + for _, p := range pathReceivers { + _, err := p() + paths = append(paths, err.Error()) + } + return "", errors.New(i18n.T(i18n.UnableToWriteLogFile, "\n"+strings.Join(paths, "\n"))) + } + return path, nil +} + +func receiverFromPath(path string) pathReceiver { + return func() (string, error) { + return checkPath(path) + } } -func receiverWithPath(receiver pathReceiver, elem ...string) pathReceiver { +func receiverFromEnv(envName string) pathReceiver { return func() (string, error) { - dir, err := receiver() + env := os.Getenv(envName) + if env == "" { + return "", errors.Errorf("env %s is empty", envName) + } + return checkPath(env) + } +} + +func receiverFromOsFunc(osFunc func() (string, error), elem ...string) pathReceiver { + return func() (string, error) { + dir, err := osFunc() if err != nil { return "", err } @@ -39,32 +77,32 @@ func receiverWithPath(receiver pathReceiver, elem ...string) pathReceiver { } } -func findFirstWritablePath(paths []pathReceiver) (string, error) { - checkedPaths := make([]string, 0, len(paths)) +func findFirstWritablePath(paths []pathReceiver) string { for _, p := range paths { path, err := p() if err == nil { - checkedPaths = append(checkedPaths, path) - if err := checkPath(path); err == nil { - return path, nil - } + return path } } - // TODO - janhajek translate - return "", errors.Errorf("Unable to find writable path from %v", checkedPaths) + return "" } -func checkPath(filePath string) error { +func checkPath(filePath string) (string, error) { dir := path.Dir(filePath) if err := os.MkdirAll(dir, 0775); err != nil { - return err + return "", err } f, err := os.OpenFile(filePath, os.O_RDONLY|os.O_CREATE, 0666) if err != nil { - return err + return "", err + } + err = f.Close() + if err != nil { + return "", err } - return f.Close() + + return filePath, nil } diff --git a/src/i18n/en.go b/src/i18n/en.go index 9ca8d603..4265068c 100644 --- a/src/i18n/en.go +++ b/src/i18n/en.go @@ -219,6 +219,11 @@ var en = map[string]string{ // global // //////////// + UnknownTerminalMode: "Unknown terminal mode: %s", + UnableToDecodeJsonFile: "Unable to decode json file: %s", + UnableToWriteCliData: "Unable to write zcli data, paths tested: %s", + UnableToWriteLogFile: "Unable to write zcli debug log file, paths tested: %s", + // args ArgsOnlyOneOptionalAllowed: "optional arg %s can be only the last one", ArgsOnlyOneArrayAllowed: "array arg %s can be only the last one", @@ -226,7 +231,7 @@ var en = map[string]string{ ArgsTooManyArgs: "expected no more than %d arg(s), got %d", // logger - LoggerUnableToOpenLogFileWarning: "Failed to open a log file, used path: %s. Try to use --log-file-path flag.\n", + LoggerUnableToOpenLogFileWarning: "Failed to open a log file, used path: %s", // ux helpers ProjectSelectorListEmpty: "You don't have any projects yet. Create a new project using `zcli project import` command.", @@ -246,11 +251,11 @@ zcli login {token} more info: https://docs.zerops.io/documentation/cli/authorization.html`, // scope - SelectedProject: "Selected project: %s", - SelectedService: "Selected service: %s", - ScopedProject: "Scoped project: %s", + SelectedProject: "Selected project", + SelectedService: "Selected service", + ScopedProject: "Scoped project", ScopedProjectNotFound: "Scoped project wasn't found, Select a different project using `zcli scope project` command.", - PreviouslyScopedProject: "Previously scoped project: %s", + PreviouslyScopedProject: "Previously scoped project", ScopeReset: "Scope was reset", DestructiveOperationConfirmationFailed: "You have to confirm a destructive operation.", diff --git a/src/i18n/i18n.go b/src/i18n/i18n.go index 3d8f509a..9415cf17 100644 --- a/src/i18n/i18n.go +++ b/src/i18n/i18n.go @@ -257,6 +257,11 @@ const ( // global // //////////// + UnknownTerminalMode = "UnknownTerminalMode" + UnableToDecodeJsonFile = "UnableToDecodeJsonFile" + UnableToWriteCliData = "UnableToWriteCliData" + UnableToWriteLogFile = "UnableToWriteLogFile" + // args ArgsOnlyOneOptionalAllowed = "ArgsOnlyOneOptionalAllowed" ArgsOnlyOneArrayAllowed = "ArgsOnlyOneArrayAllowed" diff --git a/src/logger/handler.go b/src/logger/handler.go index 2ea572f1..eea85fb8 100644 --- a/src/logger/handler.go +++ b/src/logger/handler.go @@ -1,11 +1,7 @@ package logger import ( - "fmt" "io" - "os" - - "github.com/zeropsio/zcli/src/i18n" "github.com/sirupsen/logrus" ) @@ -47,12 +43,7 @@ func NewDebugFileLogger(config DebugFileConfig) *Handler { l.Out = io.Discard l.Level = logrus.DebugLevel - file, err := os.OpenFile(config.FilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0775) - if err != nil { - os.Stdout.WriteString(fmt.Sprintf(i18n.T(i18n.LoggerUnableToOpenLogFileWarning), config.FilePath)) - } else { - file.Close() - + if config.FilePath != "" { l.AddHook(&VarLogHook{ path: config.FilePath, levels: []logrus.Level{logrus.DebugLevel, logrus.InfoLevel, logrus.WarnLevel, logrus.ErrorLevel}, diff --git a/src/params/handler.go b/src/params/handler.go index 2679654e..e3f25576 100644 --- a/src/params/handler.go +++ b/src/params/handler.go @@ -4,10 +4,9 @@ import ( "fmt" "os" - "github.com/zeropsio/zcli/src/constants" - "github.com/spf13/cobra" "github.com/spf13/viper" + "github.com/zeropsio/zcli/src/constants" ) type Handler struct { @@ -107,17 +106,16 @@ func (h *Handler) GetBool(cmd *cobra.Command, name string) bool { return false } -func (h *Handler) InitViper() error { +func (h *Handler) InitViper() { path, err := os.Getwd() - if err != nil { - return err + if err == nil { + h.viper.AddConfigPath(path) } cliDataPath, err := constants.CliDataFilePath() - if err != nil { - return err + if err == nil { + h.viper.AddConfigPath(cliDataPath) } - h.viper.AddConfigPath(path) - h.viper.AddConfigPath(cliDataPath) + h.viper.SetConfigName("zcli.config") h.viper.SetEnvPrefix("ZEROPS") h.viper.AutomaticEnv() @@ -125,8 +123,6 @@ func (h *Handler) InitViper() error { if err := h.viper.ReadInConfig(); err == nil { fmt.Println("Using config file:", h.viper.ConfigFileUsed()) } - - return nil } func toSnakeCase(flagName string) string { diff --git a/src/storage/handler.go b/src/storage/handler.go index 7583c26a..bc127f8a 100644 --- a/src/storage/handler.go +++ b/src/storage/handler.go @@ -6,6 +6,7 @@ import ( "sync" "github.com/pkg/errors" + "github.com/zeropsio/zcli/src/i18n" ) type Config struct { @@ -54,8 +55,7 @@ func (h *Handler[T]) load() error { } if err := json.NewDecoder(f).Decode(&h.data); err != nil { - // TODO - janhajek translation - return errors.WithMessagef(err, "Unable to decode json file %s", h.config.FilePath) + return errors.WithMessagef(err, i18n.T(i18n.UnableToDecodeJsonFile, h.config.FilePath)) } return nil diff --git a/src/uxBlock/blocks.go b/src/uxBlock/blocks.go index e2b4663d..e271e989 100644 --- a/src/uxBlock/blocks.go +++ b/src/uxBlock/blocks.go @@ -5,17 +5,16 @@ import ( "context" "github.com/zeropsio/zcli/src/logger" + "github.com/zeropsio/zcli/src/uxBlock/styles" ) //go:generate go run --mod=mod github.com/golang/mock/mockgen -source=$GOFILE -destination=$PWD/mocks/$GOFILE -package=mocks type UxBlocks interface { - PrintLine(values ...interface{}) - PrintSuccessLine(values ...string) - PrintInfoLine(values ...string) - PrintWarningLine(values ...string) - PrintErrorLine(values ...string) - PrintDebugLine(args ...interface{}) + LogDebug(message string) + PrintInfo(line styles.Line) + PrintWarning(line styles.Line) + PrintError(line styles.Line) Table(body *TableBody, auxOptions ...TableOption) Select(ctx context.Context, tableBody *TableBody, auxOptions ...SelectOption) ([]int, error) Prompt( diff --git a/src/uxBlock/logs.go b/src/uxBlock/logs.go index 3663192b..315f6503 100644 --- a/src/uxBlock/logs.go +++ b/src/uxBlock/logs.go @@ -1,40 +1,22 @@ package uxBlock -func (b *uxBlocks) PrintLine(values ...interface{}) { - b.info(values...) -} - -func (b *uxBlocks) PrintSuccessLine(values ...string) { - b.info(SuccessIcon, successColor.SetString(values...)) -} - -func (b *uxBlocks) PrintInfoLine(values ...string) { - b.info(InfoIcon, infoColor.SetString(values...)) -} - -func (b *uxBlocks) PrintWarningLine(values ...string) { - b.warning(WarningIcon, warningColor.SetString(values...)) -} - -func (b *uxBlocks) PrintErrorLine(values ...string) { - b.error(ErrorIcon, errorColor.SetString(values...)) -} +import "github.com/zeropsio/zcli/src/uxBlock/styles" -func (b *uxBlocks) PrintDebugLine(args ...interface{}) { - b.debugFileLogger.Debug(NewLine(args...).DisableStyle()) +func (b *uxBlocks) LogDebug(message string) { + b.debugFileLogger.Debug(message) } -func (b *uxBlocks) info(args ...interface{}) { - b.outputLogger.Info(NewLine(args...)) - b.debugFileLogger.Info(NewLine(args...).DisableStyle()) +func (b *uxBlocks) PrintInfo(line styles.Line) { + b.outputLogger.Info(line) + b.debugFileLogger.Info(line.DisableStyle()) } -func (b *uxBlocks) warning(args ...interface{}) { - b.outputLogger.Warning(NewLine(args...)) - b.debugFileLogger.Warning(NewLine(args...).DisableStyle()) +func (b *uxBlocks) PrintWarning(line styles.Line) { + b.outputLogger.Warning(line) + b.debugFileLogger.Warning(line.DisableStyle()) } -func (b *uxBlocks) error(args ...interface{}) { - b.outputLogger.Error(NewLine(args...)) - b.debugFileLogger.Error(NewLine(args...).DisableStyle()) +func (b *uxBlocks) PrintError(line styles.Line) { + b.outputLogger.Error(line) + b.debugFileLogger.Error(line.DisableStyle()) } diff --git a/src/uxBlock/mocks/blocks.go b/src/uxBlock/mocks/blocks.go index a35e232a..045ec2d0 100644 --- a/src/uxBlock/mocks/blocks.go +++ b/src/uxBlock/mocks/blocks.go @@ -6,148 +6,124 @@ package mocks import ( context "context" + reflect "reflect" + gomock "github.com/golang/mock/gomock" uxBlock "github.com/zeropsio/zcli/src/uxBlock" - reflect "reflect" + styles "github.com/zeropsio/zcli/src/uxBlock/styles" ) -// MockUxBlocks is a mock of UxBlocks interface +// MockUxBlocks is a mock of UxBlocks interface. type MockUxBlocks struct { ctrl *gomock.Controller recorder *MockUxBlocksMockRecorder } -// MockUxBlocksMockRecorder is the mock recorder for MockUxBlocks +// MockUxBlocksMockRecorder is the mock recorder for MockUxBlocks. type MockUxBlocksMockRecorder struct { mock *MockUxBlocks } -// NewMockUxBlocks creates a new mock instance +// NewMockUxBlocks creates a new mock instance. func NewMockUxBlocks(ctrl *gomock.Controller) *MockUxBlocks { mock := &MockUxBlocks{ctrl: ctrl} mock.recorder = &MockUxBlocksMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use +// EXPECT returns an object that allows the caller to indicate expected use. func (m *MockUxBlocks) EXPECT() *MockUxBlocksMockRecorder { return m.recorder } -// PrintLine mocks base method -func (m *MockUxBlocks) PrintLine(values ...interface{}) { +// LogDebug mocks base method. +func (m *MockUxBlocks) LogDebug(message string) { m.ctrl.T.Helper() - varargs := []interface{}{} - for _, a := range values { - varargs = append(varargs, a) - } - m.ctrl.Call(m, "PrintLine", varargs...) + m.ctrl.Call(m, "LogDebug", message) } -// PrintLine indicates an expected call of PrintLine -func (mr *MockUxBlocksMockRecorder) PrintLine(values ...interface{}) *gomock.Call { +// LogDebug indicates an expected call of LogDebug. +func (mr *MockUxBlocksMockRecorder) LogDebug(message interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrintLine", reflect.TypeOf((*MockUxBlocks)(nil).PrintLine), values...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LogDebug", reflect.TypeOf((*MockUxBlocks)(nil).LogDebug), message) } -// PrintSuccessLine mocks base method -func (m *MockUxBlocks) PrintSuccessLine(values ...string) { +// PrintError mocks base method. +func (m *MockUxBlocks) PrintError(line styles.Line) { m.ctrl.T.Helper() - varargs := []interface{}{} - for _, a := range values { - varargs = append(varargs, a) - } - m.ctrl.Call(m, "PrintSuccessLine", varargs...) + m.ctrl.Call(m, "PrintError", line) } -// PrintSuccessLine indicates an expected call of PrintSuccessLine -func (mr *MockUxBlocksMockRecorder) PrintSuccessLine(values ...interface{}) *gomock.Call { +// PrintError indicates an expected call of PrintError. +func (mr *MockUxBlocksMockRecorder) PrintError(line interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrintSuccessLine", reflect.TypeOf((*MockUxBlocks)(nil).PrintSuccessLine), values...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrintError", reflect.TypeOf((*MockUxBlocks)(nil).PrintError), line) } -// PrintInfoLine mocks base method -func (m *MockUxBlocks) PrintInfoLine(values ...string) { +// PrintInfo mocks base method. +func (m *MockUxBlocks) PrintInfo(line styles.Line) { m.ctrl.T.Helper() - varargs := []interface{}{} - for _, a := range values { - varargs = append(varargs, a) - } - m.ctrl.Call(m, "PrintInfoLine", varargs...) + m.ctrl.Call(m, "PrintInfo", line) } -// PrintInfoLine indicates an expected call of PrintInfoLine -func (mr *MockUxBlocksMockRecorder) PrintInfoLine(values ...interface{}) *gomock.Call { +// PrintInfo indicates an expected call of PrintInfo. +func (mr *MockUxBlocksMockRecorder) PrintInfo(line interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrintInfoLine", reflect.TypeOf((*MockUxBlocks)(nil).PrintInfoLine), values...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrintInfo", reflect.TypeOf((*MockUxBlocks)(nil).PrintInfo), line) } -// PrintWarningLine mocks base method -func (m *MockUxBlocks) PrintWarningLine(values ...string) { +// PrintWarning mocks base method. +func (m *MockUxBlocks) PrintWarning(line styles.Line) { m.ctrl.T.Helper() - varargs := []interface{}{} - for _, a := range values { - varargs = append(varargs, a) - } - m.ctrl.Call(m, "PrintWarningLine", varargs...) -} - -// PrintWarningLine indicates an expected call of PrintWarningLine -func (mr *MockUxBlocksMockRecorder) PrintWarningLine(values ...interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrintWarningLine", reflect.TypeOf((*MockUxBlocks)(nil).PrintWarningLine), values...) -} - -// PrintErrorLine mocks base method -func (m *MockUxBlocks) PrintErrorLine(values ...string) { - m.ctrl.T.Helper() - varargs := []interface{}{} - for _, a := range values { - varargs = append(varargs, a) - } - m.ctrl.Call(m, "PrintErrorLine", varargs...) + m.ctrl.Call(m, "PrintWarning", line) } -// PrintErrorLine indicates an expected call of PrintErrorLine -func (mr *MockUxBlocksMockRecorder) PrintErrorLine(values ...interface{}) *gomock.Call { +// PrintWarning indicates an expected call of PrintWarning. +func (mr *MockUxBlocksMockRecorder) PrintWarning(line interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrintErrorLine", reflect.TypeOf((*MockUxBlocks)(nil).PrintErrorLine), values...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrintWarning", reflect.TypeOf((*MockUxBlocks)(nil).PrintWarning), line) } -// PrintDebugLine mocks base method -func (m *MockUxBlocks) PrintDebugLine(args ...interface{}) { +// Prompt mocks base method. +func (m *MockUxBlocks) Prompt(ctx context.Context, message string, choices []string, auxOptions ...uxBlock.PromptOption) (int, error) { m.ctrl.T.Helper() - varargs := []interface{}{} - for _, a := range args { + varargs := []interface{}{ctx, message, choices} + for _, a := range auxOptions { varargs = append(varargs, a) } - m.ctrl.Call(m, "PrintDebugLine", varargs...) + ret := m.ctrl.Call(m, "Prompt", varargs...) + ret0, _ := ret[0].(int) + ret1, _ := ret[1].(error) + return ret0, ret1 } -// PrintDebugLine indicates an expected call of PrintDebugLine -func (mr *MockUxBlocksMockRecorder) PrintDebugLine(args ...interface{}) *gomock.Call { +// Prompt indicates an expected call of Prompt. +func (mr *MockUxBlocksMockRecorder) Prompt(ctx, message, choices interface{}, auxOptions ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrintDebugLine", reflect.TypeOf((*MockUxBlocks)(nil).PrintDebugLine), args...) + varargs := append([]interface{}{ctx, message, choices}, auxOptions...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Prompt", reflect.TypeOf((*MockUxBlocks)(nil).Prompt), varargs...) } -// Table mocks base method -func (m *MockUxBlocks) Table(body *uxBlock.TableBody, auxOptions ...uxBlock.TableOption) { +// RunSpinners mocks base method. +func (m *MockUxBlocks) RunSpinners(ctx context.Context, spinners []*uxBlock.Spinner, auxOptions ...uxBlock.SpinnerOption) func() { m.ctrl.T.Helper() - varargs := []interface{}{body} + varargs := []interface{}{ctx, spinners} for _, a := range auxOptions { varargs = append(varargs, a) } - m.ctrl.Call(m, "Table", varargs...) + ret := m.ctrl.Call(m, "RunSpinners", varargs...) + ret0, _ := ret[0].(func()) + return ret0 } -// Table indicates an expected call of Table -func (mr *MockUxBlocksMockRecorder) Table(body interface{}, auxOptions ...interface{}) *gomock.Call { +// RunSpinners indicates an expected call of RunSpinners. +func (mr *MockUxBlocksMockRecorder) RunSpinners(ctx, spinners interface{}, auxOptions ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{body}, auxOptions...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Table", reflect.TypeOf((*MockUxBlocks)(nil).Table), varargs...) + varargs := append([]interface{}{ctx, spinners}, auxOptions...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RunSpinners", reflect.TypeOf((*MockUxBlocks)(nil).RunSpinners), varargs...) } -// Select mocks base method +// Select mocks base method. func (m *MockUxBlocks) Select(ctx context.Context, tableBody *uxBlock.TableBody, auxOptions ...uxBlock.SelectOption) ([]int, error) { m.ctrl.T.Helper() varargs := []interface{}{ctx, tableBody} @@ -160,48 +136,26 @@ func (m *MockUxBlocks) Select(ctx context.Context, tableBody *uxBlock.TableBody, return ret0, ret1 } -// Select indicates an expected call of Select +// Select indicates an expected call of Select. func (mr *MockUxBlocksMockRecorder) Select(ctx, tableBody interface{}, auxOptions ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() varargs := append([]interface{}{ctx, tableBody}, auxOptions...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Select", reflect.TypeOf((*MockUxBlocks)(nil).Select), varargs...) } -// Prompt mocks base method -func (m *MockUxBlocks) Prompt(ctx context.Context, message string, choices []string, auxOptions ...uxBlock.PromptOption) (int, error) { - m.ctrl.T.Helper() - varargs := []interface{}{ctx, message, choices} - for _, a := range auxOptions { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "Prompt", varargs...) - ret0, _ := ret[0].(int) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Prompt indicates an expected call of Prompt -func (mr *MockUxBlocksMockRecorder) Prompt(ctx, message, choices interface{}, auxOptions ...interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{ctx, message, choices}, auxOptions...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Prompt", reflect.TypeOf((*MockUxBlocks)(nil).Prompt), varargs...) -} - -// RunSpinners mocks base method -func (m *MockUxBlocks) RunSpinners(ctx context.Context, spinners []*uxBlock.Spinner, auxOptions ...uxBlock.SpinnerOption) func() { +// Table mocks base method. +func (m *MockUxBlocks) Table(body *uxBlock.TableBody, auxOptions ...uxBlock.TableOption) { m.ctrl.T.Helper() - varargs := []interface{}{ctx, spinners} + varargs := []interface{}{body} for _, a := range auxOptions { varargs = append(varargs, a) } - ret := m.ctrl.Call(m, "RunSpinners", varargs...) - ret0, _ := ret[0].(func()) - return ret0 + m.ctrl.Call(m, "Table", varargs...) } -// RunSpinners indicates an expected call of RunSpinners -func (mr *MockUxBlocksMockRecorder) RunSpinners(ctx, spinners interface{}, auxOptions ...interface{}) *gomock.Call { +// Table indicates an expected call of Table. +func (mr *MockUxBlocksMockRecorder) Table(body interface{}, auxOptions ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{ctx, spinners}, auxOptions...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RunSpinners", reflect.TypeOf((*MockUxBlocks)(nil).RunSpinners), varargs...) + varargs := append([]interface{}{body}, auxOptions...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Table", reflect.TypeOf((*MockUxBlocks)(nil).Table), varargs...) } diff --git a/src/uxBlock/prompt.go b/src/uxBlock/prompt.go index 1f413468..7a95fa8f 100644 --- a/src/uxBlock/prompt.go +++ b/src/uxBlock/prompt.go @@ -7,6 +7,7 @@ import ( tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "github.com/zeropsio/zcli/src/i18n" + "github.com/zeropsio/zcli/src/uxBlock/styles" ) type promptConfig struct { @@ -26,7 +27,7 @@ func (b *uxBlocks) Prompt( } if !b.isTerminal { - b.PrintLine(message) + b.PrintInfo(styles.InfoLine(message)) return 0, errors.New(i18n.T(i18n.PromptAllowedOnlyInTerminal)) } @@ -98,9 +99,9 @@ func (m *promptModel) View() string { buttonsTexts := []string{} for i, choice := range m.choices { if i == m.cursor { - buttonsTexts = append(buttonsTexts, activeButtonStyle.Render(choice)) + buttonsTexts = append(buttonsTexts, styles.ActiveDialogButton().Render(choice)) } else { - buttonsTexts = append(buttonsTexts, buttonStyle.Render(choice)) + buttonsTexts = append(buttonsTexts, styles.DialogButton().Render(choice)) } } @@ -110,31 +111,8 @@ func (m *promptModel) View() string { dialog := lipgloss.Place(0, 0, lipgloss.Left, lipgloss.Center, - dialogBoxStyle.Render(ui), + styles.DialogBox().Render(ui), ) return dialog } - -var ( - dialogBoxStyle = lipgloss.NewStyle(). - Border(lipgloss.RoundedBorder()). - BorderForeground(lipgloss.Color("#874BFD")). - Padding(1, 0). - BorderTop(true). - BorderLeft(true). - BorderRight(true). - BorderBottom(true) - - buttonStyle = lipgloss.NewStyle(). - Foreground(lipgloss.Color("#FFF7DB")). - Background(lipgloss.Color("#888B7E")). - Padding(0, 3). - MarginRight(2). - MarginTop(1) - - activeButtonStyle = buttonStyle.Copy(). - Foreground(lipgloss.Color("#FFF7DB")). - Background(lipgloss.Color("#F25D94")). - Underline(true) -) diff --git a/src/uxBlock/select.go b/src/uxBlock/select.go index d3f6d350..3495944e 100644 --- a/src/uxBlock/select.go +++ b/src/uxBlock/select.go @@ -10,6 +10,7 @@ import ( "github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss/table" "github.com/zeropsio/zcli/src/i18n" + "github.com/zeropsio/zcli/src/uxBlock/styles" ) type selectConfig struct { @@ -45,7 +46,7 @@ func (b *uxBlocks) Select(ctx context.Context, tableBody *TableBody, auxOptions } if !b.isTerminal { - b.PrintLine(cfg.label) + b.PrintInfo(styles.InfoLine(cfg.label)) return nil, errors.New(i18n.T(i18n.SelectorAllowedOnlyInTerminal)) } @@ -56,8 +57,8 @@ func (b *uxBlocks) Select(ctx context.Context, tableBody *TableBody, auxOptions selected: make(map[int]struct{}), } p := tea.NewProgram(model, tea.WithoutSignalHandler(), tea.WithContext(ctx)) - _, err := p.Run() - if err != nil { + + if _, err := p.Run(); err != nil { return nil, err } @@ -138,53 +139,47 @@ func (m *selectModel) View() string { return "" } - baseStyle := lipgloss.NewStyle().Padding(0, 1) - t := table.New(). + BorderStyle(styles.InfoColor()). Border(lipgloss.NormalBorder()). - BorderStyle(lipgloss.NewStyle().Foreground(lipgloss.Color("238"))). StyleFunc(func(row, col int) lipgloss.Style { - even := row%2 == 0 - - if even { - return baseStyle.Copy().Foreground(lipgloss.Color("245")) + // in case that header is present, we need to adjust row index + if m.cfg.header != nil { + row -= 1 } - return baseStyle.Copy().Foreground(lipgloss.Color("252")) + if row == m.cursor { + return styles.TableRowActive() + } + + return styles.TableRow() }) if m.cfg.header != nil { - capitalizeHeaders := func(data []string) []string { - for i := range data { - data[i] = strings.ToUpper(data[i]) - } - return data - } - - headers := make([]string, len(m.cfg.header.cells)+1) - headers[0] = "" - for i, header := range m.cfg.header.cells { - headers[i+1] = header.Text + headers := make([]string, 0, len(m.cfg.header.cells)+1) + headers = append(headers, "") + for _, header := range m.cfg.header.cells { + headers = append(headers, strings.ToUpper(header.Text)) } - t = t.Headers(capitalizeHeaders(headers)...) + t = t.Headers(headers...) } - rows := make([][]string, len(m.tableBody.rows)) for rowIndex, row := range m.tableBody.rows { - cells := make([]string, len(row.cells)+1) - cells[0] = " " + cells := make([]string, 0, len(row.cells)+1) + icon := " " if rowIndex == m.cursor { - cells[0] = "✓" + icon = styles.SelectIcon } - for i, cell := range row.cells { - cells[i+1] = cell.Text + cells = append(cells, icon) + + for _, cell := range row.cells { + cells = append(cells, cell.Text) } - rows[rowIndex] = cells + t = t.Row(cells...) } - t = t.Rows(rows...) s := "" if m.cfg.label != "" { - s = SelectionIcon + m.cfg.label + "\n" + s = styles.SelectLine(m.cfg.label).String() + "\n" } t.Width(calculateTableWidth(t, m.uxBlocks.terminalWidth)) diff --git a/src/uxBlock/showcase/main.go b/src/uxBlock/showcase/main.go index 71d58ae1..f27df34d 100644 --- a/src/uxBlock/showcase/main.go +++ b/src/uxBlock/showcase/main.go @@ -10,7 +10,8 @@ import ( "github.com/mattn/go-isatty" "github.com/zeropsio/zcli/src/logger" - . "github.com/zeropsio/zcli/src/uxBlock" + "github.com/zeropsio/zcli/src/uxBlock" + . "github.com/zeropsio/zcli/src/uxBlock/styles" "golang.org/x/term" ) @@ -23,22 +24,22 @@ func main() { do(ctx, blocks) } -func do(ctx context.Context, blocks UxBlocks) { +func do(ctx context.Context, blocks uxBlock.UxBlocks) { prompts(ctx, blocks) spinners(ctx, blocks) texts(ctx, blocks) tables(ctx, blocks) } -func spinners(ctx context.Context, blocks UxBlocks) { +func spinners(ctx context.Context, blocks uxBlock.UxBlocks) { { fmt.Println("========= spinners block =========") - spinner1 := NewSpinner(InfoText("Running 1").String()) - spinner2 := NewSpinner(InfoText("Running 2").String()) - spinner3 := NewSpinner(InfoText("Running 3").String()) + spinner1 := uxBlock.NewSpinner(NewLine("Running 1")) + spinner2 := uxBlock.NewSpinner(NewLine("Running 2")) + spinner3 := uxBlock.NewSpinner(NewLine("Running 3")) - stop := blocks.RunSpinners(ctx, []*Spinner{spinner1, spinner2, spinner3}) + stop := blocks.RunSpinners(ctx, []*uxBlock.Spinner{spinner1, spinner2, spinner3}) counter := 0 tick := time.NewTicker(time.Second * 1) @@ -50,13 +51,13 @@ func spinners(ctx context.Context, blocks UxBlocks) { case <-tick.C: counter++ if counter == 2 { - spinner2.Finish(NewLine(SuccessIcon, SuccessText("Finished successfully")).String()) + spinner2.Finish(SuccessLine("Finished successfully")) } if counter == 4 { - spinner1.Finish(NewLine(ErrorIcon, ErrorText("finished with error")).String()) + spinner1.Finish(ErrorLine("finished with error")) } if counter == 6 { - spinner3.Finish(NewLine(WarningIcon, WarningText("Finish with warning")).String()) + spinner3.Finish(WarningLine("Finish with warning")) } } if counter == 6 { @@ -70,7 +71,7 @@ func spinners(ctx context.Context, blocks UxBlocks) { } } -func prompts(ctx context.Context, blocks UxBlocks) { +func prompts(ctx context.Context, blocks uxBlock.UxBlocks) { fmt.Println("========= prompt block =========") choices := []string{"yes", "no", "maybe"} choice, err := blocks.Prompt(ctx, "Question?", choices) @@ -78,21 +79,25 @@ func prompts(ctx context.Context, blocks UxBlocks) { return } - blocks.PrintInfoLine("selected", choices[choice]) + blocks.PrintInfo(InfoWithValueLine("selected", choices[choice])) fmt.Println("========= prompt block end =========") } -func texts(_ context.Context, blocks UxBlocks) { +func texts(_ context.Context, blocks uxBlock.UxBlocks) { fmt.Println("========= texts block =========") - blocks.PrintInfoLine("info line") - blocks.PrintWarningLine("warning line") - blocks.PrintErrorLine("Error line") - blocks.PrintLine(WarningText("Line"), " with ", InfoIcon, InfoText("mixed"), " ", ErrorText("styles")) + blocks.PrintInfo(NewLine("line without style")) + blocks.PrintInfo(InfoLine("info line")) + blocks.PrintInfo(InfoWithValueLine("info line", "value")) + blocks.PrintInfo(SuccessLine("success line")) + blocks.PrintWarning(WarningLine("warning line")) + blocks.PrintError(ErrorLine("Error line")) + blocks.PrintInfo(SelectLine("Select line")) + blocks.PrintInfo(NewLine(WarningText("NewLine"), " with ", InfoIcon, InfoText("mixed"), " ", ErrorText("styles"))) fmt.Println("========= texts block end =========") } -func tables(ctx context.Context, blocks UxBlocks) { +func tables(ctx context.Context, blocks uxBlock.UxBlocks) { fmt.Println("========= table selection block =========") tableData := [][]string{ @@ -107,25 +112,25 @@ func tables(ctx context.Context, blocks UxBlocks) { {"incididunt", "ut", "labore", "et"}, } - body := NewTableBody().AddStringsRows(tableData...) + body := uxBlock.NewTableBody().AddStringsRows(tableData...) line, err := blocks.Select( ctx, body, - SelectTableHeader(NewTableRow().AddStringCells("header1", "header2", "header3", "header4")), - SelectLabel("Select line"), + uxBlock.SelectTableHeader(uxBlock.NewTableRow().AddStringCells("header1", "header2", "header3", "header4")), + uxBlock.SelectLabel("Select line"), ) if err != nil { return } - blocks.PrintInfoLine("selected", tableData[line[0]][0]) + blocks.PrintInfo(InfoWithValueLine("selected", tableData[line[0]][0])) fmt.Println("========= table selection end =========") fmt.Println("========= print table block =========") - blocks.PrintInfoLine("printing table") - blocks.Table(body, WithTableHeader(NewTableRow().AddStringCells("header1", "header2", "header3", "header4"))) + blocks.PrintInfo(InfoLine("printing table")) + blocks.Table(body, uxBlock.WithTableHeader(uxBlock.NewTableRow().AddStringCells("header1", "header2", "header3", "header4"))) fmt.Println("========= print table block end =========") } @@ -141,7 +146,7 @@ func regSignals(contextCancel func()) { }() } -func createBlocks(contextCancelFunc func()) UxBlocks { +func createBlocks(contextCancelFunc func()) uxBlock.UxBlocks { isTerminal := isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd()) outputLogger := logger.NewOutputLogger(logger.OutputConfig{ @@ -157,7 +162,7 @@ func createBlocks(contextCancelFunc func()) UxBlocks { FilePath: "zerops.log", }) - blocks := NewBlock(outputLogger, debugFileLogger, isTerminal, width, contextCancelFunc) + blocks := uxBlock.NewBlock(outputLogger, debugFileLogger, isTerminal, width, contextCancelFunc) return blocks } diff --git a/src/uxBlock/spinner.go b/src/uxBlock/spinner.go index be4a9b84..64e58e3e 100644 --- a/src/uxBlock/spinner.go +++ b/src/uxBlock/spinner.go @@ -6,6 +6,7 @@ import ( bubblesSpinner "github.com/charmbracelet/bubbles/spinner" tea "github.com/charmbracelet/bubbletea" + "github.com/zeropsio/zcli/src/uxBlock/styles" ) func (b *uxBlocks) RunSpinners(ctx context.Context, spinners []*Spinner, auxOptions ...SpinnerOption) func() { @@ -17,7 +18,7 @@ func (b *uxBlocks) RunSpinners(ctx context.Context, spinners []*Spinner, auxOpti if !b.isTerminal { return func() { for _, spinner := range spinners { - b.PrintLine(spinner.text) + b.PrintInfo(spinner.line) } } } @@ -30,7 +31,7 @@ func (b *uxBlocks) RunSpinners(ctx context.Context, spinners []*Spinner, auxOpti p := tea.NewProgram(model, tea.WithoutSignalHandler(), tea.WithContext(ctx)) go func() { - //nolint:errcheck + //nolint:errcheck // Why: I'm not interest in the error p.Run() if model.canceled { b.ctxCancel() @@ -119,7 +120,7 @@ func (m *spinnerModel) View() string { if m.canceled { s += "canceled\n" } else { - s += spinner.view() + spinner.text + "\n" + s += spinner.view() + spinner.line.String() + "\n" } } @@ -132,26 +133,26 @@ type spinnerConfig struct { type SpinnerOption = func(cfg *spinnerConfig) type Spinner struct { - text string + line styles.Line finished bool spinner bubblesSpinner.Model } -func NewSpinner(text string) *Spinner { +func NewSpinner(line styles.Line) *Spinner { return &Spinner{ - text: text, + line: line, spinner: bubblesSpinner.New(bubblesSpinner.WithSpinner(bubblesSpinner.MiniDot)), } } -func (s *Spinner) SetMessage(text string) *Spinner { - s.text = text +func (s *Spinner) SetMessage(text styles.Line) *Spinner { + s.line = text return s } -func (s *Spinner) Finish(text string) *Spinner { - s.text = text +func (s *Spinner) Finish(text styles.Line) *Spinner { + s.line = text s.finished = true return s diff --git a/src/uxBlock/styles.go b/src/uxBlock/styles.go deleted file mode 100644 index 046f4645..00000000 --- a/src/uxBlock/styles.go +++ /dev/null @@ -1,108 +0,0 @@ -package uxBlock - -import ( - "fmt" - "os" - - "github.com/charmbracelet/lipgloss" -) - -const ( - SuccessIcon = "✅ " - ErrorIcon = "❌ " - SelectionIcon = "❔ " - InfoIcon = "ℹ️" - WarningIcon = "⚠️" -) - -var defaultStyle = lipgloss.NewStyle(). - Renderer(lipgloss.NewRenderer(os.Stdout)) - -var successColor = defaultStyle. - Foreground(lipgloss.CompleteAdaptiveColor{ - Light: lipgloss.CompleteColor{TrueColor: "#00ff5f", ANSI256: "47", ANSI: "0"}, - Dark: lipgloss.CompleteColor{TrueColor: "#00ff5f", ANSI256: "47", ANSI: "0"}, - }). - Bold(false) - -var errorColor = defaultStyle. - Foreground(lipgloss.CompleteAdaptiveColor{ - Light: lipgloss.CompleteColor{TrueColor: "#FF000", ANSI256: "196", ANSI: "0"}, - Dark: lipgloss.CompleteColor{TrueColor: "#FF000", ANSI256: "196", ANSI: "0"}, - }). - Bold(true) - -var warningColor = defaultStyle. - Foreground(lipgloss.CompleteAdaptiveColor{ - Light: lipgloss.CompleteColor{TrueColor: "#ffff87", ANSI256: "228", ANSI: "0"}, - Dark: lipgloss.CompleteColor{TrueColor: "#ffff87", ANSI256: "228", ANSI: "0"}, - }). - Bold(true) - -var infoColor = defaultStyle. - Foreground(lipgloss.CompleteAdaptiveColor{ - Light: lipgloss.CompleteColor{TrueColor: "#00afff", ANSI256: "039", ANSI: "0"}, - Dark: lipgloss.CompleteColor{TrueColor: "#00afff", ANSI256: "039", ANSI: "0"}, - }). - Bold(true) - -func ErrorText(text string) lipgloss.Style { - return errorColor.Copy().SetString(text) -} - -func SuccessText(text string) lipgloss.Style { - return successColor.Copy().SetString(text) -} - -func WarningText(text string) lipgloss.Style { - return warningColor.Copy().SetString(text) -} - -func InfoText(text string) lipgloss.Style { - return infoColor.Copy().SetString(text) -} - -type line struct { - args []interface{} - styles bool -} - -func NewLine(args ...interface{}) line { - return line{ - args: args, - styles: true, - } -} - -func (l line) DisableStyle() line { - l.styles = false - return l -} - -func (l line) Merge(lines ...line) line { - for _, line := range lines { - l.args = append(l.args, line.args...) - } - return l -} - -func (l line) NotEmpty() bool { - return len(l.args) > 0 -} - -func (l line) String() string { - if l.styles { - return fmt.Sprint(l.args...) - } - return fmt.Sprint(removeStyles(l.args)...) -} - -func removeStyles(args []interface{}) []interface{} { - for i, arg := range args { - if typed, ok := arg.(lipgloss.Style); ok { - args[i] = typed.Value() - } - } - - return args -} diff --git a/src/uxBlock/styles/helpers.go b/src/uxBlock/styles/helpers.go new file mode 100644 index 00000000..e3f97991 --- /dev/null +++ b/src/uxBlock/styles/helpers.go @@ -0,0 +1,47 @@ +package styles + +import "github.com/charmbracelet/lipgloss" + +func SuccessLine(text string) Line { + return NewLine(SuccessText(SuccessIcon), " ", SuccessPrefix(), " ", SuccessText(text)) +} + +func InfoWithValueLine(text string, value string) Line { + return NewLine(InfoText(InfoIcon), " ", InfoPrefix(), " ", InfoText(text), ": ", SelectText(value)) +} + +func InfoLine(text string) Line { + return NewLine(InfoText(InfoIcon), " ", InfoPrefix(), " ", InfoText(text)) +} + +func WarningLine(text string) Line { + return NewLine(WarningText(WarningIcon), " ", WarningPrefix(), " ", WarningText(text)) +} + +func ErrorLine(text string) Line { + return NewLine(ErrorText(ErrorIcon), " ", ErrorPrefix(), " ", ErrorText(text)) +} + +func SelectLine(text string) Line { + return NewLine(SelectText(SelectIcon), " ", SelectPrefix(), " ", InfoText(text)) +} + +func ErrorText(text string) lipgloss.Style { + return ErrorColor().SetString(text) +} + +func SuccessText(text string) lipgloss.Style { + return SuccessColor().SetString(text) +} + +func WarningText(text string) lipgloss.Style { + return WarningColor().SetString(text) +} + +func InfoText(text string) lipgloss.Style { + return InfoColor().SetString(text) +} + +func SelectText(text string) lipgloss.Style { + return SelectColor().SetString(text) +} diff --git a/src/uxBlock/styles/line.go b/src/uxBlock/styles/line.go new file mode 100644 index 00000000..48836396 --- /dev/null +++ b/src/uxBlock/styles/line.go @@ -0,0 +1,50 @@ +package styles + +import ( + "fmt" + + "github.com/charmbracelet/lipgloss" +) + +type Line struct { + args []interface{} + styles bool +} + +func NewLine(args ...interface{}) Line { + return Line{ + args: args, + styles: true, + } +} + +func (l Line) DisableStyle() Line { + l.styles = false + return l +} + +func (l Line) Merge(lines ...Line) Line { + for _, line := range lines { + l.args = append(l.args, line.args...) + } + return l +} + +func (l Line) NotEmpty() bool { + return len(l.args) > 0 +} + +func (l Line) String() string { + args := l.args + + for i, arg := range args { + if typed, ok := arg.(lipgloss.Style); ok { + if l.styles { + args[i] = typed.String() + } else { + args[i] = typed.Value() + } + } + } + return fmt.Sprint(args...) +} diff --git a/src/uxBlock/styles/styles.go b/src/uxBlock/styles/styles.go new file mode 100644 index 00000000..6abba119 --- /dev/null +++ b/src/uxBlock/styles/styles.go @@ -0,0 +1,186 @@ +package styles + +import ( + "os" + + "github.com/charmbracelet/lipgloss" +) + +const ( + SuccessIcon = "✔" + ErrorIcon = "✗" + SelectIcon = "➔" + InfoIcon = "➤" + WarningIcon = "!" +) + +var defaultRender = lipgloss.NewRenderer(os.Stdout) + +func defaultStyle() lipgloss.Style { + return lipgloss.NewStyle().Renderer(defaultRender) +} + +func SuccessPrefix() lipgloss.Style { + return defaultStyle(). + Foreground(lipgloss.CompleteAdaptiveColor{ + Light: lipgloss.CompleteColor{TrueColor: "#FFFFFF", ANSI256: "231", ANSI: "97"}, + Dark: lipgloss.CompleteColor{TrueColor: "#000000", ANSI256: "0", ANSI: "0"}, + }). + Background(lipgloss.CompleteAdaptiveColor{ + Light: lipgloss.CompleteColor{TrueColor: "#66bb6a", ANSI256: "114", ANSI: "32"}, + Dark: lipgloss.CompleteColor{TrueColor: "#66bb6a", ANSI256: "114", ANSI: "32"}, + }). + PaddingLeft(1).PaddingRight(1). + SetString("DONE") +} + +func SuccessColor() lipgloss.Style { + return defaultStyle(). + Foreground(lipgloss.CompleteAdaptiveColor{ + Light: lipgloss.CompleteColor{TrueColor: "#66bb6a", ANSI256: "114", ANSI: "32"}, + Dark: lipgloss.CompleteColor{TrueColor: "#66bb6a", ANSI256: "114", ANSI: "32"}, + }) +} + +func ErrorPrefix() lipgloss.Style { + return defaultStyle(). + Foreground(lipgloss.CompleteAdaptiveColor{ + Light: lipgloss.CompleteColor{TrueColor: "#FFFFFF", ANSI256: "231", ANSI: "97"}, + Dark: lipgloss.CompleteColor{TrueColor: "#000000", ANSI256: "0", ANSI: "0"}, + }). + Background(lipgloss.CompleteAdaptiveColor{ + Light: lipgloss.CompleteColor{TrueColor: "#ff1b16", ANSI256: "196", ANSI: "91"}, + Dark: lipgloss.CompleteColor{TrueColor: "#ff1b16", ANSI256: "196", ANSI: "91"}, + }). + PaddingLeft(1).PaddingRight(1). + SetString("ERR") +} + +func ErrorColor() lipgloss.Style { + return defaultStyle(). + Foreground(lipgloss.CompleteAdaptiveColor{ + Light: lipgloss.CompleteColor{TrueColor: "#ff1b16", ANSI256: "196", ANSI: "91"}, + Dark: lipgloss.CompleteColor{TrueColor: "#ff1b16", ANSI256: "196", ANSI: "91"}, + }) +} + +func WarningPrefix() lipgloss.Style { + return defaultStyle(). + Foreground(lipgloss.CompleteAdaptiveColor{ + Light: lipgloss.CompleteColor{TrueColor: "#FFFFFF", ANSI256: "231", ANSI: "97"}, + Dark: lipgloss.CompleteColor{TrueColor: "#000000", ANSI256: "0", ANSI: "0"}, + }). + Background(lipgloss.CompleteAdaptiveColor{ + Light: lipgloss.CompleteColor{TrueColor: "#ffa726", ANSI256: "216", ANSI: "93"}, + Dark: lipgloss.CompleteColor{TrueColor: "#ffa726", ANSI256: "216", ANSI: "93"}, + }). + PaddingLeft(1).PaddingRight(1). + SetString("WARN") +} + +func WarningColor() lipgloss.Style { + return defaultStyle(). + Foreground(lipgloss.CompleteAdaptiveColor{ + Light: lipgloss.CompleteColor{TrueColor: "#ffa726", ANSI256: "216", ANSI: "93"}, + Dark: lipgloss.CompleteColor{TrueColor: "#ffa726", ANSI256: "216", ANSI: "93"}, + }) +} + +func InfoPrefix() lipgloss.Style { + return defaultStyle(). + Foreground(lipgloss.CompleteAdaptiveColor{ + Light: lipgloss.CompleteColor{TrueColor: "#FFFFFF", ANSI256: "231", ANSI: "97"}, + Dark: lipgloss.CompleteColor{TrueColor: "#000000", ANSI256: "0", ANSI: "0"}, + }). + Background(lipgloss.CompleteAdaptiveColor{ + Light: lipgloss.CompleteColor{TrueColor: "#e6e7ec", ANSI256: "231", ANSI: "37"}, + Dark: lipgloss.CompleteColor{TrueColor: "#e6e7ec", ANSI256: "231", ANSI: "37"}, + }). + PaddingLeft(1).PaddingRight(1). + SetString("INFO") +} + +func InfoColor() lipgloss.Style { + return defaultStyle(). + Foreground(lipgloss.CompleteAdaptiveColor{ + Light: lipgloss.CompleteColor{TrueColor: "#e6e7ec", ANSI256: "231", ANSI: "37"}, + Dark: lipgloss.CompleteColor{TrueColor: "#e6e7ec", ANSI256: "231", ANSI: "37"}, + }) +} + +func SelectPrefix() lipgloss.Style { + return defaultStyle(). + Foreground(lipgloss.CompleteAdaptiveColor{ + Light: lipgloss.CompleteColor{TrueColor: "#FFFFFF", ANSI256: "231", ANSI: "97"}, + Dark: lipgloss.CompleteColor{TrueColor: "#000000", ANSI256: "0", ANSI: "0"}, + }). + Background(lipgloss.CompleteAdaptiveColor{ + Light: lipgloss.CompleteColor{TrueColor: "#07c", ANSI256: "27", ANSI: "30"}, + Dark: lipgloss.CompleteColor{TrueColor: "#07c", ANSI256: "27", ANSI: "30"}, + }). + PaddingLeft(1).PaddingRight(1). + SetString("SELECT") +} + +func SelectColor() lipgloss.Style { + return defaultStyle(). + Foreground(lipgloss.CompleteAdaptiveColor{ + Light: lipgloss.CompleteColor{TrueColor: "#07c", ANSI256: "27", ANSI: "30"}, + Dark: lipgloss.CompleteColor{TrueColor: "#07c", ANSI256: "27", ANSI: "30"}, + }) +} + +func CobraSectionColor() lipgloss.Style { + return defaultStyle(). + Foreground(lipgloss.CompleteAdaptiveColor{ + Light: lipgloss.CompleteColor{TrueColor: "#cc0077", ANSI256: "162", ANSI: "31"}, + Dark: lipgloss.CompleteColor{TrueColor: "#cc0077", ANSI256: "162", ANSI: "31"}, + }) +} + +func CobraItemNameColor() lipgloss.Style { + return defaultStyle(). + Foreground(lipgloss.CompleteAdaptiveColor{ + Light: lipgloss.CompleteColor{TrueColor: "#00ccbb", ANSI256: "44", ANSI: "36"}, + Dark: lipgloss.CompleteColor{TrueColor: "#00ccbb", ANSI256: "44", ANSI: "36"}, + }) +} + +func DialogBox() lipgloss.Style { + return defaultStyle(). + Border(lipgloss.RoundedBorder()). + BorderForeground(InfoColor().GetForeground()). + Padding(1, 0). + BorderTop(true). + BorderLeft(true). + BorderRight(true). + BorderBottom(true) +} + +func DialogButton() lipgloss.Style { + return defaultStyle(). + Foreground(InfoPrefix().GetForeground()). + Background(InfoPrefix().GetBackground()). + Padding(0, 3). + MarginRight(2). + MarginTop(1) +} + +func ActiveDialogButton() lipgloss.Style { + return DialogButton(). + Foreground(SelectPrefix(). + GetForeground()). + Background(SelectPrefix().GetBackground()) +} + +func TableRow() lipgloss.Style { + return InfoColor(). + PaddingLeft(1). + PaddingRight(1) +} + +func TableRowActive() lipgloss.Style { + return SelectColor(). + PaddingLeft(1). + PaddingRight(1) +} diff --git a/src/uxBlock/table.go b/src/uxBlock/table.go index 7f2c8008..9f6e7898 100644 --- a/src/uxBlock/table.go +++ b/src/uxBlock/table.go @@ -6,6 +6,7 @@ import ( "github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss/table" + "github.com/zeropsio/zcli/src/uxBlock/styles" ) type tableConfig struct { @@ -88,40 +89,19 @@ func (b *uxBlocks) Table(body *TableBody, auxOptions ...TableOption) { opt(&cfg) } - baseStyle := lipgloss.NewStyle().Padding(0, 1) - headerStyle := baseStyle.Copy().Foreground(lipgloss.Color("252")).Bold(true) - - baseStyle.SetString() - t := table.New(). + BorderStyle(styles.InfoColor()). Border(lipgloss.NormalBorder()). - BorderStyle(lipgloss.NewStyle().Foreground(lipgloss.Color("238"))). StyleFunc(func(row, col int) lipgloss.Style { - if row == 0 && cfg.header != nil { - return headerStyle - } - - even := row%2 == 0 - - if even { - return baseStyle.Copy().Foreground(lipgloss.Color("245")) - } - return baseStyle.Copy().Foreground(lipgloss.Color("252")) + return styles.TableRow() }) if cfg.header != nil { - capitalizeHeaders := func(data []string) []string { - for i := range data { - data[i] = strings.ToUpper(data[i]) - } - return data - } - headers := make([]string, len(cfg.header.cells)) for i, header := range cfg.header.cells { - headers[i] = header.Text + headers[i] = strings.ToUpper(header.Text) } - t = t.Headers(capitalizeHeaders(headers)...) + t = t.Headers(headers...) } rows := make([][]string, len(body.rows)) diff --git a/src/uxHelpers/org.go b/src/uxHelpers/org.go index a958263d..7a8b3462 100644 --- a/src/uxHelpers/org.go +++ b/src/uxHelpers/org.go @@ -8,6 +8,7 @@ import ( "github.com/zeropsio/zcli/src/entity/repository" "github.com/zeropsio/zcli/src/i18n" "github.com/zeropsio/zcli/src/uxBlock" + "github.com/zeropsio/zcli/src/uxBlock/styles" "github.com/zeropsio/zcli/src/zeropsRestApiClient" ) @@ -22,7 +23,7 @@ func PrintOrgSelector( } if len(orgs) == 0 { - uxBlocks.PrintWarningLine(i18n.T(i18n.OrgSelectorListEmpty)) + uxBlocks.PrintWarning(styles.WarningLine(i18n.T(i18n.OrgSelectorListEmpty))) return nil, nil } diff --git a/src/uxHelpers/project.go b/src/uxHelpers/project.go index 52ac8278..33ebe306 100644 --- a/src/uxHelpers/project.go +++ b/src/uxHelpers/project.go @@ -8,6 +8,7 @@ import ( "github.com/zeropsio/zcli/src/entity/repository" "github.com/zeropsio/zcli/src/i18n" "github.com/zeropsio/zcli/src/uxBlock" + "github.com/zeropsio/zcli/src/uxBlock/styles" "github.com/zeropsio/zcli/src/zeropsRestApiClient" ) @@ -22,7 +23,7 @@ func PrintProjectSelector( } if len(projects) == 0 { - uxBlocks.PrintWarningLine(i18n.T(i18n.ProjectSelectorListEmpty)) + uxBlocks.PrintWarning(styles.WarningLine(i18n.T(i18n.ProjectSelectorListEmpty))) return nil, nil } diff --git a/src/uxHelpers/service.go b/src/uxHelpers/service.go index b49f3872..86772b67 100644 --- a/src/uxHelpers/service.go +++ b/src/uxHelpers/service.go @@ -8,6 +8,7 @@ import ( "github.com/zeropsio/zcli/src/entity/repository" "github.com/zeropsio/zcli/src/i18n" "github.com/zeropsio/zcli/src/uxBlock" + "github.com/zeropsio/zcli/src/uxBlock/styles" "github.com/zeropsio/zcli/src/zeropsRestApiClient" ) @@ -23,7 +24,7 @@ func PrintServiceSelector( } if len(services) == 0 { - uxBlocks.PrintWarningLine(i18n.T(i18n.ServiceSelectorListEmpty)) + uxBlocks.PrintWarning(styles.WarningLine(i18n.T(i18n.ServiceSelectorListEmpty))) return nil, nil } diff --git a/src/uxHelpers/spinner.go b/src/uxHelpers/spinner.go index 517f3bd5..2abcdcbd 100644 --- a/src/uxHelpers/spinner.go +++ b/src/uxHelpers/spinner.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" "github.com/zeropsio/zcli/src/i18n" "github.com/zeropsio/zcli/src/uxBlock" + "github.com/zeropsio/zcli/src/uxBlock/styles" "github.com/zeropsio/zcli/src/zeropsRestApiClient" "github.com/zeropsio/zerops-go/dto/input/path" "github.com/zeropsio/zerops-go/types/enum" @@ -21,7 +22,7 @@ func ProcessCheckWithSpinner( ) error { spinners := make([]*uxBlock.Spinner, 0, len(processList)) for _, process := range processList { - spinners = append(spinners, uxBlock.NewSpinner(process.RunningMessage)) + spinners = append(spinners, uxBlock.NewSpinner(styles.NewLine(styles.InfoText(process.RunningMessage)))) } stopFunc := uxBlocks.RunSpinners(ctx, spinners) @@ -39,7 +40,7 @@ func ProcessCheckWithSpinner( err := process.F(ctx) if err != nil { - spinners[i].Finish(uxBlock.NewLine(uxBlock.ErrorIcon, uxBlock.ErrorText(process.ErrorMessageMessage)).String()) + spinners[i].Finish(styles.ErrorLine(process.ErrorMessageMessage)) stopFunc() once.Do(func() { @@ -47,7 +48,7 @@ func ProcessCheckWithSpinner( }) return } - spinners[i].Finish(uxBlock.NewLine(uxBlock.SuccessIcon, uxBlock.SuccessText(process.SuccessMessage)).String()) + spinners[i].Finish(styles.SuccessLine(process.SuccessMessage)) }(i) } diff --git a/src/yamlReader/readYaml.go b/src/yamlReader/readYaml.go index 8c2312f9..a5be0266 100644 --- a/src/yamlReader/readYaml.go +++ b/src/yamlReader/readYaml.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" "github.com/zeropsio/zcli/src/i18n" "github.com/zeropsio/zcli/src/uxBlock" + "github.com/zeropsio/zcli/src/uxBlock/styles" ) func ReadContent(uxBlocks uxBlock.UxBlocks, importYamlPath string, workingDir string) ([]byte, error) { @@ -29,7 +30,7 @@ func ReadContent(uxBlocks uxBlock.UxBlocks, importYamlPath string, workingDir st return nil, errors.New(i18n.T(i18n.ImportYamlNotFound)) } - uxBlocks.PrintLine(fmt.Sprintf("%s: %s", i18n.T(i18n.ImportYamlFound), importYamlPath)) + uxBlocks.PrintInfo(styles.InfoLine(fmt.Sprintf("%s: %s", i18n.T(i18n.ImportYamlFound), importYamlPath))) if fileInfo.Size() == 0 { return nil, errors.New(i18n.T(i18n.ImportYamlEmpty)) @@ -48,6 +49,6 @@ func ReadContent(uxBlocks uxBlock.UxBlocks, importYamlPath string, workingDir st return nil, errors.New(i18n.T(i18n.ImportYamlCorrupted)) } - uxBlocks.PrintLine(i18n.T(i18n.ImportYamlOk)) + uxBlocks.PrintInfo(styles.InfoLine(i18n.T(i18n.ImportYamlOk))) return yamlContent, nil }