diff --git a/maestro/monitor/monitor.go b/maestro/monitor/monitor.go index c9fa10ccc..5ac8a7ccd 100644 --- a/maestro/monitor/monitor.go +++ b/maestro/monitor/monitor.go @@ -71,7 +71,7 @@ func (svc *monitorService) Start(ctx context.Context, cancelFunc context.CancelF } func (svc *monitorService) getPodLogs(ctx context.Context, pod k8scorev1.Pod) ([]string, error) { - maxTailLines := int64(1) + maxTailLines := int64(10) sinceSeconds := int64(300) podLogOpts := k8scorev1.PodLogOptions{TailLines: &maxTailLines, SinceSeconds: &sinceSeconds} config, err := rest.InClusterConfig() diff --git a/ui/src/app/@theme/styles/_overrides.scss b/ui/src/app/@theme/styles/_overrides.scss index 1c0f54936..c30ad1293 100644 --- a/ui/src/app/@theme/styles/_overrides.scss +++ b/ui/src/app/@theme/styles/_overrides.scss @@ -206,13 +206,13 @@ &online, &healthy { color: #6fcf97; } - &stale, &none { + &stale { color: #f2994a; } &error, &failure { color: #df316f; } - &offline { + &offline, &none { color: #969fb9; } } @@ -264,4 +264,87 @@ text-transform: none !important; width: 110px; background-color: #df316f !important; + opacity: 0; + animation: appear 0.3s forwards; +} + +@keyframes appear { + 0% { + opacity: 0; + transform: translateY(-10px); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} +p { + font-family: 'Montserrat' !important; +} +button { + font-family: 'Montserrat' !important; +} +label { + font-family: 'Montserrat' !important; +} +.input-label { + color: #fff !important; + font-size: 14px !important; + font-weight: 500 !important; +} +input { + background-color: transparent !important; +} +.next-button { + border-radius: 16px !important; + background: #3089FC !important; + padding: 8px 24px !important; + color: #fff !important; + border: none !important; + outline: none !important; + font-size: 14px !important; + font-weight: 600 !important; + transition: background-color 0.3s ease !important; +} +.next-button:hover { + background-color: #509afc!important; +} +.next-button:disabled { + background: #2b3148 !important; +} +.cancel-back-button { + border-radius: 16px !important;; + padding: 8px 24px !important; + background-color: transparent !important; + color: #3089FC !important; + border: none !important; + outline: none !important; + font-size: 14px !important; + font-weight: 600 !important; + transition: background-color 0.3s ease !important; + margin-right: 0 !important; +} +.cancel-back-button:hover { + background-color: rgba(255, 255, 255, 0.05) !important; +} +.loading-spinner { + position: absolute; + top: 45%; + left: 50%; + transform: translate(-50%, -50%); + width: 40px; + height: 40px; + border-radius: 50%; + border: 5px solid #404a70; + border-top: 5px solid #21316e; + animation: spin 1s linear infinite; +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } } diff --git a/ui/src/app/app.module.ts b/ui/src/app/app.module.ts index 3808c49d6..abf751850 100644 --- a/ui/src/app/app.module.ts +++ b/ui/src/app/app.module.ts @@ -24,8 +24,10 @@ import { NbInputModule, NbLayoutModule, NbMenuModule, + NbSelectModule, NbSidebarModule, NbToastrModule, + NbTooltipModule, NbWindowModule, } from '@nebular/theme'; @@ -50,7 +52,8 @@ import { CodeEditorService } from 'app/common/services/code.editor.service'; HttpClientModule, AppRoutingModule, - + NbTooltipModule, + NbSelectModule, ThemeModule.forRoot(), NbSidebarModule.forRoot(), NbMenuModule.forRoot(), diff --git a/ui/src/app/auth/auth.token.interceptor.service.ts b/ui/src/app/auth/auth.token.interceptor.service.ts index b580b8c0f..b61c8e59e 100644 --- a/ui/src/app/auth/auth.token.interceptor.service.ts +++ b/ui/src/app/auth/auth.token.interceptor.service.ts @@ -65,7 +65,8 @@ export class TokenInterceptor implements HttpInterceptor { err instanceof HttpErrorResponse && err.status === 401 && !request.url.startsWith(environment.httpAdapterUrl) && - !request.url.startsWith(environment.readerUrl) + !request.url.startsWith(environment.readerUrl) && + (!request.url.endsWith('/password') && request.method !== 'PATCH') ) { localStorage.removeItem('auth_app_token'); this.router.navigateByUrl('/auth/login'); diff --git a/ui/src/app/common/services/code.editor.service.ts b/ui/src/app/common/services/code.editor.service.ts index 60357b5c7..07a00df63 100644 --- a/ui/src/app/common/services/code.editor.service.ts +++ b/ui/src/app/common/services/code.editor.service.ts @@ -30,7 +30,6 @@ export class CodeEditorService { checkEmpty (object) { for (let key in object) { - console.log(object[key]); if (object[key] === "" || typeof object[key] === "undefined" || object[key] === null) { return true; } diff --git a/ui/src/app/common/services/filter.service.ts b/ui/src/app/common/services/filter.service.ts index 329f8ee18..8d1d46701 100644 --- a/ui/src/app/common/services/filter.service.ts +++ b/ui/src/app/common/services/filter.service.ts @@ -74,6 +74,10 @@ export class FilterService { } } + removeFilterByParam(param: string) { + this.removeFilter(this._filters.findIndex((filter) => filter.param === param && filter.name === 'Name' && filter)); + } + // make a decorator out of this? createFilteredList() { return ( diff --git a/ui/src/app/common/services/orb.service.ts b/ui/src/app/common/services/orb.service.ts index bb3754668..acf5f0aa8 100644 --- a/ui/src/app/common/services/orb.service.ts +++ b/ui/src/app/common/services/orb.service.ts @@ -34,12 +34,14 @@ export const PollControls = { RESUME: true, }; +export const pollIntervalKey = 'pollinterval'; + @Injectable({ providedIn: 'root', }) export class OrbService implements OnDestroy { // interval for timer - pollInterval = 1000; + pollInterval; pollController$: BehaviorSubject; @@ -51,11 +53,15 @@ export class OrbService implements OnDestroy { // next to force refresh private forceRefresh: Subject; + isPollingPaused = false; + pausePolling() { + this.isPollingPaused = true; this.pollController$.next(PollControls.PAUSE); } startPolling() { + this.isPollingPaused = false; this.pollController$.next(PollControls.RESUME); } @@ -68,7 +74,7 @@ export class OrbService implements OnDestroy { this.pollController$.pipe( switchMap((control) => { if (control === PollControls.RESUME) - return defer(() => timer(1, this.pollInterval)); + return defer(() => timer(1, this.pollInterval)); return EMPTY; }), ), @@ -100,8 +106,23 @@ export class OrbService implements OnDestroy { this.lastPollUpdate$ = new Subject(); this.forceRefresh = new Subject(); this.killPolling = new Subject(); + this.pollInterval = this.getPollInterval(); + + this.pollController$ = new BehaviorSubject(PollControls.RESUME); + } + getPollInterval() { + + let pollInterval: number; - this.pollController$ = new BehaviorSubject(PollControls.PAUSE); + if (localStorage.getItem(pollIntervalKey)) { + pollInterval = Number(localStorage.getItem(pollIntervalKey)); + } + else { + pollInterval = 60000; + localStorage.setItem(pollIntervalKey, pollInterval.toString()); + } + + return pollInterval; } private mapTags = (list: AgentGroup[] & Sink[]) => { @@ -155,95 +176,103 @@ export class OrbService implements OnDestroy { } getAgentFullView(id: string) { - return this.agent.getAgentById(id).pipe( - mergeMap((agent) => { - const policy_state = agent?.last_hb_data?.policy_state; - const datasetIds = - !!policy_state && - Object.values(policy_state) - .map((state) => state['datasets']) - .reduce((acc, val) => acc.concat(val), []) - .filter(this.onlyUnique); - return datasetIds.length > 0 - ? forkJoin( - datasetIds.map((_id) => this.dataset.getDatasetById(_id)), - ).pipe( - map((datasets) => - datasets.reduce((acc, val: Dataset) => { - acc[val.id] = val; - return acc; - }, {}), - ), - map((datasets) => ({ agent, datasets })), - ) - : of({ agent, datasets: {} }); - }), - mergeMap(({ agent, datasets }) => { - const group_state = agent?.last_hb_data?.group_state; - const groupIds = !!group_state && Object.keys(group_state); - const groups$ = - groupIds.length > 0 - ? forkJoin(groupIds.map((_id) => this.group.getAgentGroupById(_id))) - : of([]); - return groups$.pipe(map((groups) => ({ agent, groups, datasets }))); - }), + return this.observe( + this.agent.getAgentById(id).pipe( + mergeMap((agent) => { + const policy_state = agent?.last_hb_data?.policy_state; + const datasetIds = + !!policy_state && + Object.values(policy_state) + .map((state) => state['datasets']) + .reduce((acc, val) => acc.concat(val), []) + .filter(this.onlyUnique); + return datasetIds.length > 0 + ? forkJoin( + datasetIds.map((_id) => this.dataset.getDatasetById(_id)), + ).pipe( + map((datasets) => + datasets.reduce((acc, val: Dataset) => { + acc[val.id] = val; + return acc; + }, {}), + ), + map((datasets) => ({ agent, datasets })), + ) + : of({ agent, datasets: {} }); + }), + mergeMap(({ agent, datasets }) => { + const group_state = agent?.last_hb_data?.group_state; + const groupIds = !!group_state && Object.keys(group_state); + const groups$ = + groupIds.length > 0 + ? forkJoin(groupIds.map((_id) => this.group.getAgentGroupById(_id))) + : of([]); + return groups$.pipe(map((groups) => ({ agent, groups, datasets }))); + }), + ) ); } getPolicyFullView(id: string) { // retrieve policy - return this.policy.getAgentPolicyById(id).pipe( - mergeMap((policy) => - // need a way to get a dataset linked to a policy without having to filter it out - this.dataset.getAllDatasets().pipe( - map((_dataset) => - _dataset.filter((dataset) => policy.id === dataset.agent_policy_id), + return this.observe( + this.policy.getAgentPolicyById(id).pipe( + mergeMap((policy) => + // need a way to get a dataset linked to a policy without having to filter it out + this.dataset.getAllDatasets().pipe( + map((_dataset) => + _dataset.filter((dataset) => policy.id === dataset.agent_policy_id), + ), + // from the filtered dataset list, query all agent groups associated with the list + mergeMap((datasets: Dataset[]) => { + const combinedDatasets = datasets + .map((dataset) => dataset.agent_group_id) + .filter(this.onlyUnique) + .filter((val) => !!val && val !== '') + .map((groupId) => this.group.getAgentGroupById(groupId)); + return combinedDatasets.length > 0 + ? forkJoin(combinedDatasets).pipe( + map((groups) => ({ datasets, groups, policy })), + ) + : of({ datasets, groups: [], policy }); + }), + // same for sinks + mergeMap(({ datasets, groups }) => { + const combinedSinks = datasets + .map((dataset) => dataset?.sink_ids) + .reduce((acc, val) => acc.concat(val), []) + .filter(this.onlyUnique) + .filter((val) => !!val && val !== '') + .map((sinkId) => this.sink.getSinkById(sinkId)); + return combinedSinks.length > 0 + ? forkJoin(combinedSinks).pipe( + map((sinks) => ({ datasets, sinks, policy, groups })), + ) + : of({ datasets, sinks: [], policy, groups }); + }), ), - // from the filtered dataset list, query all agent groups associated with the list - mergeMap((datasets: Dataset[]) => { - const combinedDatasets = datasets - .map((dataset) => dataset.agent_group_id) - .filter(this.onlyUnique) - .filter((val) => !!val && val !== '') - .map((groupId) => this.group.getAgentGroupById(groupId)); - return combinedDatasets.length > 0 - ? forkJoin(combinedDatasets).pipe( - map((groups) => ({ datasets, groups, policy })), - ) - : of({ datasets, groups: [], policy }); - }), - // same for sinks - mergeMap(({ datasets, groups }) => { - const combinedSinks = datasets - .map((dataset) => dataset?.sink_ids) - .reduce((acc, val) => acc.concat(val), []) - .filter(this.onlyUnique) - .filter((val) => !!val && val !== '') - .map((sinkId) => this.sink.getSinkById(sinkId)); - return combinedSinks.length > 0 - ? forkJoin(combinedSinks).pipe( - map((sinks) => ({ datasets, sinks, policy, groups })), - ) - : of({ datasets, sinks: [], policy, groups }); - }), ), - ), - // from here on I can map to any shape I like - // dataset list uses the info below - map(({ datasets, sinks, policy, groups }) => ({ - datasets: datasets.map((dataset) => ({ - ...dataset, - agent_group: groups.find( - (group) => group.id === dataset.agent_group_id, - ), - agent_policy: policy, - sinks: sinks.filter((sink) => dataset.sink_ids.includes(sink.id)), + // from here on I can map to any shape I like + // dataset list uses the info below + map(({ datasets, sinks, policy, groups }) => ({ + datasets: datasets.map((dataset) => ({ + ...dataset, + agent_group: groups.find( + (group) => group.id === dataset.agent_group_id, + ), + agent_policy: policy, + sinks: sinks.filter((sink) => dataset.sink_ids.includes(sink.id)), + })), + sinks, + policy: { ...policy, groups, datasets }, + groups, })), - sinks, - policy: { ...policy, groups, datasets }, - groups, - })), - ); + ) + ); + } + + getSinkView(id: string) { + return this.observe(this.sink.getSinkById(id)); } getDatasetListView() { diff --git a/ui/src/app/pages/dashboard/dashboard.component.scss b/ui/src/app/pages/dashboard/dashboard.component.scss index f91f42262..af7247aa2 100644 --- a/ui/src/app/pages/dashboard/dashboard.component.scss +++ b/ui/src/app/pages/dashboard/dashboard.component.scss @@ -96,16 +96,16 @@ h6 { line-height: 24px !important; & > a { - white-space: nowrap; - padding: 0 0.3rem; - background-color: #3089fc; + white-space: nowrap !important; + padding: 0 0.3rem !important; + background-color: #3089fc !important; font-weight: 700 !important; text-decoration: none !important; - text-underline: none; + text-underline: none !important; color: #ffffff !important; border-radius: 10px; - link: #ffffff; - fill: #3089fc; + link: #ffffff !important; + fill: #3089fc !important; } } } diff --git a/ui/src/app/pages/datasets/dataset-from/dataset-from.component.html b/ui/src/app/pages/datasets/dataset-from/dataset-from.component.html index a2a370d44..952635bfd 100644 --- a/ui/src/app/pages/datasets/dataset-from/dataset-from.component.html +++ b/ui/src/app/pages/datasets/dataset-from/dataset-from.component.html @@ -18,14 +18,14 @@
- + *
- + *
@@ -69,7 +69,7 @@
- + *
- + *
diff --git a/ui/src/app/pages/datasets/delete/dataset.delete.component.scss b/ui/src/app/pages/datasets/delete/dataset.delete.component.scss index c45601370..ecb4178c6 100644 --- a/ui/src/app/pages/datasets/delete/dataset.delete.component.scss +++ b/ui/src/app/pages/datasets/delete/dataset.delete.component.scss @@ -1,43 +1,43 @@ nb-card { - max-width: 38rem; + max-width: 38rem !important; nb-card-header { - background: #232940; - color: #969fb9; + background: #232940 !important; + color: #969fb9 !important; } nb-card-body { - margin: 2rem 3rem; - padding: 0; + margin: 2rem 3rem !important; + padding: 0 !important; p { - color: #969fb9; + color: #969fb9 !important; } .ns1-red { - color: #df316f; + color: #df316f !important; } } nb-card-footer { - text-align: center; - padding: 1.5rem; + text-align: center !important; + padding: 1.5rem !important; } } // ORB ::ng-deep { .orb-close-dialog { - background-color: #23294000; - border-radius: 4px; - display: contents; - float: right; + background-color: #23294000 !important; + border-radius: 4px !important; + display: contents !important; + float: right !important; > span { - float: right; - font-size: 1.5rem; - color: #3089fc; - font-weight: 900; + float: right !important; + font-size: 1.5rem !important; + color: #3089fc !important; + font-weight: 900 !important; } } diff --git a/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.html b/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.html index a27a7707e..e3a851290 100644 --- a/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.html +++ b/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.html @@ -26,7 +26,7 @@

{{ isEdit ? 'Edit Agent Policy' : 'Create Agent Policy'}}

Agent Policy Details -

Provide a name, a description summary and a supported backend for the Agent Policy

+

Provide a name, a description and a supported backend for the Policy

@@ -34,9 +34,8 @@

{{ isEdit ? 'Edit Agent Policy' : 'Create Agent Policy'}}

- * + class="input-label" + for="name">Policy Name*
{{ isEdit ? 'Edit Agent Policy' : 'Create Agent Policy'}} fullWidth="true" [status]="detailsFG?.controls.name.dirty ? (!detailsFG.controls.name.valid ? 'danger' : 'success') : 'basic'" id="name" - nbInput/> + nbInput + placeholder="Policy Name"/> -

+

Name is required! -

-

+

+
Name must start with a letter or "_" and contain only letters, numbers, "-" or "_" -

-

+

+
Name must be less than {{detailsFG.controls.name.errors?.maxlength.requiredLength}} characters -

+
{{ isEdit ? 'Edit Agent Policy' : 'Create Agent Policy'}} formControlName="description" fullWidth="true" id="description" - nbInput/> + nbInput + placeholder="Policy Description"/>

Description must be less than {{detailsFG.controls.description.errors?.maxlength.requiredLength}} characters @@ -82,7 +83,7 @@

{{ isEdit ? 'Edit Agent Policy' : 'Create Agent Policy'}}

{{ isEdit ? 'Edit Agent Policy' : 'Create Agent Policy'}}

- + +
- +
@@ -140,85 +142,150 @@

{{ isEdit ? 'Edit Agent Policy' : 'Create Agent Policy'}}

Provide a valid YAML or JSON configuration

-
- - Create Policy through {{isJsonMode ? "JSON editor" : "YAML editor"}} - +
+ +
-
-
-

Paste or Upload your JSON configuration

- - -
-
- - -
-
-
-
-

Paste or Upload your YAML configuration

- - -
-
+
+

Paste or Upload your {{isJsonMode ? 'Json' : 'Yaml'}} configuration

+ + +
+
+
+ + + + + -
+ +
+ +
+ + + +
+ Review & Confirm +
+
+
+
+
+ +

{{detailsFG.controls.name.value}}

+
+
+
+
+
+
+ +

{{detailsFG.controls.description.value}}

+

No description provided

+
+
+
+
+
+
+ +

{{detailsFG.controls.backend.value}}

+
+
+
+
+
+ + +
+
+
+ + +
+ +
diff --git a/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.scss b/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.scss index 0af6c504f..959ba6122 100644 --- a/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.scss +++ b/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.scss @@ -22,11 +22,49 @@ nb-card-footer { mat-chip nb-icon { font-size: 1rem; } +label { + color: #969FB9; +} ngx-tag-control, ngx-tag-display { margin-top: 20px; } +.review-label { + font-family: 'Montserrat'; + font-size: 13px; + font-weight: 400 !important; + margin: 0; + color: #969fb9 !important; +} +.language-button { + border-radius: 16px; + + padding: 8px 24px; + color: #fff; + border: none; + outline: none; + font-size: 14px; + font-weight: 600; + transition: background-color 0.2s ease; + margin: 8px 4px 8px 4px; + width: 90px; + +} +.div-language-button { + background-color: #24293E; + width: fit-content; + padding: 0 4px 0 4px; + border-radius: 25px; + margin-bottom: 20px; +} +.true { + background: #3089FC; +} +.false { + background-color: #181C2F; +} + ::ng-deep { .header { align-items: flex-end !important; @@ -55,22 +93,39 @@ ngx-tag-control, ngx-tag-display { .step { flex-direction: row-reverse !important; align-items: start !important; + + &-label { + p { + font-family: 'Montserrat', sans-serif; + font-weight: 400; + color: #969fb9; + } + strong { + font-family: 'Montserrat', sans-serif; + font-weight: 700; + color: #969fb9; + } + } } .step.selected { - -webkit-text-stroke-color: rgba(255, 255, 255, 0.15); - -webkit-text-stroke-width: 1px; - text-shadow: 0 0 20px #ffffff8f; + p { + color: #fff; + } + strong { + color: #fff; + } & > .label-index { - box-shadow: 0 0 12px 1px #df316f; - background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTEiIGhlaWdodD0iOCIgdmlld0JveD0iMCAwIDExIDgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0wLjUgMy45OTY1MUw0LjE4NjgyIDcuNjgzMzNMMTAuODIzMSAxLjA0NzA2TDkuNzgzNDEgMEw0LjE4NjgyIDUuNTk2NTlMMS41Mzk2OCAyLjk1NjgzTDAuNSAzLjk5NjUxWiIgZmlsbD0iI2ZmZiIvPgo8L3N2Zz4K'); - background-color: #df316f; + box-shadow: 0 0 12px 1px #df316f; + background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTEiIGhlaWdodD0iOCIgdmlld0JveD0iMCAwIDExIDgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0wLjUgMy45OTY1MUw0LjE4NjgyIDcuNjgzMzNMMTAuODIzMSAxLjA0NzA2TDkuNzgzNDEgMEw0LjE4NjgyIDUuNTk2NTlMMS41Mzk2OCAyLjk1NjgzTDAuNSAzLjk5NjUxWiIgZmlsbD0iI2ZmZiIvPgo8L3N2Zz4K'); + background-color: #df316f; } } + .step-content { - width: 500px !important; + width: 500px; } .connector { @@ -79,8 +134,8 @@ ngx-tag-control, ngx-tag-display { &::after { content: ''; - height: 40px; - transform: translateY(-40px); + height: 70px; + transform: translateY(-70px); width: 1px; border-left: solid 1px #969fb9b3; position: absolute; @@ -90,7 +145,6 @@ ngx-tag-control, ngx-tag-display { .connector.connector-past { transition: background 0.5s 0s ease-in-out; - &::after { transition: border 0.5s 0s ease-in-out; border-left: solid 1px #df316f; @@ -106,6 +160,9 @@ ngx-tag-control, ngx-tag-display { .step-label { width: 214px; text-align: end; + p { + font-size: 0.9375rem; + } } ::ng-deep .orb-breadcrumb { @@ -168,18 +225,20 @@ ngx-tag-control, ngx-tag-display { } .code-editor { - height: calc(100%); + height: calc(90%); width: calc(100%); } .code-editor-wrapper { - min-height: 350px; + min-height: 300px; min-width: 200px; - height: calc(58vh); + height: calc(50vh); width: calc(100%); - display: block; } - +.stepper { + margin: 0 !important; + padding-top: 0 !important; +} .handlers-list { display: flex; flex-direction: column; diff --git a/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.ts b/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.ts index 025583845..bf3cb9219 100644 --- a/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.ts +++ b/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.ts @@ -45,6 +45,10 @@ export class AgentPolicyAddComponent { agentPolicyID: string; + reviewPolicyConfig: boolean; + + editorVisible = true; + @ViewChild('editorComponentYaml') editorYaml; @@ -143,6 +147,7 @@ kind: collection`; private _formBuilder: FormBuilder, private editor: CodeEditorService, ) { + this.reviewPolicyConfig = false; this.isRequesting = false; this.agentPolicyID = this.route.snapshot.paramMap.get('id'); this.agentPolicy = this.newAgent(); @@ -339,4 +344,8 @@ kind: collection`; return this.editor.isYaml(this.codeyaml); } } + refreshEditor() { + this.editorVisible = false; setTimeout(() => { this.editorVisible = true; }, 0); + } + } diff --git a/ui/src/app/pages/datasets/policies.agent/delete/agent.policy.delete.component.scss b/ui/src/app/pages/datasets/policies.agent/delete/agent.policy.delete.component.scss index 8ac634efb..458a0d644 100644 --- a/ui/src/app/pages/datasets/policies.agent/delete/agent.policy.delete.component.scss +++ b/ui/src/app/pages/datasets/policies.agent/delete/agent.policy.delete.component.scss @@ -41,7 +41,7 @@ nb-card { } } - .orb-sink-delete-warning-button:not(.btn-disabled) { + .orb-delete-warning-button:not(.btn-disabled) { background-color: #df316f !important; color: #ffffff !important; } diff --git a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html index b3307d5cd..aa459edda 100644 --- a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html +++ b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html @@ -63,9 +63,17 @@

All Policies

(click)="onOpenView(row)" class="view-policy-button" nbTooltip="{{ value }}" + *ngIf="value" > {{ value }} + -
+
Policy View
-
-
- - - Last Update: {{ lastUpdate | date: 'HH:mm:ss a' }} - -
- - - - -
-
+
+ + +
+ + + +
+
+
+
+
+ -
diff --git a/ui/src/app/pages/datasets/policies.agent/view/agent.policy.view.component.scss b/ui/src/app/pages/datasets/policies.agent/view/agent.policy.view.component.scss index 0d9922742..19ed35e11 100644 --- a/ui/src/app/pages/datasets/policies.agent/view/agent.policy.view.component.scss +++ b/ui/src/app/pages/datasets/policies.agent/view/agent.policy.view.component.scss @@ -235,7 +235,19 @@ button { color: #969fb9; font-size: 14px; } +header { + display: flex; + justify-content: space-between; + align-items: center; +} + +.left-content { + flex: 1; + margin-left: 0.9rem; +} + .right-content { display: flex; - justify-content: flex-end; + align-items: center; } + diff --git a/ui/src/app/pages/datasets/policies.agent/view/agent.policy.view.component.ts b/ui/src/app/pages/datasets/policies.agent/view/agent.policy.view.component.ts index a6d9de9e0..04fffa9ef 100644 --- a/ui/src/app/pages/datasets/policies.agent/view/agent.policy.view.component.ts +++ b/ui/src/app/pages/datasets/policies.agent/view/agent.policy.view.component.ts @@ -25,18 +25,18 @@ import { STRINGS } from 'assets/text/strings'; import { Subscription } from 'rxjs'; import yaml from 'js-yaml'; import { AgentGroup } from 'app/common/interfaces/orb/agent.group.interface'; -import { filter } from 'rxjs/operators'; import { PolicyDuplicateComponent } from '../duplicate/agent.policy.duplicate.confirmation'; import { NbDialogService } from '@nebular/theme'; import { updateMenuItems } from 'app/pages/pages-menu'; import { AgentPolicyDeleteComponent } from '../delete/agent.policy.delete.component'; +import { error } from 'console'; @Component({ selector: 'ngx-agent-view', templateUrl: './agent.policy.view.component.html', styleUrls: ['./agent.policy.view.component.scss'], }) -export class AgentPolicyViewComponent implements OnInit, OnDestroy, OnChanges { +export class AgentPolicyViewComponent implements OnInit, OnDestroy { strings = STRINGS.agents; isLoading: boolean; @@ -94,9 +94,6 @@ export class AgentPolicyViewComponent implements OnInit, OnDestroy, OnChanges { this.lastUpdate = new Date(); } - ngOnChanges(): void { - this.fetchData(); - } isEditMode() { return Object.values(this.editMode).reduce( @@ -166,13 +163,18 @@ export class AgentPolicyViewComponent implements OnInit, OnDestroy, OnChanges { backend, } as AgentPolicy; - this.policiesService.editAgentPolicy(payload).subscribe((resp) => { + this.policiesService.editAgentPolicy(payload).subscribe( + (resp) => { this.notifications.success('Agent Policy updated successfully', ''); this.discard(); this.policy = resp; - this.fetchData(); + this.orb.refreshNow(); this.isRequesting = false; - }); + }, + (error) => { + this.isRequesting = false; + } + ); } catch (err) { this.notifications.error( @@ -224,6 +226,8 @@ export class AgentPolicyViewComponent implements OnInit, OnDestroy, OnChanges { ngOnDestroy() { this.policySubscription?.unsubscribe(); + this.orb.isPollingPaused ? this.orb.startPolling() : null; + this.orb.killPolling.next(); } openDeleteModal() { const { name: name, id } = this.policy as AgentPolicy; diff --git a/ui/src/app/pages/fleet/agents/add/agent.add.component.html b/ui/src/app/pages/fleet/agents/add/agent.add.component.html index c8bdea7fe..e6d920d42 100644 --- a/ui/src/app/pages/fleet/agents/add/agent.add.component.html +++ b/ui/src/app/pages/fleet/agents/add/agent.add.component.html @@ -25,8 +25,7 @@

{{isEdit ? 'Edit Agent' : 'New Agent'}}

- - * +
{{isEdit ? 'Edit Agent' : 'New Agent'}} formControlName="name" fullWidth="true" [status]="firstFormGroup.controls?.name.dirty ? (!firstFormGroup.controls.name.valid ? 'danger' : 'success') : 'basic'" - nbInput/> + nbInput + placeholder="Agent Name"/> -

+

Name is required! -

-

+

+
Name must start with a letter or "_" and contain only letters, numbers, "-" or "_" -

-

+

+
Name must be less than {{firstFormGroup.controls.name.errors?.maxlength.requiredLength}} characters -

+

- +
@@ -89,32 +87,32 @@

{{isEdit ? 'Edit Agent' : 'New Agent'}}


- - + +
{{isEdit ? 'Edit Agent' : 'New Agent'}}
- +

{{firstFormGroup.controls.name.value}}

@@ -135,40 +133,40 @@

{{isEdit ? 'Edit Agent' : 'New Agent'}}


- +

- - +
diff --git a/ui/src/app/pages/fleet/agents/add/agent.add.component.scss b/ui/src/app/pages/fleet/agents/add/agent.add.component.scss index d708b3e00..e6bdcc01c 100644 --- a/ui/src/app/pages/fleet/agents/add/agent.add.component.scss +++ b/ui/src/app/pages/fleet/agents/add/agent.add.component.scss @@ -107,6 +107,14 @@ nb-card-footer { } } +.review-label { + font-family: 'Montserrat'; + font-size: 13px; + font-weight: 400 !important; + margin: 0; + color: #969fb9 !important; +} + .required { color: #df316f; padding-left: 2px; diff --git a/ui/src/app/pages/fleet/agents/key/agent.key.component.html b/ui/src/app/pages/fleet/agents/key/agent.key.component.html index 406545aff..966c4249f 100644 --- a/ui/src/app/pages/fleet/agents/key/agent.key.component.html +++ b/ui/src/app/pages/fleet/agents/key/agent.key.component.html @@ -18,7 +18,7 @@ Agent Key -
+        
           
-          {{ agent?.key }}
+          {{ agent?.key }}
         

See here + target="_blank">Click here   for more advanced options.

@@ -61,7 +61,7 @@ {{ defaultCommandShow }} @@ -82,6 +82,9 @@ pack="eva"> + +
@@ -98,8 +101,15 @@
             {{ fileConfigCommandShow }}
           
         
- + +

+ Click here + +   to learn more about how create and apply configuration files. +

diff --git a/ui/src/app/pages/fleet/agents/key/agent.key.component.scss b/ui/src/app/pages/fleet/agents/key/agent.key.component.scss index c11ef7c7a..c87226b2e 100644 --- a/ui/src/app/pages/fleet/agents/key/agent.key.component.scss +++ b/ui/src/app/pages/fleet/agents/key/agent.key.component.scss @@ -12,6 +12,9 @@ nb-card { button { float: right; } + nb-icon { + float: right ; + } } nb-card-body { @@ -21,7 +24,7 @@ nb-card { padding: 0; p { - color: #969fb9; + color: #fff; } .ns1-red { @@ -35,6 +38,7 @@ nb-card { align-content: space-between; align-items: flex-start; justify-content: space-between; + margin: 0; background: transparent; padding: 0.75rem; @@ -55,6 +59,7 @@ nb-card { code { color: #ffffff; line-height: 2.5 !important; + font-size: 16px !important; } } } @@ -86,3 +91,13 @@ nb-card { color: #df316f !important; } } +a { + white-space: nowrap !important; + padding: 0 0.3rem !important; + background-color: #3089fc !important; + font-weight: 700 !important; + text-decoration: none !important; + color: #ffffff !important; + border-radius: 10px; + fill: #3089fc !important; +} diff --git a/ui/src/app/pages/fleet/agents/list/agent.list.component.scss b/ui/src/app/pages/fleet/agents/list/agent.list.component.scss index b3d73df0f..0612f71ef 100644 --- a/ui/src/app/pages/fleet/agents/list/agent.list.component.scss +++ b/ui/src/app/pages/fleet/agents/list/agent.list.component.scss @@ -187,6 +187,8 @@ input[type=checkbox] { font-weight: 600; text-transform: none !important; width: 160px; + opacity: 0; + animation: appear 0.3s forwards; &.btn-disabled { background: #2b3148; diff --git a/ui/src/app/pages/fleet/agents/list/agent.list.component.ts b/ui/src/app/pages/fleet/agents/list/agent.list.component.ts index a7ea3b768..702b66eaf 100644 --- a/ui/src/app/pages/fleet/agents/list/agent.list.component.ts +++ b/ui/src/app/pages/fleet/agents/list/agent.list.component.ts @@ -192,7 +192,6 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe } ngAfterViewInit() { - this.orb.refreshNow(); this.columns = [ { name: '', diff --git a/ui/src/app/pages/fleet/agents/match/agent.match.component.html b/ui/src/app/pages/fleet/agents/match/agent.match.component.html index 9dbd339fa..7e026295f 100644 --- a/ui/src/app/pages/fleet/agents/match/agent.match.component.html +++ b/ui/src/app/pages/fleet/agents/match/agent.match.component.html @@ -50,16 +50,25 @@ -
- - - {{tag | tagchip}} - - -
+ + + {{ tag.key }}:  + {{ tag.value }} + + + No tag were created + +
{ const {policy_state} = agent; - const policy_agg_info = !!policy_state && policy_state[this.policy.id].state || AgentPolicyStates.failedToApply; + const policy_agg_info = !!policy_state && policy_state[this.policy.id]?.state || AgentPolicyStates.failedToApply; return {...agent, policy_agg_info }; }) } else { diff --git a/ui/src/app/pages/fleet/agents/view/agent.view.component.html b/ui/src/app/pages/fleet/agents/view/agent.view.component.html index 1f4b94801..041f6fb04 100644 --- a/ui/src/app/pages/fleet/agents/view/agent.view.component.html +++ b/ui/src/app/pages/fleet/agents/view/agent.view.component.html @@ -5,15 +5,9 @@

Agent View

- - - - Last Update: {{ lastUpdate | date: 'HH:mm:ss a' }} - +
-
+
+
+
+
+
- +
diff --git a/ui/src/app/pages/fleet/agents/view/agent.view.component.ts b/ui/src/app/pages/fleet/agents/view/agent.view.component.ts index 647e561f6..ca6091fa6 100644 --- a/ui/src/app/pages/fleet/agents/view/agent.view.component.ts +++ b/ui/src/app/pages/fleet/agents/view/agent.view.component.ts @@ -89,17 +89,10 @@ export class AgentViewComponent implements OnInit, OnDestroy { ngOnDestroy() { this.agentSubscription?.unsubscribe(); - } - refreshAgent() { - this.isLoading = true; - this.retrieveAgent(); + this.orb.isPollingPaused ? this.orb.startPolling() : null; + this.orb.killPolling.next(); } - onRefreshRequests(value: boolean) { - if (value) { - this.refreshAgent(); - } - } openDeleteModal() { const { name, id } = this.agent; this.dialogService diff --git a/ui/src/app/pages/fleet/groups/add/agent.group.add.component.html b/ui/src/app/pages/fleet/groups/add/agent.group.add.component.html index b5f3cb496..b1fca8438 100644 --- a/ui/src/app/pages/fleet/groups/add/agent.group.add.component.html +++ b/ui/src/app/pages/fleet/groups/add/agent.group.add.component.html @@ -26,8 +26,7 @@

{{strings[isEdit ? 'edit' : 'add']['header']}}

- - * +
{{strings[isEdit ? 'edit' : 'add']['header']}} formControlName="name" [status]="firstFormGroup?.controls.name.dirty ? (!firstFormGroup.controls.name.valid ? 'danger' : 'success') : 'basic'" fullWidth="true" - nbInput/> + nbInput + placeholder="Agent Group Name"/>
-

+

Name is required! -

-

+

+
Name must start with a letter or "_" and contain only letters, numbers, "-" or "_" -

-

+

+
Name must be less than {{firstFormGroup.controls.name.errors?.maxlength.requiredLength}} characters -

+

- +
+ nbInput + placeholder="Agent Group Description"/>

Description must be less than {{firstFormGroup.controls.description.errors?.maxlength.requiredLength}} characters @@ -68,27 +69,27 @@

{{strings[isEdit ? 'edit' : 'add']['header']}}


+ -
@@ -104,21 +105,20 @@

{{strings[isEdit ? 'edit' : 'add']['header']}}

(tagsChange)="updateMatches()" [(tags)]="selectedTags">
-
-
-

- {{strings.match.matchAny}} {{tagMatch.total}} {{strings.match.agents}} - .  -

-

- {{strings.match.matchNone}} -

-
+
+

+ {{strings.match.matchAny}} {{tagMatch.total}} +  {{strings.match.agents}}  + +

+

+ {{strings.match.matchNone}} +

{{strings[isEdit ? 'edit' : 'add']['header']}}
@@ -166,25 +166,26 @@

{{strings[isEdit ? 'edit' : 'add']['header']}}

- +

{{firstFormGroup.controls.name.value}}


- -

{{firstFormGroup.controls.description.value}}

+ +

{{firstFormGroup.controls.description.value}}

+

No description added


+
@@ -192,14 +193,15 @@

{{strings[isEdit ? 'edit' : 'add']['header']}}

-

- {{strings.match.matchAny}} {{tagMatch.total}} {{strings.match.agents}} - .  +

+ {{strings.match.matchAny}} {{tagMatch.total}} +  {{strings.match.agents}}  +

{{strings.match.matchNone}} @@ -216,32 +218,31 @@

{{strings[isEdit ? 'edit' : 'add']['header']}}


@@ -270,12 +271,23 @@

{{strings[isEdit ? 'edit' : 'add']['header']}}

let-i="index" let-row="row" let-value="value"> - + - {{tag | tagchip}} + style="background-color: #2B3148;" + class="orb-tag-chip" + > + {{ tag.key }}:  + {{ tag.value }} + + + No tag were created @@ -296,7 +308,7 @@

{{strings[isEdit ? 'edit' : 'add']['header']}}

Object.entries(a) @@ -177,8 +171,8 @@ export class AgentGroupAddComponent { prop: 'state', name: 'Status', - flexGrow: 1, - resizeable: false, + resizeable: true, + canAutoResize: false, width: 120, cellTemplate: this.agentStateTemplateRef, }, @@ -286,12 +280,16 @@ export class AgentGroupAddComponent if (this.isEdit) { this.agentGroupsService .editAgentGroup({ ...payload, id: this.agentGroupID }) - .subscribe(() => { + .subscribe( + (resp) => { this.notificationsService.success( 'Agent Group successfully updated', '', ); this.goBack(); + }, + (error) => { + this.isRequesting = false; }); } else { this.agentGroupsService.addAgentGroup(payload).subscribe(() => { diff --git a/ui/src/app/pages/fleet/groups/details/agent.group.details.component.html b/ui/src/app/pages/fleet/groups/details/agent.group.details.component.html index da2e7d5d8..7c1c89d1c 100644 --- a/ui/src/app/pages/fleet/groups/details/agent.group.details.component.html +++ b/ui/src/app/pages/fleet/groups/details/agent.group.details.component.html @@ -13,7 +13,7 @@

{{strings.propNames.name}}

{{ agentGroup.name }}

-
+

{{strings.propNames.description}}

{{ agentGroup.description }}

@@ -27,13 +27,24 @@

{{strings.propNames.tags}}

-
+
- {{tag | tagchip}} + *ngFor="let tag of agentGroup.tags | keyvalue" + style="background-color: #2B3148;" + class="orb-tag-chip" + > + {{ tag.key }}:  + {{ tag.value }} + + + No tag were created
diff --git a/ui/src/app/pages/fleet/groups/details/agent.group.details.component.scss b/ui/src/app/pages/fleet/groups/details/agent.group.details.component.scss index 15e268be0..f28cb3381 100644 --- a/ui/src/app/pages/fleet/groups/details/agent.group.details.component.scss +++ b/ui/src/app/pages/fleet/groups/details/agent.group.details.component.scss @@ -67,4 +67,9 @@ nb-tabset { margin-bottom: 0.4rem; } } - +.background { + background-color: #232940; + padding: 10px; + border-radius: 8px; + margin-bottom: 20px; +} diff --git a/ui/src/app/pages/fleet/groups/list/agent.group.list.component.html b/ui/src/app/pages/fleet/groups/list/agent.group.list.component.html index d9a35c5c2..56c817877 100644 --- a/ui/src/app/pages/fleet/groups/list/agent.group.list.component.html +++ b/ui/src/app/pages/fleet/groups/list/agent.group.list.component.html @@ -64,9 +64,15 @@

{{ strings.list.header }}

let-row="row" let-value="value" > - - {{ value }} - + + No description was provided diff --git a/ui/src/app/pages/fleet/groups/list/agent.group.list.component.scss b/ui/src/app/pages/fleet/groups/list/agent.group.list.component.scss index bf19677d6..538c825d8 100644 --- a/ui/src/app/pages/fleet/groups/list/agent.group.list.component.scss +++ b/ui/src/app/pages/fleet/groups/list/agent.group.list.component.scss @@ -189,4 +189,14 @@ mat-chip-list { } input[type=checkbox] { margin-left: 10px; -} \ No newline at end of file +} +.view-group-button { + background-color: transparent !important; + background-repeat: no-repeat !important; + border: none !important; + cursor: pointer !important; + outline: none !important; + overflow: hidden !important; + color: #ffffff; + text-align: left; +} diff --git a/ui/src/app/pages/fleet/groups/list/agent.group.list.component.ts b/ui/src/app/pages/fleet/groups/list/agent.group.list.component.ts index 46c40e338..9009c7a39 100644 --- a/ui/src/app/pages/fleet/groups/list/agent.group.list.component.ts +++ b/ui/src/app/pages/fleet/groups/list/agent.group.list.component.ts @@ -163,7 +163,6 @@ export class AgentGroupListComponent } ngAfterViewInit() { - this.orb.refreshNow(); this.columns = [ { name: '', @@ -184,15 +183,6 @@ export class AgentGroupListComponent minWidth: 150, cellTemplate: this.agentGroupNameTemplateCell, }, - { - prop: 'description', - name: 'Description', - width: 350, - canAutoResize: true, - resizeable: true, - minWidth: 180, - cellTemplate: this.agentGroupNameTemplateCell, - }, { prop: 'matching_agents', name: 'Agents', @@ -203,6 +193,15 @@ export class AgentGroupListComponent comparator: (a, b) => a.total - b.total, cellTemplate: this.agentGroupsTemplateCell, }, + { + prop: 'description', + name: 'Description', + width: 350, + canAutoResize: true, + resizeable: true, + minWidth: 180, + cellTemplate: this.agentGroupNameTemplateCell, + }, { prop: 'tags', width: 450, diff --git a/ui/src/app/pages/profile/profile.component.html b/ui/src/app/pages/profile/profile.component.html index 917c60901..61cfc10e5 100644 --- a/ui/src/app/pages/profile/profile.component.html +++ b/ui/src/app/pages/profile/profile.component.html @@ -1,62 +1,174 @@ -
-
- - User Information +
+
+

Account Information

+

User Profile / Settings

+
+
+ +
+
+
+ +
+
+
+ +
+

User Name

+
+

{{ user?.fullName }}

+
+
+ +
+
+ + + + +
+
+
+

+ Polling Control Configuration + + + +

+ + {{timer}} seconds + + +
+
+ +
+