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