+ Data Pipelines help Data Engineers develop, deploy, run, and manage data processing workloads
+ This app wraps the data pipelines library in order to provide example of the library usage
+
+
+
+
+
+
Learn more recommended
+
+
+
+
+
+
Overview
+
+ High level architecture and capabilities of the data pipelines project
+
+
+
+
+
+
+
+
+
How to
+
+ Learn about how to create your first data job
+
+
+
+
+
+
+
+
+
Explore
+
+ Explore existing data jobs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Widgets
+
+
+
+
+
+
+
+
diff --git a/projects/frontend/data-pipelines/gui/projects/ui/src/app/getting-started/getting-started.component.scss b/projects/frontend/data-pipelines/gui/projects/ui/src/app/getting-started/getting-started.component.scss
new file mode 100644
index 0000000000..674a0ed32a
--- /dev/null
+++ b/projects/frontend/data-pipelines/gui/projects/ui/src/app/getting-started/getting-started.component.scss
@@ -0,0 +1,4 @@
+/*
+ * Copyright 2021-2023 VMware, Inc.
+ * SPDX-License-Identifier: Apache-2.0
+ */
diff --git a/projects/frontend/data-pipelines/gui/projects/ui/src/app/getting-started/getting-started.component.spec.ts b/projects/frontend/data-pipelines/gui/projects/ui/src/app/getting-started/getting-started.component.spec.ts
new file mode 100644
index 0000000000..5619096035
--- /dev/null
+++ b/projects/frontend/data-pipelines/gui/projects/ui/src/app/getting-started/getting-started.component.spec.ts
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021-2023 VMware, Inc.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
+import { GettingStartedComponent } from './getting-started.component';
+import { OAuthService } from 'angular-oauth2-oidc';
+
+describe('GettingStartedComponent', () => {
+ let component: GettingStartedComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(waitForAsync(() => {
+ TestBed.configureTestingModule({
+ declarations: [GettingStartedComponent],
+ providers: [OAuthService],
+ imports: []
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(GettingStartedComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/projects/frontend/data-pipelines/gui/projects/ui/src/app/getting-started/getting-started.component.ts b/projects/frontend/data-pipelines/gui/projects/ui/src/app/getting-started/getting-started.component.ts
new file mode 100644
index 0000000000..72f431654d
--- /dev/null
+++ b/projects/frontend/data-pipelines/gui/projects/ui/src/app/getting-started/getting-started.component.ts
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2021-2023 VMware, Inc.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'app-getting-started',
+ templateUrl: './getting-started.component.html',
+ styleUrls: ['./getting-started.component.scss']
+})
+export class GettingStartedComponent {
+ constructor() {
+ // No-op.
+ }
+}
diff --git a/projects/frontend/data-pipelines/gui/projects/ui/src/app/http.interceptor.ts b/projects/frontend/data-pipelines/gui/projects/ui/src/app/http.interceptor.ts
new file mode 100644
index 0000000000..2c09e92ae4
--- /dev/null
+++ b/projects/frontend/data-pipelines/gui/projects/ui/src/app/http.interceptor.ts
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2021-2023 VMware, Inc.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { Injectable, Optional } from '@angular/core';
+import { OAuthModuleConfig, OAuthResourceServerErrorHandler, OAuthStorage } from 'angular-oauth2-oidc';
+import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
+
+import { Observable } from 'rxjs';
+import { authCodeFlowConfig } from './auth';
+
+@Injectable()
+export class AuthorizationInterceptor implements HttpInterceptor {
+
+ constructor(
+ private authStorage: OAuthStorage,
+ private errorHandler: OAuthResourceServerErrorHandler,
+ @Optional() private moduleConfig: OAuthModuleConfig) {
+ }
+
+ /**
+ * @inheritDoc
+ */
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ intercept(req: HttpRequest, next: HttpHandler): Observable> {
+ const url = req.url.toLowerCase();
+ if (!this.moduleConfig) {
+ return next.handle(req);
+ }
+
+ if (!this.moduleConfig.resourceServer) {
+ return next.handle(req);
+ }
+
+ if (!this.moduleConfig.resourceServer.allowedUrls) {
+ return next.handle(req);
+ }
+
+ if (!this.checkUrl(url)) {
+ return next.handle(req);
+ }
+
+ const sendAccessToken = this.moduleConfig.resourceServer.sendAccessToken;
+
+ if (sendAccessToken && url.startsWith(authCodeFlowConfig.issuer) && url.endsWith('api/auth/token')) {
+ const headers = req.headers
+ .set('Authorization', 'Basic ' + btoa(authCodeFlowConfig.clientId + ':'));
+
+ return next.handle(req.clone({ headers }));
+ } else if (sendAccessToken) {
+ const token = this.authStorage.getItem('access_token');
+ const header = `Bearer ${token}`;
+ const headers = req.headers
+ .set('Authorization', header);
+
+ return next.handle(req.clone({ headers }));
+ }
+
+ return next.handle(req);
+ }
+
+ private checkUrl(url: string): boolean {
+ const found = this.moduleConfig.resourceServer.allowedUrls.find(u => url.startsWith(u));
+ return !!found;
+ }
+}
diff --git a/projects/frontend/data-pipelines/gui/projects/ui/src/environments/environment.prod.ts b/projects/frontend/data-pipelines/gui/projects/ui/src/environments/environment.prod.ts
new file mode 100644
index 0000000000..bdc8e7c053
--- /dev/null
+++ b/projects/frontend/data-pipelines/gui/projects/ui/src/environments/environment.prod.ts
@@ -0,0 +1,8 @@
+/*
+ * Copyright 2021-2023 VMware, Inc.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+export const environment = {
+ production: true
+};
diff --git a/projects/frontend/data-pipelines/gui/projects/ui/src/environments/environment.ts b/projects/frontend/data-pipelines/gui/projects/ui/src/environments/environment.ts
new file mode 100644
index 0000000000..6bf2099149
--- /dev/null
+++ b/projects/frontend/data-pipelines/gui/projects/ui/src/environments/environment.ts
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2021-2023 VMware, Inc.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+// This file can be replaced during build by using the `fileReplacements` array.
+// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
+// The list of file replacements can be found in `angular.json`.
+
+export const environment = {
+ production: false
+};
+
+/*
+ * For easier debugging in development mode, you can import the following file
+ * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
+ *
+ * This import should be commented out in production mode because it will have a negative impact
+ * on performance if an error is thrown.
+ */
+import 'zone.js/plugins/zone-error'; // Included with Angular CLI.
diff --git a/projects/frontend/data-pipelines/gui/projects/ui/src/favicon.ico b/projects/frontend/data-pipelines/gui/projects/ui/src/favicon.ico
new file mode 100644
index 0000000000..997406ad22
Binary files /dev/null and b/projects/frontend/data-pipelines/gui/projects/ui/src/favicon.ico differ
diff --git a/projects/frontend/data-pipelines/gui/projects/ui/src/index.html b/projects/frontend/data-pipelines/gui/projects/ui/src/index.html
new file mode 100644
index 0000000000..ac4328f021
--- /dev/null
+++ b/projects/frontend/data-pipelines/gui/projects/ui/src/index.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+ Ui
+
+
+
+
+
+
+
+
+
diff --git a/projects/frontend/data-pipelines/gui/projects/ui/src/main.ts b/projects/frontend/data-pipelines/gui/projects/ui/src/main.ts
new file mode 100644
index 0000000000..a61616e51e
--- /dev/null
+++ b/projects/frontend/data-pipelines/gui/projects/ui/src/main.ts
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2021-2023 VMware, Inc.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { enableProdMode } from '@angular/core';
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+import { environment } from './environments/environment';
+
+if (environment.production) {
+ enableProdMode();
+}
+
+platformBrowserDynamic()
+ .bootstrapModule(AppModule)
+ .catch(err => console.error(err));
diff --git a/projects/frontend/data-pipelines/gui/projects/ui/src/polyfills.ts b/projects/frontend/data-pipelines/gui/projects/ui/src/polyfills.ts
new file mode 100644
index 0000000000..ebd6d2cbc1
--- /dev/null
+++ b/projects/frontend/data-pipelines/gui/projects/ui/src/polyfills.ts
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2021-2023 VMware, Inc.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * This file includes polyfills needed by Angular and is loaded before the app.
+ * You can add your own extra polyfills to this file.
+ *
+ * This file is divided into 2 sections:
+ * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
+ * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
+ * file.
+ *
+ * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
+ * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
+ * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
+ *
+ * Learn more in https://angular.io/guide/browser-support
+ */
+
+/***************************************************************************************************
+ * BROWSER POLYFILLS
+ */
+
+import '@webcomponents/custom-elements';
+/**
+ * By default, zone.js will patch all possible macroTask and DomEvents
+ * user can disable parts of macroTask/DomEvents patch by setting following flags
+ * because those flags need to be set before `zone.js` being loaded, and webpack
+ * will put import in the top of bundle, so user need to create a separate file
+ * in this directory (for example: zone-flags.ts), and put the following flags
+ * into that file, and then add the following code before importing zone.js.
+ * import './zone-flags';
+ *
+ * The flags allowed in zone-flags.ts are listed here.
+ *
+ * The following flags will work for all browsers.
+ *
+ * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
+ * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
+ * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
+ *
+ * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
+ * with the following flag, it will bypass `zone.js` patch for IE/Edge
+ *
+ * (window as any).__Zone_enable_cross_context_check = true;
+ *
+ */
+/***************************************************************************************************
+ * Zone JS is required by default for Angular itself.
+ */
+import 'zone.js'; // Included with Angular CLI.
+(window as any).global = window;
+
+/***************************************************************************************************
+ * APPLICATION IMPORTS
+ */
diff --git a/projects/frontend/data-pipelines/gui/projects/ui/src/styles.scss b/projects/frontend/data-pipelines/gui/projects/ui/src/styles.scss
new file mode 100644
index 0000000000..43ef083bb1
--- /dev/null
+++ b/projects/frontend/data-pipelines/gui/projects/ui/src/styles.scss
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2021-2023 VMware, Inc.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* You can add global styles to this file, and also import other style files */
+
+/**
+ Placeholder
+ **/
+
+:root {
+ --taurus-placeholder-color: var(--clr-color-neutral-500, #b3b3b3);
+}
+
+/* _normalize overwrite */
+::-webkit-input-placeholder {
+ /* clr-forms-placeholder-color */
+ color: var(--taurus-placeholder-color) !important;
+}
+
+/* Internet Explorer 10-11 */
+:-ms-input-placeholder {
+ /* clr-forms-placeholder-color */
+ color: var(--taurus-placeholder-color) !important;
+}
+
+/* Microsoft Edge */
+::-ms-input-placeholder {
+ /* clr-forms-placeholder-color */
+ color: var(--taurus-placeholder-color) !important;
+}
+
+/* Chrome, Firefox, Opera, Safari 10.1+ */
+::placeholder {
+ /* clr-forms-placeholder-color */
+ color: var(--taurus-placeholder-color) !important;
+}
+
+.fade-to-dark.dark {
+ --taurus-placeholder-color: #b3b3b3;
+}
+
+html {
+ scroll-behavior: smooth;
+}
+
+.content-container.switch-btn-bottom .nav-content {
+ margin-bottom: 1.5rem;
+}
+
+/* combo box */
+.clr-popover-content {
+ margin-top: 10px;
+}
+
+/* vmw search component */
+vmw-search .search-container cds-icon[shape=search] {
+ top: 2px !important;
+}
+
+/* forms */
+.destination-modal-body .custom-header-item .custom-header-input {
+ display: inline-block;
+ max-width: 10rem;
+}
+
+.modal-submit {
+ position: absolute;
+ left: -9999px;
+ z-index: -9999;
+ visibility: hidden;
+}
+
+vmw-form-section-container.p-header-section .form-header {
+ padding-bottom: 0 !important;
+ margin-top: 0;
+}
+
+vmw-form-section-container.p-header-section .form-header .section-title {
+ font-size: .7rem;
+ font-weight: 500;
+}
+
+vmw-form-section-container.p-header-section .vmw-vertical-line {
+ margin-top: 0 !important;
+}
+
+vmw-form-section-container.p-header-section .csp-edit-button {
+ margin-left: 1rem !important;
+}
+
+/* links */
+a.disabled {
+ pointer-events: none;
+ cursor: default;
+ opacity: 0.5;
+}
+
+/* theme */
+.toogle-theme {
+ position: absolute;
+ bottom: 0;
+ background-color: transparent !important;
+ padding-left: 0 !important;
+}
+
+.toogle-theme:hover {
+ background-color: transparent !important;
+}
+
+.toogle-theme .nav-link {
+ background-color: transparent !important;
+}
+
+.page-title {
+ margin-top: 0;
+}
+
+.tc {
+ text-align: center !important;
+}
+
+/* margins */
+.m-0 {
+ margin: 0 !important;
+}
+
+.mt-0 {
+ margin-top: 0 !important;
+}
+
+.mb-12 {
+ margin-bottom: 12px !important;
+}
+
+.pl-35 {
+ padding-left: 35px !important;
+}
+
+.w-100 {
+ width: 100% !important;
+}
+
+/* modals */
+.modal-body > :first-child {
+ margin-top: 0;
+}
+
+input.modal-form-control {
+ width: 12rem;
+}
+
+select.modal-form-control {
+ width: 8rem;
+}
+
+.modal-actions {
+ margin-top: -20px !important;
+}
+
+/* color styles */
+.red {
+ color: #EB5757;
+}
+
+/* position */
+.right {
+ float: right;
+}
+
+.left {
+ float: left;
+}
+
+/* lists */
+ul.idented {
+ text-indent: 2em;
+}
+
+/* media */
+@media (max-width: 600px) {
+ .right {
+ float: none !important;
+ }
+}
+
+/* datagrid cells */
+.cell-img-container {
+ min-width: 30px !important;
+ width: 60px !important;
+ text-align: center !important;
+}
+
+.cell-center {
+ margin: auto !important;
+}
+
+.enabled-column {
+ width: 6rem !important;
+}
+
+/* limit-height */
+.limit-height {
+ height: 50vh;
+}
+
+.limit-height clr-datagrid {
+ height: 50vh !important;
+}
+
+.limit-height clr-datagrid .datagrid {
+ margin-top: 0;
+}
+
+.limit-height clr-datagrid clr-dg-cell {
+ margin: auto;
+}
+
+/* team-list-component */
+.team-list-container .clr-form-control {
+ margin-top: 0 !important;
+}
+
+/* CSP-HEADER */
+/* Hide header assets */
+.header .header-actions .nav-icon.app-switcher {
+ width: 0;
+}
+
+.header .header-actions .nav-icon.app-switcher cds-icon {
+ display: none !important;
+}
+
+.header .header-actions .nav-icon.user-menu span.org-name {
+ display: none;
+}
+
+@media (min-width: 768px) {
+ .header .header-actions .nav-icon.user-menu div {
+ margin-top: .5rem;
+ }
+}
+
+.cdk-overlay-container {
+ z-index: 1100;
+}
diff --git a/projects/frontend/data-pipelines/gui/projects/ui/src/test.ts b/projects/frontend/data-pipelines/gui/projects/ui/src/test.ts
new file mode 100644
index 0000000000..d57e73ade7
--- /dev/null
+++ b/projects/frontend/data-pipelines/gui/projects/ui/src/test.ts
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2021-2023 VMware, Inc.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+// This file is required by karma.conf.js and loads recursively all the .spec and framework files
+
+import 'zone.js/testing';
+import { getTestBed } from '@angular/core/testing';
+import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
+
+declare const require: {
+ context(path: string, deep?: boolean, filter?: RegExp): {
+ keys(): string[];
+ (id: string): T;
+ };
+};
+
+// First, initialize the Angular testing environment.
+getTestBed().initTestEnvironment(
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting(),
+ {
+ teardown: { destroyAfterEach: false }
+ }
+);
+// Then we find all the tests.
+const context = require.context('./', true, /\.spec\.ts$/);
+// And load the modules.
+context.keys().map(context);