mirror of
https://github.com/argoproj/argo-cd.git
synced 2026-02-20 09:38:49 +01:00
Compare commits
5 Commits
hydrator-c
...
v2.3.0-rc1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d7eed4932 | ||
|
|
af8c5eb07a | ||
|
|
1a476f7564 | ||
|
|
7f15389c72 | ||
|
|
1a3556e1cc |
2
.github/workflows/release.yaml
vendored
2
.github/workflows/release.yaml
vendored
@@ -197,6 +197,8 @@ jobs:
|
||||
if: ${{ env.DRY_RUN != 'true' }}
|
||||
|
||||
|
||||
- uses: docker/setup-qemu-action@v1
|
||||
- uses: docker/setup-buildx-action@v1
|
||||
- name: Build and push Docker image for release
|
||||
run: |
|
||||
set -ue
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/argoproj/pkg/rand"
|
||||
@@ -68,7 +67,7 @@ func runCommand(ctx context.Context, command Command, path string, env []string)
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
// Make sure the command is killed immediately on timeout. https://stackoverflow.com/a/38133948/684776
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
||||
cmd.SysProcAttr = newSysProcAttr(true)
|
||||
|
||||
start := time.Now()
|
||||
err = cmd.Start()
|
||||
@@ -80,7 +79,7 @@ func runCommand(ctx context.Context, command Command, path string, env []string)
|
||||
<-ctx.Done()
|
||||
// Kill by group ID to make sure child processes are killed. The - tells `kill` that it's a group ID.
|
||||
// Since we didn't set Pgid in SysProcAttr, the group ID is the same as the process ID. https://pkg.go.dev/syscall#SysProcAttr
|
||||
_ = syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
|
||||
_ = sysCallKill(-cmd.Process.Pid)
|
||||
}()
|
||||
|
||||
err = cmd.Wait()
|
||||
|
||||
16
cmpserver/plugin/plugin_unix.go
Normal file
16
cmpserver/plugin/plugin_unix.go
Normal file
@@ -0,0 +1,16 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func newSysProcAttr(setpgid bool) *syscall.SysProcAttr {
|
||||
return &syscall.SysProcAttr{Setpgid: setpgid}
|
||||
}
|
||||
|
||||
func sysCallKill(pid int) error {
|
||||
return syscall.Kill(pid, syscall.SIGKILL)
|
||||
}
|
||||
16
cmpserver/plugin/plugin_windows.go
Normal file
16
cmpserver/plugin/plugin_windows.go
Normal file
@@ -0,0 +1,16 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func newSysProcAttr(setpgid bool) *syscall.SysProcAttr {
|
||||
return &syscall.SysProcAttr{}
|
||||
}
|
||||
|
||||
func sysCallKill(pid int) error {
|
||||
return nil
|
||||
}
|
||||
@@ -5,7 +5,7 @@ kind: Kustomization
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: latest
|
||||
newTag: v2.3.0-rc1
|
||||
resources:
|
||||
- ./application-controller
|
||||
- ./dex
|
||||
|
||||
@@ -3033,7 +3033,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -3082,7 +3082,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
name: copyutil
|
||||
volumeMounts:
|
||||
- mountPath: /var/run/argocd
|
||||
@@ -3247,7 +3247,7 @@ spec:
|
||||
key: controller.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -11,4 +11,4 @@ resources:
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: latest
|
||||
newTag: v2.3.0-rc1
|
||||
|
||||
@@ -11,7 +11,7 @@ patchesStrategicMerge:
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: latest
|
||||
newTag: v2.3.0-rc1
|
||||
resources:
|
||||
- ../../base/application-controller
|
||||
- ../../base/dex
|
||||
|
||||
@@ -10348,7 +10348,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
volumeMounts:
|
||||
@@ -10381,7 +10381,7 @@ spec:
|
||||
containers:
|
||||
- command:
|
||||
- argocd-notifications
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -10614,7 +10614,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -10663,7 +10663,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
name: copyutil
|
||||
volumeMounts:
|
||||
- mountPath: /var/run/argocd
|
||||
@@ -10890,7 +10890,7 @@ spec:
|
||||
key: server.http.cookie.maxnumber
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -11086,7 +11086,7 @@ spec:
|
||||
key: controller.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -7644,7 +7644,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
volumeMounts:
|
||||
@@ -7677,7 +7677,7 @@ spec:
|
||||
containers:
|
||||
- command:
|
||||
- argocd-notifications
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -7910,7 +7910,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -7959,7 +7959,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
name: copyutil
|
||||
volumeMounts:
|
||||
- mountPath: /var/run/argocd
|
||||
@@ -8186,7 +8186,7 @@ spec:
|
||||
key: server.http.cookie.maxnumber
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -8382,7 +8382,7 @@ spec:
|
||||
key: controller.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -9718,7 +9718,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
volumeMounts:
|
||||
@@ -9751,7 +9751,7 @@ spec:
|
||||
containers:
|
||||
- command:
|
||||
- argocd-notifications
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -9948,7 +9948,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -9997,7 +9997,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
name: copyutil
|
||||
volumeMounts:
|
||||
- mountPath: /var/run/argocd
|
||||
@@ -10220,7 +10220,7 @@ spec:
|
||||
key: server.http.cookie.maxnumber
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -10410,7 +10410,7 @@ spec:
|
||||
key: controller.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -7014,7 +7014,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
volumeMounts:
|
||||
@@ -7047,7 +7047,7 @@ spec:
|
||||
containers:
|
||||
- command:
|
||||
- argocd-notifications
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -7244,7 +7244,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -7293,7 +7293,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
name: copyutil
|
||||
volumeMounts:
|
||||
- mountPath: /var/run/argocd
|
||||
@@ -7516,7 +7516,7 @@ spec:
|
||||
key: server.http.cookie.maxnumber
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -7706,7 +7706,7 @@ spec:
|
||||
key: controller.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.3.0-rc1
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import {Checkbox} from 'argo-ui';
|
||||
import {useData} from 'argo-ui/v2';
|
||||
import * as minimatch from 'minimatch';
|
||||
import * as React from 'react';
|
||||
import {Context} from '../../../shared/context';
|
||||
import {Application, ApplicationDestination, Cluster, HealthStatusCode, HealthStatuses, SyncStatusCode, SyncStatuses} from '../../../shared/models';
|
||||
import {AppsListPreferences, services} from '../../../shared/services';
|
||||
import {Filter, FiltersGroup} from '../filter/filter';
|
||||
@@ -13,6 +15,7 @@ export interface FilterResult {
|
||||
health: boolean;
|
||||
namespaces: boolean;
|
||||
clusters: boolean;
|
||||
favourite: boolean;
|
||||
labels: boolean;
|
||||
}
|
||||
|
||||
@@ -28,6 +31,7 @@ export function getFilterResults(applications: Application[], pref: AppsListPref
|
||||
sync: pref.syncFilter.length === 0 || pref.syncFilter.includes(app.status.sync.status),
|
||||
health: pref.healthFilter.length === 0 || pref.healthFilter.includes(app.status.health.status),
|
||||
namespaces: pref.namespacesFilter.length === 0 || pref.namespacesFilter.some(ns => app.spec.destination.namespace && minimatch(app.spec.destination.namespace, ns)),
|
||||
favourite: !pref.showFavorites || pref.favoritesAppList.includes(app.metadata.name),
|
||||
clusters:
|
||||
pref.clustersFilter.length === 0 ||
|
||||
pref.clustersFilter.some(filterString => {
|
||||
@@ -211,6 +215,23 @@ const NamespaceFilter = (props: AppFilterProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
const FavoriteFilter = (props: AppFilterProps) => {
|
||||
const ctx = React.useContext(Context);
|
||||
return (
|
||||
<div className='filter'>
|
||||
<Checkbox
|
||||
checked={!!props.pref.showFavorites}
|
||||
id='favouriteFilter'
|
||||
onChange={val => {
|
||||
ctx.navigation.goto('.', {showFavorites: val}, {replace: true});
|
||||
services.viewPreferences.updatePreferences({appList: {...props.pref, showFavorites: val}});
|
||||
}}
|
||||
/>{' '}
|
||||
<label htmlFor='favouriteFilter'>FAVORITES ONLY</label>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const ApplicationsFilter = (props: AppFilterProps) => {
|
||||
const setShown = (val: boolean) => {
|
||||
services.viewPreferences.updatePreferences({appList: {...props.pref, hideFilters: !val}});
|
||||
@@ -218,6 +239,7 @@ export const ApplicationsFilter = (props: AppFilterProps) => {
|
||||
|
||||
return (
|
||||
<FiltersGroup setShown={setShown} expanded={!props.pref.hideFilters} content={props.children}>
|
||||
<FavoriteFilter {...props} />
|
||||
<SyncFilter {...props} />
|
||||
<HealthFilter {...props} />
|
||||
<LabelsFilter {...props} />
|
||||
|
||||
@@ -172,7 +172,6 @@
|
||||
&__external-links-icon-container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 28px;
|
||||
}
|
||||
|
||||
.filters-group__panel {
|
||||
|
||||
@@ -122,6 +122,9 @@ const ViewPref = ({children}: {children: (pref: AppsListPreferences & {page: num
|
||||
.split(',')
|
||||
.filter(item => !!item);
|
||||
}
|
||||
if (params.get('showFavorites') != null) {
|
||||
viewPref.showFavorites = params.get('showFavorites') === 'true';
|
||||
}
|
||||
if (params.get('view') != null) {
|
||||
viewPref.view = params.get('view') as AppsListViewType;
|
||||
} else {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {DropDownMenu} from 'argo-ui';
|
||||
import {DataLoader, DropDownMenu, Tooltip} from 'argo-ui';
|
||||
import * as React from 'react';
|
||||
import {Key, KeybindingContext, useNav} from 'argo-ui/v2';
|
||||
import {Cluster} from '../../../shared/components';
|
||||
@@ -9,6 +9,7 @@ import * as AppUtils from '../utils';
|
||||
import {OperationState} from '../utils';
|
||||
import {ApplicationsLabels} from './applications-labels';
|
||||
import {ApplicationsSource} from './applications-source';
|
||||
import {services} from '../../../shared/services';
|
||||
require('./applications-table.scss');
|
||||
|
||||
export const ApplicationsTable = (props: {
|
||||
@@ -34,66 +35,98 @@ export const ApplicationsTable = (props: {
|
||||
return (
|
||||
<Consumer>
|
||||
{ctx => (
|
||||
<div className='applications-table argo-table-list argo-table-list--clickable'>
|
||||
{props.applications.map((app, i) => (
|
||||
<div
|
||||
key={app.metadata.name}
|
||||
className={`argo-table-list__row
|
||||
<DataLoader load={() => services.viewPreferences.getPreferences()}>
|
||||
{pref => {
|
||||
const favList = pref.appList.favoritesAppList || [];
|
||||
return (
|
||||
<div className='applications-table argo-table-list argo-table-list--clickable'>
|
||||
{props.applications.map((app, i) => (
|
||||
<div
|
||||
key={app.metadata.name}
|
||||
className={`argo-table-list__row
|
||||
applications-list__entry applications-list__entry--health-${app.status.health.status} ${selectedApp === i ? 'applications-tiles__selected' : ''}`}>
|
||||
<div className={`row applications-list__table-row`} onClick={e => ctx.navigation.goto(`/applications/${app.metadata.name}`, {}, {event: e})}>
|
||||
<div className='columns small-4'>
|
||||
<div className='row'>
|
||||
<div className='show-for-xxlarge columns small-3'>Project:</div>
|
||||
<div className='columns small-12 xxlarge-9'>{app.spec.project}</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='show-for-xxlarge columns small-3'>Name:</div>
|
||||
<div className='columns small-12 xxlarge-9'>
|
||||
{app.metadata.name} <ApplicationURLs urls={AppUtils.getExternalUrls(app.metadata.annotations, app.status.summary.externalURLs)} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='columns small-6'>
|
||||
<div className='row'>
|
||||
<div className='show-for-xxlarge columns small-2'>Source:</div>
|
||||
<div className='columns small-12 xxlarge-10 applications-table-source' style={{position: 'relative'}}>
|
||||
<div className='applications-table-source__link'>
|
||||
<ApplicationsSource source={app.spec.source} />
|
||||
<div
|
||||
className={`row applications-list__table-row`}
|
||||
onClick={e => ctx.navigation.goto(`/applications/${app.metadata.name}`, {}, {event: e})}>
|
||||
<div className='columns small-4'>
|
||||
<div className='row'>
|
||||
<div className=' columns small-2'>
|
||||
<div>
|
||||
<Tooltip content={favList?.includes(app.metadata.name) ? 'Remove Favorite' : 'Add Favorite'}>
|
||||
<button
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
favList?.includes(app.metadata.name)
|
||||
? favList.splice(favList.indexOf(app.metadata.name), 1)
|
||||
: favList.push(app.metadata.name);
|
||||
services.viewPreferences.updatePreferences({appList: {...pref.appList, favoritesAppList: favList}});
|
||||
}}>
|
||||
<i
|
||||
className={'fas fa-star'}
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
marginRight: '7px',
|
||||
color: favList?.includes(app.metadata.name) ? '#1FBDD0' : 'grey'
|
||||
}}
|
||||
/>
|
||||
</button>
|
||||
</Tooltip>
|
||||
<ApplicationURLs urls={AppUtils.getExternalUrls(app.metadata.annotations, app.status.summary.externalURLs)} />
|
||||
</div>
|
||||
</div>
|
||||
<div className='show-for-xxlarge columns small-4'>Project:</div>
|
||||
<div className='columns small-12 xxlarge-6'>{app.spec.project}</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className=' columns small-2' />
|
||||
<div className='show-for-xxlarge columns small-4'>Name:</div>
|
||||
<div className='columns small-12 xxlarge-6'>{app.metadata.name}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='applications-table-source__labels'>
|
||||
<ApplicationsLabels app={app} />
|
||||
|
||||
<div className='columns small-6'>
|
||||
<div className='row'>
|
||||
<div className='show-for-xxlarge columns small-2'>Source:</div>
|
||||
<div className='columns small-12 xxlarge-10 applications-table-source' style={{position: 'relative'}}>
|
||||
<div className='applications-table-source__link'>
|
||||
<ApplicationsSource source={app.spec.source} />
|
||||
</div>
|
||||
<div className='applications-table-source__labels'>
|
||||
<ApplicationsLabels app={app} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='show-for-xxlarge columns small-2'>Destination:</div>
|
||||
<div className='columns small-12 xxlarge-10'>
|
||||
<Cluster server={app.spec.destination.server} name={app.spec.destination.name} />/{app.spec.destination.namespace}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='columns small-2'>
|
||||
<AppUtils.HealthStatusIcon state={app.status.health} /> <span>{app.status.health.status}</span> <br />
|
||||
<AppUtils.ComparisonStatusIcon status={app.status.sync.status} />
|
||||
<span>{app.status.sync.status}</span> <OperationState app={app} quiet={true} />
|
||||
<DropDownMenu
|
||||
anchor={() => (
|
||||
<button className='argo-button argo-button--light argo-button--lg argo-button--short'>
|
||||
<i className='fa fa-ellipsis-v' />
|
||||
</button>
|
||||
)}
|
||||
items={[
|
||||
{title: 'Sync', action: () => props.syncApplication(app.metadata.name)},
|
||||
{title: 'Refresh', action: () => props.refreshApplication(app.metadata.name)},
|
||||
{title: 'Delete', action: () => props.deleteApplication(app.metadata.name)}
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='show-for-xxlarge columns small-2'>Destination:</div>
|
||||
<div className='columns small-12 xxlarge-10'>
|
||||
<Cluster server={app.spec.destination.server} name={app.spec.destination.name} />/{app.spec.destination.namespace}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='columns small-2'>
|
||||
<AppUtils.HealthStatusIcon state={app.status.health} /> <span>{app.status.health.status}</span>
|
||||
<br />
|
||||
<AppUtils.ComparisonStatusIcon status={app.status.sync.status} />
|
||||
<span>{app.status.sync.status}</span> <OperationState app={app} quiet={true} />
|
||||
<DropDownMenu
|
||||
anchor={() => (
|
||||
<button className='argo-button argo-button--light argo-button--lg argo-button--short'>
|
||||
<i className='fa fa-ellipsis-v' />
|
||||
</button>
|
||||
)}
|
||||
items={[
|
||||
{title: 'Sync', action: () => props.syncApplication(app.metadata.name)},
|
||||
{title: 'Refresh', action: () => props.refreshApplication(app.metadata.name)},
|
||||
{title: 'Delete', action: () => props.deleteApplication(app.metadata.name)}
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
</DataLoader>
|
||||
)}
|
||||
</Consumer>
|
||||
);
|
||||
|
||||
@@ -102,158 +102,178 @@ export const ApplicationTiles = ({applications, syncApplication, refreshApplicat
|
||||
<Consumer>
|
||||
{ctx => (
|
||||
<DataLoader load={() => services.viewPreferences.getPreferences()}>
|
||||
{pref => (
|
||||
<div className='applications-tiles argo-table-list argo-table-list--clickable row small-up-1 medium-up-2 large-up-3 xxxlarge-up-4' ref={appContainerRef}>
|
||||
{applications.map((app, i) => (
|
||||
<div key={app.metadata.name} className='column column-block'>
|
||||
<div
|
||||
ref={appRef.set ? null : appRef.ref}
|
||||
className={`argo-table-list__row applications-list__entry applications-list__entry--health-${app.status.health.status} ${
|
||||
selectedApp === i ? 'applications-tiles__selected' : ''
|
||||
}`}>
|
||||
<div className='row' onClick={e => ctx.navigation.goto(`/applications/${app.metadata.name}`, {view: pref.appDetails.view}, {event: e})}>
|
||||
<div className={`columns small-12 applications-list__info qe-applications-list-${app.metadata.name}`}>
|
||||
<div className='applications-list__external-link'>
|
||||
<ApplicationURLs urls={AppUtils.getExternalUrls(app.metadata.annotations, app.status.summary.externalURLs)} />
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='columns small-12'>
|
||||
<i className={'icon argo-icon-' + (app.spec.source.chart != null ? 'helm' : 'git')} />
|
||||
<span className='applications-list__title'>{app.metadata.name}</span>
|
||||
{pref => {
|
||||
const favList = pref.appList.favoritesAppList || [];
|
||||
return (
|
||||
<div
|
||||
className='applications-tiles argo-table-list argo-table-list--clickable row small-up-1 medium-up-2 large-up-3 xxxlarge-up-4'
|
||||
ref={appContainerRef}>
|
||||
{applications.map((app, i) => (
|
||||
<div key={app.metadata.name} className='column column-block'>
|
||||
<div
|
||||
ref={appRef.set ? null : appRef.ref}
|
||||
className={`argo-table-list__row applications-list__entry applications-list__entry--health-${app.status.health.status} ${
|
||||
selectedApp === i ? 'applications-tiles__selected' : ''
|
||||
}`}>
|
||||
<div className='row' onClick={e => ctx.navigation.goto(`/applications/${app.metadata.name}`, {view: pref.appDetails.view}, {event: e})}>
|
||||
<div className={`columns small-12 applications-list__info qe-applications-list-${app.metadata.name}`}>
|
||||
<div className='applications-list__external-link'>
|
||||
<ApplicationURLs urls={AppUtils.getExternalUrls(app.metadata.annotations, app.status.summary.externalURLs)} />
|
||||
<Tooltip content={favList?.includes(app.metadata.name) ? 'Remove Favorite' : 'Add Favorite'}>
|
||||
<button
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
favList?.includes(app.metadata.name)
|
||||
? favList.splice(favList.indexOf(app.metadata.name), 1)
|
||||
: favList.push(app.metadata.name);
|
||||
services.viewPreferences.updatePreferences({appList: {...pref.appList, favoritesAppList: favList}});
|
||||
}}>
|
||||
<i
|
||||
className={'fas fa-star fa-lg'}
|
||||
style={{cursor: 'pointer', marginLeft: '7px', color: favList?.includes(app.metadata.name) ? '#1FBDD0' : 'grey'}}
|
||||
/>
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Project:'>
|
||||
Project:
|
||||
<div className='row'>
|
||||
<div className='columns small-12'>
|
||||
<i className={'icon argo-icon-' + (app.spec.source.chart != null ? 'helm' : 'git')} />
|
||||
<span className='applications-list__title'>{app.metadata.name}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className='columns small-9'>{app.spec.project}</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Labels:'>
|
||||
Labels:
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Project:'>
|
||||
Project:
|
||||
</div>
|
||||
<div className='columns small-9'>{app.spec.project}</div>
|
||||
</div>
|
||||
<div className='columns small-9'>
|
||||
<Tooltip
|
||||
zIndex={4}
|
||||
content={
|
||||
<div>
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Labels:'>
|
||||
Labels:
|
||||
</div>
|
||||
<div className='columns small-9'>
|
||||
<Tooltip
|
||||
zIndex={4}
|
||||
content={
|
||||
<div>
|
||||
{Object.keys(app.metadata.labels || {})
|
||||
.map(label => ({label, value: app.metadata.labels[label]}))
|
||||
.map(item => (
|
||||
<div key={item.label}>
|
||||
{item.label}={item.value}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
}>
|
||||
<span>
|
||||
{Object.keys(app.metadata.labels || {})
|
||||
.map(label => ({label, value: app.metadata.labels[label]}))
|
||||
.map(item => (
|
||||
<div key={item.label}>
|
||||
{item.label}={item.value}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
}>
|
||||
<span>
|
||||
{Object.keys(app.metadata.labels || {})
|
||||
.map(label => `${label}=${app.metadata.labels[label]}`)
|
||||
.join(', ')}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Status:'>
|
||||
Status:
|
||||
</div>
|
||||
<div className='columns small-9' qe-id='applications-tiles-health-status'>
|
||||
<AppUtils.HealthStatusIcon state={app.status.health} /> {app.status.health.status}
|
||||
|
||||
<AppUtils.ComparisonStatusIcon status={app.status.sync.status} /> {app.status.sync.status}
|
||||
|
||||
<OperationState app={app} quiet={true} />
|
||||
</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Repository:'>
|
||||
Repository:
|
||||
</div>
|
||||
<div className='columns small-9'>
|
||||
<Tooltip content={app.spec.source.repoURL} zIndex={4}>
|
||||
<span>{app.spec.source.repoURL}</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Target Revision:'>
|
||||
Target Revision:
|
||||
</div>
|
||||
<div className='columns small-9'>{app.spec.source.targetRevision}</div>
|
||||
</div>
|
||||
{app.spec.source.path && (
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Path:'>
|
||||
Path:
|
||||
.map(label => `${label}=${app.metadata.labels[label]}`)
|
||||
.join(', ')}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className='columns small-9'>{app.spec.source.path}</div>
|
||||
</div>
|
||||
)}
|
||||
{app.spec.source.chart && (
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Chart:'>
|
||||
Chart:
|
||||
<div className='columns small-3' title='Status:'>
|
||||
Status:
|
||||
</div>
|
||||
<div className='columns small-9' qe-id='applications-tiles-health-status'>
|
||||
<AppUtils.HealthStatusIcon state={app.status.health} /> {app.status.health.status}
|
||||
|
||||
<AppUtils.ComparisonStatusIcon status={app.status.sync.status} /> {app.status.sync.status}
|
||||
|
||||
<OperationState app={app} quiet={true} />
|
||||
</div>
|
||||
<div className='columns small-9'>{app.spec.source.chart}</div>
|
||||
</div>
|
||||
)}
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Destination:'>
|
||||
Destination:
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Repository:'>
|
||||
Repository:
|
||||
</div>
|
||||
<div className='columns small-9'>
|
||||
<Tooltip content={app.spec.source.repoURL} zIndex={4}>
|
||||
<span>{app.spec.source.repoURL}</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div className='columns small-9'>
|
||||
<Cluster server={app.spec.destination.server} name={app.spec.destination.name} />
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Target Revision:'>
|
||||
Target Revision:
|
||||
</div>
|
||||
<div className='columns small-9'>{app.spec.source.targetRevision}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Namespace:'>
|
||||
Namespace:
|
||||
{app.spec.source.path && (
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Path:'>
|
||||
Path:
|
||||
</div>
|
||||
<div className='columns small-9'>{app.spec.source.path}</div>
|
||||
</div>
|
||||
)}
|
||||
{app.spec.source.chart && (
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Chart:'>
|
||||
Chart:
|
||||
</div>
|
||||
<div className='columns small-9'>{app.spec.source.chart}</div>
|
||||
</div>
|
||||
)}
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Destination:'>
|
||||
Destination:
|
||||
</div>
|
||||
<div className='columns small-9'>
|
||||
<Cluster server={app.spec.destination.server} name={app.spec.destination.name} />
|
||||
</div>
|
||||
</div>
|
||||
<div className='columns small-9'>{app.spec.destination.namespace}</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='columns applications-list__entry--actions'>
|
||||
<a
|
||||
className='argo-button argo-button--base'
|
||||
qe-id='applications-tiles-button-sync'
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
syncApplication(app.metadata.name);
|
||||
}}>
|
||||
<i className='fa fa-sync' /> Sync
|
||||
</a>
|
||||
|
||||
<a
|
||||
className='argo-button argo-button--base'
|
||||
qe-id='applications-tiles-button-refresh'
|
||||
{...AppUtils.refreshLinkAttrs(app)}
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
refreshApplication(app.metadata.name);
|
||||
}}>
|
||||
<i className={classNames('fa fa-redo', {'status-icon--spin': AppUtils.isAppRefreshing(app)})} />{' '}
|
||||
<span className='show-for-xxlarge'>Refresh</span>
|
||||
</a>
|
||||
|
||||
<a
|
||||
className='argo-button argo-button--base'
|
||||
qe-id='applications-tiles-button-delete'
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
deleteApplication(app.metadata.name);
|
||||
}}>
|
||||
<i className='fa fa-times-circle' /> <span className='show-for-xxlarge'>Delete</span>
|
||||
</a>
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Namespace:'>
|
||||
Namespace:
|
||||
</div>
|
||||
<div className='columns small-9'>{app.spec.destination.namespace}</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='columns applications-list__entry--actions'>
|
||||
<a
|
||||
className='argo-button argo-button--base'
|
||||
qe-id='applications-tiles-button-sync'
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
syncApplication(app.metadata.name);
|
||||
}}>
|
||||
<i className='fa fa-sync' /> Sync
|
||||
</a>
|
||||
|
||||
<a
|
||||
className='argo-button argo-button--base'
|
||||
qe-id='applications-tiles-button-refresh'
|
||||
{...AppUtils.refreshLinkAttrs(app)}
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
refreshApplication(app.metadata.name);
|
||||
}}>
|
||||
<i className={classNames('fa fa-redo', {'status-icon--spin': AppUtils.isAppRefreshing(app)})} />{' '}
|
||||
<span className='show-for-xxlarge'>Refresh</span>
|
||||
</a>
|
||||
|
||||
<a
|
||||
className='argo-button argo-button--base'
|
||||
qe-id='applications-tiles-button-delete'
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
deleteApplication(app.metadata.name);
|
||||
}}>
|
||||
<i className='fa fa-times-circle' /> <span className='show-for-xxlarge'>Delete</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
</DataLoader>
|
||||
)}
|
||||
</Consumer>
|
||||
|
||||
@@ -63,6 +63,7 @@ export class AppsListPreferences {
|
||||
pref.projectsFilter = [];
|
||||
pref.reposFilter = [];
|
||||
pref.syncFilter = [];
|
||||
pref.showFavorites = false;
|
||||
}
|
||||
|
||||
public labelsFilter: string[];
|
||||
@@ -75,6 +76,8 @@ export class AppsListPreferences {
|
||||
public view: AppsListViewType;
|
||||
public hideFilters: boolean;
|
||||
public statusBarView: HealthStatusBarPreferences;
|
||||
public showFavorites: boolean;
|
||||
public favoritesAppList: string[];
|
||||
}
|
||||
|
||||
export interface ViewPreferences {
|
||||
@@ -117,6 +120,8 @@ const DEFAULT_PREFERENCES: ViewPreferences = {
|
||||
syncFilter: new Array<string>(),
|
||||
healthFilter: new Array<string>(),
|
||||
hideFilters: false,
|
||||
showFavorites: false,
|
||||
favoritesAppList: new Array<string>(),
|
||||
statusBarView: {
|
||||
showHealthStatusBar: true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user