github.com/argoproj/argo-cd/v2@v2.10.9/ui/src/app/shared/services/view-preferences-service.ts (about) 1 import * as deepMerge from 'deepmerge'; 2 import {BehaviorSubject, Observable} from 'rxjs'; 3 4 import {PodGroupType} from '../../applications/components/application-pod-view/pod-view'; 5 import {UserMessages} from '../models'; 6 7 export type AppsDetailsViewType = 'tree' | 'network' | 'list' | 'pods'; 8 9 export enum AppsDetailsViewKey { 10 Tree = 'tree', 11 Network = 'network', 12 List = 'list', 13 Pods = 'pods' 14 } 15 16 export interface AppDetailsPreferences { 17 resourceFilter: string[]; 18 view: AppsDetailsViewType | string; 19 resourceView: 'manifest' | 'diff' | 'desiredManifest'; 20 inlineDiff: boolean; 21 compactDiff: boolean; 22 hideManagedFields?: boolean; 23 orphanedResources: boolean; 24 podView: PodViewPreferences; 25 darkMode: boolean; 26 followLogs: boolean; 27 hideFilters: boolean; 28 wrapLines: boolean; 29 groupNodes?: boolean; 30 zoom: number; 31 podGroupCount: number; 32 userHelpTipMsgs: UserMessages[]; 33 } 34 35 export interface PodViewPreferences { 36 sortMode: PodGroupType; 37 hideUnschedulable: boolean; 38 } 39 40 export interface HealthStatusBarPreferences { 41 showHealthStatusBar: boolean; 42 } 43 44 export type AppsListViewType = 'tiles' | 'list' | 'summary'; 45 46 export enum AppsListViewKey { 47 List = 'list', 48 Summary = 'summary', 49 Tiles = 'tiles' 50 } 51 52 export class AppsListPreferences { 53 public static countEnabledFilters(pref: AppsListPreferences) { 54 return [pref.clustersFilter, pref.healthFilter, pref.labelsFilter, pref.namespacesFilter, pref.projectsFilter, pref.reposFilter, pref.syncFilter].reduce( 55 (count, filter) => { 56 if (filter && filter.length > 0) { 57 return count + 1; 58 } 59 return count; 60 }, 61 0 62 ); 63 } 64 65 public static clearFilters(pref: AppsListPreferences) { 66 pref.clustersFilter = []; 67 pref.healthFilter = []; 68 pref.labelsFilter = []; 69 pref.namespacesFilter = []; 70 pref.projectsFilter = []; 71 pref.reposFilter = []; 72 pref.syncFilter = []; 73 pref.autoSyncFilter = []; 74 pref.showFavorites = false; 75 } 76 77 public labelsFilter: string[]; 78 public projectsFilter: string[]; 79 public reposFilter: string[]; 80 public syncFilter: string[]; 81 public autoSyncFilter: string[]; 82 public healthFilter: string[]; 83 public namespacesFilter: string[]; 84 public clustersFilter: string[]; 85 public view: AppsListViewType; 86 public hideFilters: boolean; 87 public statusBarView: HealthStatusBarPreferences; 88 public showFavorites: boolean; 89 public favoritesAppList: string[]; 90 } 91 92 export interface ViewPreferences { 93 version: number; 94 appDetails: AppDetailsPreferences; 95 appList: AppsListPreferences; 96 pageSizes: {[key: string]: number}; 97 sortOptions?: {[key: string]: string}; 98 hideBannerContent: string; 99 hideSidebar: boolean; 100 position: string; 101 theme: string; 102 } 103 104 const VIEW_PREFERENCES_KEY = 'view_preferences'; 105 106 const minVer = 5; 107 108 const DEFAULT_PREFERENCES: ViewPreferences = { 109 version: 1, 110 appDetails: { 111 view: 'tree', 112 hideFilters: false, 113 resourceFilter: [], 114 inlineDiff: false, 115 compactDiff: false, 116 hideManagedFields: true, 117 resourceView: 'manifest', 118 orphanedResources: false, 119 podView: { 120 sortMode: 'node', 121 hideUnschedulable: true 122 }, 123 darkMode: false, 124 followLogs: false, 125 wrapLines: false, 126 zoom: 1.0, 127 podGroupCount: 15.0, 128 userHelpTipMsgs: [] 129 }, 130 appList: { 131 view: 'tiles' as AppsListViewType, 132 labelsFilter: new Array<string>(), 133 projectsFilter: new Array<string>(), 134 namespacesFilter: new Array<string>(), 135 clustersFilter: new Array<string>(), 136 reposFilter: new Array<string>(), 137 syncFilter: new Array<string>(), 138 autoSyncFilter: new Array<string>(), 139 healthFilter: new Array<string>(), 140 hideFilters: false, 141 showFavorites: false, 142 favoritesAppList: new Array<string>(), 143 statusBarView: { 144 showHealthStatusBar: true 145 } 146 }, 147 pageSizes: {}, 148 hideBannerContent: '', 149 hideSidebar: false, 150 position: '', 151 theme: 'light' 152 }; 153 154 export class ViewPreferencesService { 155 private preferencesSubj: BehaviorSubject<ViewPreferences>; 156 157 public init() { 158 if (!this.preferencesSubj) { 159 this.preferencesSubj = new BehaviorSubject(this.loadPreferences()); 160 window.addEventListener('storage', () => { 161 this.preferencesSubj.next(this.loadPreferences()); 162 }); 163 } 164 } 165 166 public getPreferences(): Observable<ViewPreferences> { 167 return this.preferencesSubj; 168 } 169 170 public updatePreferences(change: Partial<ViewPreferences>) { 171 const nextPref = Object.assign({}, this.preferencesSubj.getValue(), change, {version: minVer}); 172 window.localStorage.setItem(VIEW_PREFERENCES_KEY, JSON.stringify(nextPref)); 173 this.preferencesSubj.next(nextPref); 174 } 175 176 private loadPreferences(): ViewPreferences { 177 let preferences: ViewPreferences; 178 const preferencesStr = window.localStorage.getItem(VIEW_PREFERENCES_KEY); 179 if (preferencesStr) { 180 try { 181 preferences = JSON.parse(preferencesStr); 182 } catch (e) { 183 preferences = DEFAULT_PREFERENCES; 184 } 185 if (!preferences.version || preferences.version < minVer) { 186 preferences = DEFAULT_PREFERENCES; 187 } 188 } else { 189 preferences = DEFAULT_PREFERENCES; 190 } 191 return deepMerge(DEFAULT_PREFERENCES, preferences); 192 } 193 }