Skip to content

NIFI-14319: Create initial project structure for new NiFi Registry UI #9855

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions nifi-frontend/src/main/frontend/apps/nifi-registry/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"overrides": [
{
"files": ["*.ts"],
"extends": [
"plugin:@nx/angular",
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@angular-eslint/recommended",
"plugin:@angular-eslint/template/process-inline-templates",
"plugin:prettier/recommended"
],
"rules": {
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": "app",
"style": "camelCase"
}
],
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": "",
"style": "kebab-case"
}
],
"@angular-eslint/component-class-suffix": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-this-alias": "warn",
"@typescript-eslint/no-unused-vars": "warn",
"no-useless-escape": "off"
}
},
{
"files": ["*.html"],
"extends": ["plugin:@nx/angular-template"],
"rules": {}
}
]
}
38 changes: 38 additions & 0 deletions nifi-frontend/src/main/frontend/apps/nifi-registry/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

export default {
displayName: 'NiFi Registry',
preset: '../../jest.preset.js',
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
coverageDirectory: '../../coverage/apps/nifi-registry',
transform: {
'^.+\\.(ts|mjs|js|html)$': [
'jest-preset-angular',
{
tsconfig: '<rootDir>/tsconfig.spec.json',
stringifyContentPathRegex: '\\.(html|svg)$'
}
]
},
transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
snapshotSerializers: [
'jest-preset-angular/build/serializers/no-ng-attributes',
'jest-preset-angular/build/serializers/ng-snapshot',
'jest-preset-angular/build/serializers/html-comment'
]
};
120 changes: 120 additions & 0 deletions nifi-frontend/src/main/frontend/apps/nifi-registry/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
{
"name": "nifi-registry",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"generators": {
"@schematics/angular:component": {
"style": "scss"
}
},
"prefix": "app",
"sourceRoot": "apps/nifi-registry/src",
"targets": {
"build": {
"executor": "@nx/angular:application",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/apps/nifi-registry",
"index": "apps/nifi-registry/src/index.html",
"browser": "apps/nifi-registry/src/main.ts",
"polyfills": ["zone.js"],
"tsConfig": "apps/nifi-registry/tsconfig.app.json",
"inlineStyleLanguage": "scss",
"assets": [
{
"glob": "**/*.svg",
"input": "libs/shared/src/assets/",
"output": "./assets"
}
],
"styles": ["apps/nifi-registry/src/styles.scss"],
"stylePreprocessorOptions": {
"includePaths": [""]
},
"scripts": [],
"preserveSymlinks": true
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"outputHashing": "all"
"outputHashing": "all",
"optimization": true

},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true,
"preserveSymlinks": true,
"namedChunks": true,
"outputHashing": "none",
"assets": [
{
"glob": "**/*.svg",
"input": "libs/shared/src/assets/",
"output": "./assets"
}
],
"fileReplacements": [
{
"replace": "apps/nifi-registry/src/environments/environment.ts",
"with": "apps/nifi-registry/src/environments/environment.development.ts"
}
]
}
},
"defaultConfiguration": "production"
},
"serve": {
"executor": "@nx/angular:dev-server",
"configurations": {
"production": {
"buildTarget": "nifi-registry:build:production"
},
"development": {
"buildTarget": "nifi-registry:build:development",
"servePath": "/nifi-registry"
}
},
"defaultConfiguration": "development",
"options": {
"proxyConfig": "apps/nifi-registry/proxy.config.mjs",
"buildTarget": "nifi-registry:build",
"port": 4204
}
},
"extract-i18n": {
"executor": "@angular-devkit/build-angular:extract-i18n",
"options": {
"buildTarget": "nifi-registry:build"
}
},
"lint": {
"executor": "@nx/eslint:lint"
},
"test": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "apps/nifi-registry/jest.config.ts"
}
},
"serve-static": {
"executor": "@nx/web:file-server",
"options": {
"buildTarget": "nifi-registry:build",
"staticFilePath": "dist/apps/nifi-registry/browser",
"spa": true
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

const target = {
target: 'http://localhost:18080',
secure: false,
logLevel: 'debug',
changeOrigin: true,
headers: {
'X-ProxyScheme': 'http',
'X-ProxyPort': 4204
},
configure: (proxy, _options) => {
proxy.on('error', (err, _req, _res) => {
console.log('proxy error', err);
});
proxy.on('proxyReq', (proxyReq, req, _res) => {
console.log('Sending Request to the Target:', req.method, req.url);
});
proxy.on('proxyRes', (proxyRes, req, _res) => {
console.log('Received Response from the Target:', proxyRes.statusCode, req.url);
});
},
bypass: function (req) {
if (req.url.startsWith('/nifi-registry/')) {
return req.url;
}
}
};

export default {
'/**': target
};
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

@use 'sass:map';
@use '@angular/material' as mat;

@mixin generate-theme() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no styles here. I think you can delete this file.

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ExplorerComponent } from './pages/expolorer/feature/explorer.component';

const routes: Routes = [
{
path: 'explorer',
component: ExplorerComponent
},
{
path: 'nifi-registry',
redirectTo: 'explorer'
},
{
path: '',
redirectTo: 'explorer',
pathMatch: 'full'
},
{
path: '',
loadComponent: () => import('./pages/expolorer/feature/explorer.component').then((m) => m.ExplorerComponent)
}
];

@NgModule({
imports: [
RouterModule.forRoot(routes, {
paramsInheritanceStrategy: 'always',
useHash: true
})
],
exports: [RouterModule]
})
export class AppRoutingModule {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<div class="flex flex-col h-screen">
<app-header></app-header>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems odd to me that we would need two different header components (one for NiFi and now one for NiFi Registry). It would be nice if the fd-header could be generalized and moved into the shared lib. This is not a requirement for this PR but really should be considered.

I also see some theming issues:

Screenshot 2025-05-05 at 10 41 08 AM Screenshot 2025-05-05 at 10 41 16 AM
  1. In dark mode the 'NiFi Registry' text is not the correct color. It should be secondary-contrast
  2. In light mode the logo svg is not really visible. I realize that this is just an unfortunate consequence of the background color of the header matching the colors in the logo. I am not sure what to do here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll be sure to update the text color to use secondary-contrast. In regard to the svg, I think it might be time for a logo refresh? Perhaps it could include the name like NiFi's logo and I can remove this not-so-great-looking header. As a temporary solution, I could override the theme to utilize the old header color in light mode. What do you think?

With regard to using a shared component for the header, I'm very much in support of this. I think we could create a very simplistic component which leverages Angular's content projection, but I'm open to different ideas. The approach I wanted to take with this big piece of work is utilize shared components that currently exist, and make note of components that should be created and shared to be addressed after migrating the Registry UI. How does that sit with you? I can track it as a separate epic in Jira, or I can create tickets in this epic and address them once I have most of the application migrated.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point here is that the text color needs to pass contrast ratio with the background color in both light and dark mode.

One option here for the NiFi Registry logo is that we could wrap it in a div or span and give it the legacy Registry header background color and some rounded border radius:

Screenshot 2025-05-08 at 1 25 13 PM

This would work in both light and dark mode and not require a new logo.

As for you thoughts on a shared component: Yes I think leveraging Angular's content projection is a good path to explore. I was thinking you could just move the header from nifi into the shared lib. If you want to do this in a follow on effort I am supportive of that but we need a way to track this work. We need an epic or at least a parent jira with sub-tasks. This way would make it easier to break the work up so others may contribute and it should also lead to smaller more manageable PRs. Big PRs like this are difficult and time consuming to review.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the logo suggestion! I'll give that a try.

I have a Jira task open with subtasks (NIFI-14319 is one of them). The tickets are broken down by views. I don't believe the remaining PRs will be nearly as large as this one initializing the project, but I also now know that breaking down by view is not granular enough. I'll work on breaking these down further asap.

I'd rather address shared components separately to avoid having to deal with rebase conflicts in a PR like this one. Having a dedicated PR for promoting a handful of components from NiFi into the shared lib should be a very straightforward refactor and shouldn't take nearly as long to review.

<router-outlet></router-outlet>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Loading
Loading