From 33dd2beafcb7e3b3bc9114cf09d6fb19cfa71d7b Mon Sep 17 00:00:00 2001 From: Scott Aslan Date: Tue, 5 Sep 2017 17:02:14 -0400 Subject: [PATCH] [NIFIREG-13] Initial implementation of the registry UI/UX --- .travis.yml | 21 + nifi-registry-jetty/pom.xml | 25 +- .../nifi/registry/jetty/JettyServer.java | 23 +- .../apache/nifi-registry/web/webdefault.xml | 556 +++ nifi-registry-web-api/pom.xml | 10 +- nifi-registry-web-ui/pom.xml | 467 ++- .../src/main/frontend/Gruntfile.js | 91 + .../src/main/frontend/karma-test-shim.js | 113 + .../src/main/frontend/karma.conf.ci.js | 39 + .../src/main/frontend/karma.conf.js | 140 + .../src/main/frontend/package.json | 65 + .../src/main/frontend/protractor.config.js | 201 ++ .../src/main/locale/messages.es.xlf | 46 + .../src/main/platform/core/README.md | 33 + .../core/common/styles/_basicElements.scss | 130 + .../core/common/styles/_buttonToggles.scss | 98 + .../platform/core/common/styles/_buttons.scss | 198 ++ .../core/common/styles/_checkboxes.scss | 85 + .../platform/core/common/styles/_chips.scss | 67 + .../core/common/styles/_expansionPanels.scss | 59 + .../core/common/styles/_globalVars.scss | 80 + .../core/common/styles/_helperClasses.scss | 72 + .../platform/core/common/styles/_inputs.scss | 124 + .../platform/core/common/styles/_links.scss | 33 + .../platform/core/common/styles/_menus.scss | 120 + .../platform/core/common/styles/_modals.scss | 23 + .../platform/core/common/styles/_panels.scss | 54 + .../platform/core/common/styles/_radios.scss | 56 + .../platform/core/common/styles/_sideNav.scss | 20 + .../platform/core/common/styles/_tables.scss | 113 + .../platform/core/common/styles/_tabs.scss | 41 + .../core/common/styles/_tooltips.scss | 24 + .../common/styles/fluid-design-system.scss | 55 + .../core/dialogs/_fds-dialog-component.scss | 21 + .../confirm-dialog.component.html | 45 + .../confirm-dialog.component.js | 64 + .../core/dialogs/fds-dialog.component.html | 29 + .../core/dialogs/fds-dialog.component.js | 82 + .../core/dialogs/fds-dialogs.module.js | 87 + .../core/dialogs/services/dialog.service.js | 130 + .../core/fluid-design-system.module.js | 99 + .../resources/filters/registry-min.properties | 19 + .../resources/filters/registry.properties | 23 + .../src/main/webapp/WEB-INF/pages/index.jsp | 25 +- .../src/main/webapp/WEB-INF/web.xml | 29 +- .../nf-registry-general-administration.html | 30 + .../nf-registry-general-administration.js | 61 + .../nf-registry-administration.html | 39 + .../nf-registry-administration.js | 84 + .../nf-registry-administration.spec.js | 152 + .../users/add/nf-registry-add-user.html | 28 + .../users/add/nf-registry-add-user.js | 66 + .../details/nf-registry-user-details.html | 28 + .../users/details/nf-registry-user-details.js | 66 + .../nf-registry-users-administration.html | 122 + .../users/nf-registry-users-administration.js | 128 + .../nf-registry-user-permissions.html | 28 + .../nf-registry-user-permissions.js | 66 + .../nf-registry-bucket-permissions.html | 28 + .../nf-registry-bucket-permissions.js | 77 + .../nf-registry-workflow-administration.html | 170 + .../nf-registry-workflow-administration.js | 121 + ...nf-registry-explorer-grid-list-viewer.html | 18 + .../nf-registry-explorer-grid-list-viewer.js | 43 + .../nf-registry-droplet-grid-list-viewer.html | 17 + .../nf-registry-droplet-grid-list-viewer.js | 75 + .../nf-registry-bucket-grid-list-viewer.html | 18 + .../nf-registry-bucket-grid-list-viewer.js | 76 + .../nf-registry-grid-list-viewer.html | 186 + .../registry/nf-registry-grid-list-viewer.js | 106 + .../explorer/nf-registry-explorer.html | 18 + .../explorer/nf-registry-explorer.js | 61 + .../fluid-design-system/fds-demo.html | 3060 +++++++++++++++++ .../fluid-design-system/fds-demo.js | 1029 ++++++ .../nf-registry-page-not-found.js | 36 + .../main/webapp/images/registry-favicon.png | Bin 0 -> 388 bytes .../webapp/images/registry-logo-web-app.svg | 17 + .../src/main/webapp/nf-registry-bootstrap.js | 52 + .../src/main/webapp/nf-registry.animations.js | 119 + .../src/main/webapp/nf-registry.e2e-spec.js | 30 + .../src/main/webapp/nf-registry.html | 88 + .../src/main/webapp/nf-registry.js | 59 + .../src/main/webapp/nf-registry.module.js | 60 + .../src/main/webapp/nf-registry.routes.js | 104 + .../src/main/webapp/nf-registry.spec.js | 63 + .../webapp/services/nf-registry.service.js | 981 ++++++ .../main/webapp/systemjs-angular-loader.js | 66 + .../main/webapp/systemjs.builder.config.js | 137 + .../src/main/webapp/systemjs.config.extras.js | 27 + .../src/main/webapp/systemjs.spec.config.js | 76 + .../main/webapp/theming/_helperClasses.scss | 63 + .../webapp/theming/_structureElements.scss | 82 + .../administration/_structureElements.scss} | 8 +- .../general/_structureElements.scss | 25 + .../users/_structureElements.scss | 61 + .../workflow/_structureElements.scss | 61 + .../grid-list/_structureElements.scss | 44 + .../_structureElements.scss | 25 + .../src/main/webapp/theming/nf-registry.scss | 30 + pom.xml | 141 +- 100 files changed, 12262 insertions(+), 129 deletions(-) create mode 100644 .travis.yml create mode 100644 nifi-registry-jetty/src/main/resources/org/apache/nifi-registry/web/webdefault.xml create mode 100644 nifi-registry-web-ui/src/main/frontend/Gruntfile.js create mode 100644 nifi-registry-web-ui/src/main/frontend/karma-test-shim.js create mode 100644 nifi-registry-web-ui/src/main/frontend/karma.conf.ci.js create mode 100644 nifi-registry-web-ui/src/main/frontend/karma.conf.js create mode 100644 nifi-registry-web-ui/src/main/frontend/package.json create mode 100644 nifi-registry-web-ui/src/main/frontend/protractor.config.js create mode 100644 nifi-registry-web-ui/src/main/locale/messages.es.xlf create mode 100644 nifi-registry-web-ui/src/main/platform/core/README.md create mode 100644 nifi-registry-web-ui/src/main/platform/core/common/styles/_basicElements.scss create mode 100644 nifi-registry-web-ui/src/main/platform/core/common/styles/_buttonToggles.scss create mode 100644 nifi-registry-web-ui/src/main/platform/core/common/styles/_buttons.scss create mode 100644 nifi-registry-web-ui/src/main/platform/core/common/styles/_checkboxes.scss create mode 100644 nifi-registry-web-ui/src/main/platform/core/common/styles/_chips.scss create mode 100644 nifi-registry-web-ui/src/main/platform/core/common/styles/_expansionPanels.scss create mode 100644 nifi-registry-web-ui/src/main/platform/core/common/styles/_globalVars.scss create mode 100644 nifi-registry-web-ui/src/main/platform/core/common/styles/_helperClasses.scss create mode 100644 nifi-registry-web-ui/src/main/platform/core/common/styles/_inputs.scss create mode 100644 nifi-registry-web-ui/src/main/platform/core/common/styles/_links.scss create mode 100644 nifi-registry-web-ui/src/main/platform/core/common/styles/_menus.scss create mode 100644 nifi-registry-web-ui/src/main/platform/core/common/styles/_modals.scss create mode 100644 nifi-registry-web-ui/src/main/platform/core/common/styles/_panels.scss create mode 100644 nifi-registry-web-ui/src/main/platform/core/common/styles/_radios.scss create mode 100644 nifi-registry-web-ui/src/main/platform/core/common/styles/_sideNav.scss create mode 100644 nifi-registry-web-ui/src/main/platform/core/common/styles/_tables.scss create mode 100644 nifi-registry-web-ui/src/main/platform/core/common/styles/_tabs.scss create mode 100644 nifi-registry-web-ui/src/main/platform/core/common/styles/_tooltips.scss create mode 100644 nifi-registry-web-ui/src/main/platform/core/common/styles/fluid-design-system.scss create mode 100644 nifi-registry-web-ui/src/main/platform/core/dialogs/_fds-dialog-component.scss create mode 100644 nifi-registry-web-ui/src/main/platform/core/dialogs/confirm-dialog/confirm-dialog.component.html create mode 100644 nifi-registry-web-ui/src/main/platform/core/dialogs/confirm-dialog/confirm-dialog.component.js create mode 100644 nifi-registry-web-ui/src/main/platform/core/dialogs/fds-dialog.component.html create mode 100644 nifi-registry-web-ui/src/main/platform/core/dialogs/fds-dialog.component.js create mode 100644 nifi-registry-web-ui/src/main/platform/core/dialogs/fds-dialogs.module.js create mode 100644 nifi-registry-web-ui/src/main/platform/core/dialogs/services/dialog.service.js create mode 100644 nifi-registry-web-ui/src/main/platform/core/fluid-design-system.module.js create mode 100644 nifi-registry-web-ui/src/main/resources/filters/registry-min.properties create mode 100644 nifi-registry-web-ui/src/main/resources/filters/registry.properties create mode 100644 nifi-registry-web-ui/src/main/webapp/components/administration/general/nf-registry-general-administration.html create mode 100644 nifi-registry-web-ui/src/main/webapp/components/administration/general/nf-registry-general-administration.js create mode 100644 nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.html create mode 100644 nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.js create mode 100644 nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.spec.js create mode 100644 nifi-registry-web-ui/src/main/webapp/components/administration/users/add/nf-registry-add-user.html create mode 100644 nifi-registry-web-ui/src/main/webapp/components/administration/users/add/nf-registry-add-user.js create mode 100644 nifi-registry-web-ui/src/main/webapp/components/administration/users/details/nf-registry-user-details.html create mode 100644 nifi-registry-web-ui/src/main/webapp/components/administration/users/details/nf-registry-user-details.js create mode 100644 nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.html create mode 100644 nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.js create mode 100644 nifi-registry-web-ui/src/main/webapp/components/administration/users/permissions/nf-registry-user-permissions.html create mode 100644 nifi-registry-web-ui/src/main/webapp/components/administration/users/permissions/nf-registry-user-permissions.js create mode 100644 nifi-registry-web-ui/src/main/webapp/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.html create mode 100644 nifi-registry-web-ui/src/main/webapp/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js create mode 100644 nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.html create mode 100644 nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.js create mode 100644 nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/nf-registry-explorer-grid-list-viewer.html create mode 100644 nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/nf-registry-explorer-grid-list-viewer.js create mode 100644 nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/bucket/droplet/nf-registry-droplet-grid-list-viewer.html create mode 100644 nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/bucket/droplet/nf-registry-droplet-grid-list-viewer.js create mode 100644 nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/bucket/nf-registry-bucket-grid-list-viewer.html create mode 100644 nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/bucket/nf-registry-bucket-grid-list-viewer.js create mode 100644 nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.html create mode 100644 nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.js create mode 100644 nifi-registry-web-ui/src/main/webapp/components/explorer/nf-registry-explorer.html create mode 100644 nifi-registry-web-ui/src/main/webapp/components/explorer/nf-registry-explorer.js create mode 100644 nifi-registry-web-ui/src/main/webapp/components/fluid-design-system/fds-demo.html create mode 100644 nifi-registry-web-ui/src/main/webapp/components/fluid-design-system/fds-demo.js create mode 100644 nifi-registry-web-ui/src/main/webapp/components/page-not-found/nf-registry-page-not-found.js create mode 100644 nifi-registry-web-ui/src/main/webapp/images/registry-favicon.png create mode 100644 nifi-registry-web-ui/src/main/webapp/images/registry-logo-web-app.svg create mode 100644 nifi-registry-web-ui/src/main/webapp/nf-registry-bootstrap.js create mode 100644 nifi-registry-web-ui/src/main/webapp/nf-registry.animations.js create mode 100644 nifi-registry-web-ui/src/main/webapp/nf-registry.e2e-spec.js create mode 100644 nifi-registry-web-ui/src/main/webapp/nf-registry.html create mode 100644 nifi-registry-web-ui/src/main/webapp/nf-registry.js create mode 100644 nifi-registry-web-ui/src/main/webapp/nf-registry.module.js create mode 100644 nifi-registry-web-ui/src/main/webapp/nf-registry.routes.js create mode 100644 nifi-registry-web-ui/src/main/webapp/nf-registry.spec.js create mode 100644 nifi-registry-web-ui/src/main/webapp/services/nf-registry.service.js create mode 100644 nifi-registry-web-ui/src/main/webapp/systemjs-angular-loader.js create mode 100644 nifi-registry-web-ui/src/main/webapp/systemjs.builder.config.js create mode 100644 nifi-registry-web-ui/src/main/webapp/systemjs.config.extras.js create mode 100644 nifi-registry-web-ui/src/main/webapp/systemjs.spec.config.js create mode 100644 nifi-registry-web-ui/src/main/webapp/theming/_helperClasses.scss create mode 100644 nifi-registry-web-ui/src/main/webapp/theming/_structureElements.scss rename nifi-registry-web-ui/src/main/webapp/{css/main.css => theming/components/administration/_structureElements.scss} (89%) create mode 100644 nifi-registry-web-ui/src/main/webapp/theming/components/administration/general/_structureElements.scss create mode 100644 nifi-registry-web-ui/src/main/webapp/theming/components/administration/users/_structureElements.scss create mode 100644 nifi-registry-web-ui/src/main/webapp/theming/components/administration/workflow/_structureElements.scss create mode 100644 nifi-registry-web-ui/src/main/webapp/theming/components/explorer/grid-list/_structureElements.scss create mode 100644 nifi-registry-web-ui/src/main/webapp/theming/components/fluid-design-system/_structureElements.scss create mode 100644 nifi-registry-web-ui/src/main/webapp/theming/nf-registry.scss diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..4bef78311 --- /dev/null +++ b/.travis.yml @@ -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. + +# before_install +# 1. Configures pre-installed Chrome on Travis CI for karma testing +before_install: + - export CHROME_BIN=chromium-browser + - export DISPLAY=:99.0 + - sh -e /etc/init.d/xvfb start \ No newline at end of file diff --git a/nifi-registry-jetty/pom.xml b/nifi-registry-jetty/pom.xml index 3c75832c5..38e644288 100644 --- a/nifi-registry-jetty/pom.xml +++ b/nifi-registry-jetty/pom.xml @@ -13,7 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. --> - + 4.0.0 org.apache.nifi.registry @@ -49,29 +50,23 @@ org.eclipse.jetty jetty-servlets - - org.eclipse.jetty - jetty-jsp - org.apache.commons commons-lang3 - javax.servlet - javax.servlet-api - - - javax.servlet.jsp - javax.servlet.jsp-api + org.eclipse.jetty + jetty-annotations - javax.el - javax.el-api + org.eclipse.jetty + apache-jsp + compile - javax.servlet.jsp.jstl - javax.servlet.jsp.jstl-api + org.eclipse.jetty + apache-jstl + compile \ No newline at end of file diff --git a/nifi-registry-jetty/src/main/java/org/apache/nifi/registry/jetty/JettyServer.java b/nifi-registry-jetty/src/main/java/org/apache/nifi/registry/jetty/JettyServer.java index 474f90716..9f71e5fc0 100644 --- a/nifi-registry-jetty/src/main/java/org/apache/nifi/registry/jetty/JettyServer.java +++ b/nifi-registry-jetty/src/main/java/org/apache/nifi/registry/jetty/JettyServer.java @@ -20,6 +20,7 @@ import org.apache.nifi.registry.security.AuthorizedUserFilter; import org.apache.commons.lang3.StringUtils; import org.apache.nifi.registry.properties.NiFiRegistryProperties; +import org.eclipse.jetty.annotations.AnnotationConfiguration; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.HttpConfiguration; @@ -32,6 +33,9 @@ import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.eclipse.jetty.webapp.Configuration; +import org.eclipse.jetty.webapp.JettyWebXmlConfiguration; +import org.eclipse.jetty.webapp.WebAppClassLoader; import org.eclipse.jetty.webapp.WebAppContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,6 +44,7 @@ import javax.servlet.Filter; import java.io.File; import java.io.FileFilter; +import java.io.IOException; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; @@ -56,7 +61,7 @@ public class JettyServer { private static final Logger logger = LoggerFactory.getLogger(JettyServer.class); - + private static final String WEB_DEFAULTS_XML = "org/apache/nifi-registry/web/webdefault.xml"; private static final int HEADER_BUFFER_SIZE = 16 * 1024; // 16kb private static final FileFilter WAR_FILTER = new FileFilter() { @@ -79,6 +84,11 @@ public JettyServer(final NiFiRegistryProperties properties) { this.properties = properties; this.server = new Server(threadPool); + + // enable the annotation based configuration to ensure the jsp container is initialized properly + final Configuration.ClassList classlist = Configuration.ClassList.setServerDefault(server); + classlist.addBefore(JettyWebXmlConfiguration.class.getName(), AnnotationConfiguration.class.getName()); + configureConnectors(); loadWars(); } @@ -223,6 +233,7 @@ private WebAppContext loadWar(final File warFile, final String contextPath) { List serverClasses = new ArrayList<>(Arrays.asList(webappContext.getServerClasses())); serverClasses.remove("org.slf4j."); webappContext.setServerClasses(serverClasses.toArray(new String[0])); + webappContext.setDefaultsDescriptor(WEB_DEFAULTS_XML); // get the temp directory for this webapp final File webWorkingDirectory = properties.getWebWorkingDirectory(); @@ -245,11 +256,11 @@ private WebAppContext loadWar(final File warFile, final String contextPath) { // configure the max form size (3x the default) webappContext.setMaxFormContentSize(600000); -// try { -// webappContext.setClassLoader(new WebAppClassLoader(ClassLoader.getSystemClassLoader(), webappContext)); -// } catch (final IOException ioe) { -// throw new RuntimeException(ioe); -// } + try { + webappContext.setClassLoader(new WebAppClassLoader(ClassLoader.getSystemClassLoader(), webappContext)); + } catch (final IOException ioe) { + throw new RuntimeException(ioe); + } logger.info("Loading WAR: " + warFile.getAbsolutePath() + " with context path set to " + contextPath); return webappContext; } diff --git a/nifi-registry-jetty/src/main/resources/org/apache/nifi-registry/web/webdefault.xml b/nifi-registry-jetty/src/main/resources/org/apache/nifi-registry/web/webdefault.xml new file mode 100644 index 000000000..814dbd809 --- /dev/null +++ b/nifi-registry-jetty/src/main/resources/org/apache/nifi-registry/web/webdefault.xml @@ -0,0 +1,556 @@ + + + + + + + + + + + + + + + + + + + + + + + + Default web.xml file. + This file is applied to a Web application before it's own WEB_INF/web.xml file + + + + + + + + org.eclipse.jetty.servlet.listener.ELContextCleaner + + + + + + + + org.eclipse.jetty.servlet.listener.IntrospectorCleaner + + + + + + + + + + + + + + + + + + + default + org.eclipse.jetty.servlet.DefaultServlet + + aliases + false + + + acceptRanges + true + + + dirAllowed + false + + + welcomeServlets + true + + + redirectWelcome + false + + + maxCacheSize + 256000000 + + + maxCachedFileSize + 200000000 + + + maxCachedFiles + 2048 + + + gzip + true + + + etags + false + + + useFileMappedBuffer + true + + + + 0 + + + + default + / + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jsp + org.apache.jasper.servlet.JspServlet + + logVerbosityLevel + DEBUG + + + fork + false + + + keepgenerated + true + + + development + false + + + xpoweredBy + false + + + compilerTargetVM + 1.7 + + + compilerSourceVM + 1.7 + + + 0 + + + + jsp + *.jsp + *.jspf + *.jspx + *.xsp + *.JSP + *.JSPF + *.JSPX + *.XSP + + + + + + 30 + + + + + + + + + + + + + index.html + index.htm + index.jsp + + + + + + ar + ISO-8859-6 + + + be + ISO-8859-5 + + + bg + ISO-8859-5 + + + ca + ISO-8859-1 + + + cs + ISO-8859-2 + + + da + ISO-8859-1 + + + de + ISO-8859-1 + + + el + ISO-8859-7 + + + en + ISO-8859-1 + + + es + ISO-8859-1 + + + et + ISO-8859-1 + + + fi + ISO-8859-1 + + + fr + ISO-8859-1 + + + hr + ISO-8859-2 + + + hu + ISO-8859-2 + + + is + ISO-8859-1 + + + it + ISO-8859-1 + + + iw + ISO-8859-8 + + + ja + Shift_JIS + + + ko + EUC-KR + + + lt + ISO-8859-2 + + + lv + ISO-8859-2 + + + mk + ISO-8859-5 + + + nl + ISO-8859-1 + + + no + ISO-8859-1 + + + pl + ISO-8859-2 + + + pt + ISO-8859-1 + + + ro + ISO-8859-2 + + + ru + ISO-8859-5 + + + sh + ISO-8859-5 + + + sk + ISO-8859-2 + + + sl + ISO-8859-2 + + + sq + ISO-8859-2 + + + sr + ISO-8859-5 + + + sv + ISO-8859-1 + + + tr + ISO-8859-9 + + + uk + ISO-8859-5 + + + zh + GB2312 + + + zh_TW + Big5 + + + + + + Disable TRACE + / + TRACE + + + + + + Enable everything but TRACE + / + TRACE + + + + + diff --git a/nifi-registry-web-api/pom.xml b/nifi-registry-web-api/pom.xml index 74c6ba3ac..94478eb15 100644 --- a/nifi-registry-web-api/pom.xml +++ b/nifi-registry-web-api/pom.xml @@ -14,7 +14,8 @@ limitations under the License. --> - + 4.0.0 org.apache.nifi.registry @@ -57,7 +58,8 @@ NiFi Registry REST API ${project.version} - The Rest Api provides an interface to a registry with operations for saving, versioning, reading NiFi flows + The Rest Api provides an interface to a registry with operations for saving, + versioning, reading NiFi flows and components. @@ -71,7 +73,9 @@ classpath:/templates/index.html.hbs - ${project.build.directory}/${project.artifactId}-${project.version}/docs/rest-api/index.html + + ${project.build.directory}/${project.artifactId}-${project.version}/docs/rest-api/index.html + ${project.build.directory}/swagger-ui diff --git a/nifi-registry-web-ui/pom.xml b/nifi-registry-web-ui/pom.xml index 270af29fe..7240345de 100644 --- a/nifi-registry-web-ui/pom.xml +++ b/nifi-registry-web-ui/pom.xml @@ -14,7 +14,8 @@ limitations under the License. --> - + 4.0.0 org.apache.nifi.registry @@ -25,26 +26,446 @@ nifi-registry-web-ui 0.0.1-SNAPSHOT war - - - javax.servlet - javax.servlet-api - provided - - - javax.servlet.jsp - javax.servlet.jsp-api - provided - - - javax.el - javax.el-api - provided - - - javax.servlet.jsp.jstl - javax.servlet.jsp.jstl-api - provided - - + + true + ${project.build.directory}/tmp + registry-min.properties + ${basedir}/src/main + ${basedir}/src/main/frontend + ${project.build.directory}/frontend-working-directory + ${project.build.directory}/${project.build.finalName}/node_modules + + + + + src/main/resources/filters/${registry.filter} + + + + + org.eclipse.jetty + jetty-jspc-maven-plugin + ${jetty.version} + + + + jspc + + + true + true + + **/index.jsp + + + + + + + org.apache.maven.plugins + maven-resources-plugin + + + + copy-web-xml + prepare-package + + copy-resources + + + ${staging.dir}/WEB-INF + + + ${project.build.directory} + true + + web.xml + + + + + + + + copy-client-side-build-and-test-configs + initialize + + copy-resources + + + ${frontend.working.dir} + + + ${frontend.dependency.configs} + false + + * + + + + + + + + copy-source + initialize + + copy-resources + + + ${frontend.working.dir} + + + ${frontend.source} + false + + locale/**/* + webapp/**/* + platform/**/* + + + + + + + + copy-fluid-design-system + process-sources + + copy-resources + + + ${frontend.working.dir}/node_modules/@fluid-design-system/dist + + + + ${frontend.working.dir} + false + + platform/**/* + + + + + + + + copy-client-side-deps + prepare-package + + copy-resources + + + ${frontend.assets} + + + ${frontend.working.dir}/node_modules + false + + + roboto-fontface/fonts/Roboto/Roboto-Regular.ttf + roboto-fontface/fonts/Roboto/Roboto-Medium.ttf + roboto-fontface/fonts/Roboto/Roboto-Light.ttf + roboto-fontface/fonts/Roboto/Roboto-Bold.ttf + roboto-fontface/LICENSE* + + @covalent/core/common/platform.css + @covalent/core/common/styles/font/MaterialIcons-Regular.woff2 + @covalent/core/common/styles/font/MaterialIcons-Regular.ttf + @covalent/core/README.md + + + @fluid-design-system/dist/platform/core/common/styles/css/* + + @fluid-design-system/dist/platform/core/dialogs/**/* + @fluid-design-system/dist/platform/core/LICENSE.md + + font-awesome/css/font-awesome.css + font-awesome/fonts/fontawesome-webfont.woff2 + font-awesome/fonts/fontawesome-webfont.ttf + font-awesome/README.md + + + + + + + + copy-webapp-client-side-styles + prepare-package + + copy-resources + + + ${project.build.directory}/${project.build.finalName}/css + + + ${frontend.working.dir}/webapp/css + false + + * + + + + + + + + + + org.apache.maven.plugins + maven-war-plugin + + ${staging.dir}/WEB-INF/web.xml + + + src/main/webapp/WEB-INF/pages + WEB-INF/pages + + index.jsp + + true + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12.4 + + ${skipTests} + + + + + org.apache.maven.plugins + maven-clean-plugin + 3.0.0 + + true + + + ${project.build.directory} + + ** + + + frontend-working-directory/node/**/* + frontend-working-directory/node_modules/**/* + + + + + + + com.github.eirslett + frontend-maven-plugin + 1.5 + + ${frontend.working.dir} + + + + + install-node-and-npm + + install-node-and-npm + + initialize + + v6.11.1 + 3.10.10 + + + + + npm-install + + npm + + initialize + + --silent --cache-min Infinity install + ${frontend.working.dir} + + + + + grunt-compile-fds-sass + + grunt + + generate-sources + + compile-fds-styles + ${frontend.working.dir} + + + + + javascript-tests + + npm + + test + + run test:ci + ${frontend.working.dir} + + + + + grunt-compile-web-ui-sass + + grunt + + generate-resources + + compile-web-ui-styles + ${frontend.working.dir} + + + + + + com.github.eirslett + frontend-maven-plugin + 1.5 + + + + grunt-package-web-ui + + grunt + + generate-resources + + bundle-web-ui + ${frontend.working.dir} + + + + + + org.apache.maven.plugins + maven-resources-plugin + + + + copy-web-ui-bundle + prepare-package + + copy-resources + + + ${project.build.directory}/${project.build.finalName} + + + + ${frontend.working.dir}/webapp + false + + nf-registry.bundle.* + + + + + + + + copy-localization + prepare-package + + copy-resources + + + ${project.build.directory}/${project.build.finalName} + + + + ${frontend.working.dir}/locale + false + + * + + + + + + + + + org.apache.rat + apache-rat-plugin + + + nbactions.xml + src/main/frontend/package.json + src/main/platform/core/package.json + src/main/platform/core/README.md + + + + + diff --git a/nifi-registry-web-ui/src/main/frontend/Gruntfile.js b/nifi-registry-web-ui/src/main/frontend/Gruntfile.js new file mode 100644 index 000000000..5ec5c61d7 --- /dev/null +++ b/nifi-registry-web-ui/src/main/frontend/Gruntfile.js @@ -0,0 +1,91 @@ +/* + * 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. + */ + +module.exports = function (grunt) { + // load all grunt tasks matching the ['grunt-*', '@*/grunt-*'] patterns + require('load-grunt-tasks')(grunt); + + grunt.initConfig({ + sass: { + options: { + outputStyle: 'compressed', + sourceMap: true + }, + minifyFds: { + files: [{ + './platform/core/common/styles/css/fluid-design-system.min.css': ['./platform/core/common/styles/fluid-design-system.scss'] + }] + }, + minifyWebUi: { + files: [{ + './webapp/css/nf-registry.min.css': ['./webapp/theming/nf-registry.scss'] + }] + } + }, + systemjs: { + options: { + sfx: true, + minify: true, // Comment out this line when developing + sourceMaps: true, + build: { + lowResSourceMaps: true + } + }, + bundleWebUi: { + options: { + configFile: "./webapp/systemjs.builder.config.js" + }, + files: [{ + "src": "./webapp/nf-registry-bootstrap.js", + "dest": "./webapp/nf-registry.bundle.min.js" + }] + } + }, + compress: { + options: { + mode: 'gzip' + }, + webUi: { + files: [{ + expand: true, + src: ['./webapp/nf-registry.bundle.min.js'], + dest: './', + ext: '.bundle.min.js.gz' + }] + }, + webUiStyles: { + files: [{ + expand: true, + src: ['./webapp/css/nf-registry.min.css'], + dest: './', + ext: '.min.css.gz' + }] + }, + fdsStyles: { + files: [{ + expand: true, + src: ['./platform/core/common/styles/css/fluid-design-system.min.css'], + dest: './', + ext: '.min.css.gz' + }] + } + } + }); + grunt.registerTask('compile-fds-styles', ['sass:minifyFds', 'compress:fdsStyles']); + grunt.registerTask('compile-web-ui-styles', ['sass:minifyWebUi', 'compress:webUiStyles']); + grunt.registerTask('bundle-web-ui', ['systemjs:bundleWebUi', 'compress:webUi']); +}; diff --git a/nifi-registry-web-ui/src/main/frontend/karma-test-shim.js b/nifi-registry-web-ui/src/main/frontend/karma-test-shim.js new file mode 100644 index 000000000..d0a524dad --- /dev/null +++ b/nifi-registry-web-ui/src/main/frontend/karma-test-shim.js @@ -0,0 +1,113 @@ +/* + * 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. + */ + +// /*global jasmine, __karma__, window*/ +Error.stackTraceLimit = 0; // "No stacktrace"" is usually best for app testing. + +// Uncomment to get full stacktrace output. Sometimes helpful, usually not. +// Error.stackTraceLimit = Infinity; // + +jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000; + +// builtPaths: root paths for output ("built") files +// get from karma.config.js, then prefix with '/base/' +var builtPaths = (__karma__.config.builtPaths) + .map(function (p) { + return '/base/' + p; + }); + +__karma__.loaded = function () { +}; + +function isJsFile(path) { + return path.slice(-3) == '.js'; +} + +function isSpecFile(path) { + return /\.spec\.(.*\.)?js$/.test(path); +} + +// Is a "built" file if is JavaScript file in one of the "built" folders +function isBuiltFile(path) { + return isJsFile(path) && + builtPaths.reduce(function (keep, bp) { + return keep || (path.substr(0, bp.length) === bp); + }, false); +} + +var allSpecFiles = Object.keys(window.__karma__.files) + .filter(isSpecFile) + .filter(isBuiltFile); + +System.config({ + // Base URL for System.js calls. 'base/' is where Karma serves files from. + baseURL: 'base', + + // Map the angular testing umd bundles + map: { + '@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js', + '@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js', + '@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js', + '@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js', + '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js', + '@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js', + '@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js', + '@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js' + } +}); + +System.import('webapp/systemjs.spec.config.js') + .then(importSystemJsExtras) + .then(initTestBed) + .then(initTesting); + +/** Optional SystemJS configuration extras. Keep going w/o it */ +function importSystemJsExtras() { + return System.import('webapp/systemjs.config.extras.js') + .catch(function (reason) { + console.log( + 'Warning: System.import could not load the optional "systemjs.config.extras.js". Did you omit it by accident? Continuing without it.' + ); + console.log(reason); + }); +} + +function initTestBed() { + return Promise.all([ + System.import('@angular/core/testing'), + System.import('@angular/platform-browser-dynamic/testing') + ]) + + .then(function (providers) { + var coreTesting = providers[0]; + var browserTesting = providers[1]; + + coreTesting.TestBed.initTestEnvironment( + browserTesting.BrowserDynamicTestingModule, + browserTesting.platformBrowserDynamicTesting()); + }) +} + +// Import all spec files and start karma +function initTesting() { + return Promise.all( + allSpecFiles.map(function (moduleName) { + return System.import(moduleName); + }) + ) + .then(__karma__.start, __karma__.error); +} diff --git a/nifi-registry-web-ui/src/main/frontend/karma.conf.ci.js b/nifi-registry-web-ui/src/main/frontend/karma.conf.ci.js new file mode 100644 index 000000000..c03db0d46 --- /dev/null +++ b/nifi-registry-web-ui/src/main/frontend/karma.conf.ci.js @@ -0,0 +1,39 @@ +/* + * 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. + */ + +var baseConfig = require('./karma.conf.js'); + +module.exports = function (config) { + // Load base config + baseConfig(config); + + if (process.env.TRAVIS) { + config.set({ + browsers: ['Chrome_travis_ci'] + }); + } + + // Override base config + config.set({ + singleRun: true, + autoWatch: false, + reporters: ['progress', 'spec', 'coverage'], + specReporter: { + failFast: true + } + }); +}; \ No newline at end of file diff --git a/nifi-registry-web-ui/src/main/frontend/karma.conf.js b/nifi-registry-web-ui/src/main/frontend/karma.conf.js new file mode 100644 index 000000000..f3946b739 --- /dev/null +++ b/nifi-registry-web-ui/src/main/frontend/karma.conf.js @@ -0,0 +1,140 @@ +/* + * 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. + */ + +module.exports = function (config) { + + var appBase = 'webapp/'; // app JS and map files + + config.set({ + basePath: '', + frameworks: ['jasmine'], + + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-spec-reporter'), + require('karma-coverage') + ], + + client: { + builtPaths: [appBase], // add more spec base paths as needed + clearContext: false // leave Jasmine Spec Runner output visible in browser + }, + + files: [ + // System.js for module loading + 'node_modules/systemjs/dist/system.src.js', + + // Polyfills + 'node_modules/core-js/client/shim.js', + + // zone.js + 'node_modules/zone.js/dist/zone.js', + 'node_modules/zone.js/dist/long-stack-trace-zone.js', + 'node_modules/zone.js/dist/proxy.js', + 'node_modules/zone.js/dist/sync-test.js', + 'node_modules/zone.js/dist/jasmine-patch.js', + 'node_modules/zone.js/dist/async-test.js', + 'node_modules/zone.js/dist/fake-async-test.js', + 'node_modules/hammerjs/hammer.js', + + // RxJs + {pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false}, + {pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false}, + + // Paths loaded via module imports: + {pattern: 'node_modules/@angular/**/*.js', included: false, watched: false}, + {pattern: 'node_modules/@angular/**/*.js.map', included: false, watched: false}, + {pattern: 'node_modules/@covalent/**/*.js', included: false, watched: false}, + {pattern: 'node_modules/@covalent/**/*.js.map', included: false, watched: false}, + {pattern: 'node_modules/@fluid-design-system/**/*.js', included: false, watched: false}, + {pattern: 'node_modules/jquery/**/*.js', included: false, watched: false}, + {pattern: 'node_modules/roboto-fontface/**/*.ttf', included: false, watched: false}, + {pattern: 'node_modules/systemjs-plugin-text/text.js', included: false, watched: false}, + + {pattern: appBase + 'systemjs.spec.config.js', included: false, watched: false}, + 'karma-test-shim.js', // optionally extend SystemJS mapping e.g., with barrels + + // Include the Fluid Design System (which includes the Teradata Covalent and + // Angular Material themes) in the test suite. + { + pattern: 'node_modules/@fluid-design-system/dist/platform/core/common/styles/css/fluid-design-system.min.css', + included: true, + watched: true, + served: true + }, + { + pattern: 'node_modules/@fluid-design-system/dist/platform/core/common/styles/css/fluid-design-system.min.css.map', + included: false, + watched: false + }, + + // Include the Nifi Registry styles (currently built based off of the + // @fluid-design-system/dist/platform/core/common/styles/_globalVars.scss) + { + pattern: 'webapp/css/nf-registry.min.css', + included: true, + watched: true + }, + { + pattern: 'webapp/css/nf-registry.min.css.map', + included: false, + watched: false + }, + + // Asset (HTML) paths loaded via Angular's component compiler + // (these paths need to be rewritten, see proxies section) + // {pattern: appBase + '**/*.html', included: false, watched: true}, + + // Images + {pattern: '**/*.svg', watched: false, included: false, served: true}, + + // Paths for debugging with source maps in dev tools + {pattern: appBase + '**/*.js', included: false, watched: false} + ], + + // Proxied base paths for loading assets + proxies: { + // required for modules fetched by SystemJS + '/base/nifi-registry/node_modules/': '/base/node_modules/', + '/base/systemjs-angular-loader.js': '/base/webapp/systemjs-angular-loader.js', + '/base/nifi-registry/': '/base/webapp/', + '/nifi-registry/images/': '/base/webapp/images/' + }, + + exclude: [], + preprocessors: { + 'webapp/**/!(*spec|*mock).js': 'coverage', + 'platform/**/!(*spec|*mock).js': 'coverage' + }, + reporters: ['progress', 'kjhtml', 'spec', 'coverage'], + coverageReporter: { + type: 'html', + dir: 'coverage/' + }, + specReporter: { + failFast: false + }, + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['Chrome'], + singleRun: false + }) +} diff --git a/nifi-registry-web-ui/src/main/frontend/package.json b/nifi-registry-web-ui/src/main/frontend/package.json new file mode 100644 index 000000000..731747570 --- /dev/null +++ b/nifi-registry-web-ui/src/main/frontend/package.json @@ -0,0 +1,65 @@ +{ + "name": "nifi-registry", + "version": "0.0.1", + "description": "", + "scripts": { + "protractor": "protractor protractor.config.js", + "test:dev": "./node_modules/protractor/bin/webdriver-manager update --gecko false && karma start karma.conf.js", + "test:ci": "./node_modules/protractor/bin/webdriver-manager update --gecko false && karma start karma.conf.ci.js", + "test:once": "karma start karma.conf.js --single-run" + }, + "keywords": [], + "author": "", + "repository": { + "type": "git", + "url": "https://github.com/apache/nifi-registry" + }, + "dependencies": { + "@covalent/core": "1.0.0-beta.6", + "angular2-moment": "1.6.0", + "font-awesome": "4.7.0", + "moment": "2.18.1", + "roboto-fontface": "0.7.0" + }, + "devDependencies": { + "@angular/animations": "4.2.0", + "@angular/cdk": "2.0.0-beta.8", + "@angular/common": "4.2.0", + "@angular/compiler": "4.2.0", + "@angular/core": "4.2.0", + "@angular/flex-layout": "2.0.0-beta.8", + "@angular/forms": "4.2.0", + "@angular/http": "4.2.0", + "@angular/material": "2.0.0-beta.6", + "@angular/platform-browser": "4.2.0", + "@angular/platform-browser-dynamic": "4.2.0", + "@angular/router": "4.2.0", + "canonical-path": "0.0.2", + "grunt": "0.4.5", + "grunt-cli": "1.2.0", + "grunt-contrib-compress": "1.4.3", + "grunt-sass": "2.0.0", + "grunt-systemjs-builder": "1.0.0", + "hammerjs": "2.0.8", + "jasmine-core": "2.4.1", + "jquery": "3.2.1", + "karma": "1.7.0", + "karma-chrome-launcher": "2.0.0", + "karma-cli": "1.0.1", + "karma-coverage": "1.1.1", + "karma-jasmine": "1.0.2", + "karma-jasmine-html-reporter": "0.2.2", + "karma-spec-reporter": "0.0.31", + "load-grunt-tasks": "3.5.2", + "lodash": "4.16.2", + "material-design-icons": "3.0.1", + "protractor": "4.0.14", + "reset-css": "2.2.0", + "rxjs": "5.4.3", + "systemjs": "0.20.17", + "systemjs-plugin-text": "0.0.11", + "zone.js": "0.8.4" + }, + "bundleDependencies": [], + "private": true +} diff --git a/nifi-registry-web-ui/src/main/frontend/protractor.config.js b/nifi-registry-web-ui/src/main/frontend/protractor.config.js new file mode 100644 index 000000000..e8ef72145 --- /dev/null +++ b/nifi-registry-web-ui/src/main/frontend/protractor.config.js @@ -0,0 +1,201 @@ +/* + * 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. + */ + +var fs = require('fs'); +var path = require('canonical-path'); +var _ = require('lodash'); + +exports.config = { + directConnect: true, + + // Capabilities to be passed to the webdriver instance. + capabilities: { + 'browserName': 'chrome' + }, + + // Framework to use. Jasmine is recommended. + framework: 'jasmine', + + // Spec patterns are relative to this config file + specs: ['**/*e2e-spec.js'], + + // For angular tests + useAllAngular2AppRoots: true, + + // Base URL for application server + baseUrl: 'http://localhost:8080/nifi-registry', + + // See https://github.com/angular/protractor/blob/master/docs/server-setup.md for the various protractor + // browser driver setup. Here we directly use Chrome or Firefox drivers. If Chrome or Firefox are not + // available an error will be thrown and a Selenium Server needs to be installed and started. + directConnect: true, + + //OR + + // The address of a running selenium server. + // seleniumAddress: 'http://localhost:4444/wd/hub', + + // OR + + // The location of the selenium standalone server .jar file, relative + // to the location of this config. If no other method of starting selenium + // is found, this will default to + // node_modules/protractor/selenium/selenium-server... + // seleniumServerJar: './node_modules/protractor/selenium/selenium-server-standalone-2.41.0.jar', + + // The port to start the selenium server on, or null if the server should + // find its own unused port. + // seleniumPort: 4444, + + onPrepare: function () { + // debugging + console.log('browser.params:' + JSON.stringify(browser.params)); + jasmine.getEnv().addReporter(new Reporter(browser.params)); + + // Allow changing bootstrap mode to NG1 for upgrade tests + global.setProtractorToNg1Mode = function () { + browser.useAllAngular2AppRoots = false; + browser.rootEl = 'body'; + }; + }, + + jasmineNodeOpts: { + defaultTimeoutInterval: 10000, + showTiming: true, + print: function () { + } + } +}; + +// Custom reporter +function Reporter(options) { + var _defaultOutputFile = path.resolve(process.cwd(), './_test-output', 'protractor-results.txt'); + options.outputFile = options.outputFile || _defaultOutputFile; + + initOutputFile(options.outputFile); + options.appDir = options.appDir || './'; + var _root = {appDir: options.appDir, suites: []}; + log('AppDir: ' + options.appDir, +1); + var _currentSuite; + + this.suiteStarted = function (suite) { + _currentSuite = {description: suite.description, status: null, specs: []}; + _root.suites.push(_currentSuite); + log('Suite: ' + suite.description, +1); + }; + + this.suiteDone = function (suite) { + var statuses = _currentSuite.specs.map(function (spec) { + return spec.status; + }); + statuses = _.uniq(statuses); + var status = statuses.indexOf('failed') >= 0 ? 'failed' : statuses.join(', '); + _currentSuite.status = status; + log('Suite ' + _currentSuite.status + ': ' + suite.description, -1); + }; + + this.specStarted = function (spec) { + + }; + + this.specDone = function (spec) { + var currentSpec = { + description: spec.description, + status: spec.status + }; + if (spec.failedExpectations.length > 0) { + currentSpec.failedExpectations = spec.failedExpectations; + } + + _currentSuite.specs.push(currentSpec); + log(spec.status + ' - ' + spec.description); + }; + + this.jasmineDone = function () { + outputFile = options.outputFile; + //// Alternate approach - just stringify the _root - not as pretty + //// but might be more useful for automation. + // var output = JSON.stringify(_root, null, 2); + var output = formatOutput(_root); + fs.appendFileSync(outputFile, output); + }; + + function ensureDirectoryExistence(filePath) { + var dirname = path.dirname(filePath); + if (directoryExists(dirname)) { + return true; + } + ensureDirectoryExistence(dirname); + fs.mkdirSync(dirname); + } + + function directoryExists(path) { + try { + return fs.statSync(path).isDirectory(); + } + catch (err) { + return false; + } + } + + function initOutputFile(outputFile) { + ensureDirectoryExistence(outputFile); + var header = "Protractor results for: " + (new Date()).toLocaleString() + "\n\n"; + fs.writeFileSync(outputFile, header); + } + + // for output file output + function formatOutput(output) { + var indent = ' '; + var pad = ' '; + var results = []; + results.push('AppDir:' + output.appDir); + output.suites.forEach(function (suite) { + results.push(pad + 'Suite: ' + suite.description + ' -- ' + suite.status); + pad += indent; + suite.specs.forEach(function (spec) { + results.push(pad + spec.status + ' - ' + spec.description); + if (spec.failedExpectations) { + pad += indent; + spec.failedExpectations.forEach(function (fe) { + results.push(pad + 'message: ' + fe.message); + }); + pad = pad.substr(2); + } + }); + pad = pad.substr(2); + results.push(''); + }); + results.push(''); + return results.join('\n'); + } + + // for console output + var _pad; + + function log(str, indent) { + _pad = _pad || ''; + if (indent == -1) { + _pad = _pad.substr(2); + } + console.log(_pad + str); + if (indent == 1) { + _pad = _pad + ' '; + } + } + +} diff --git a/nifi-registry-web-ui/src/main/locale/messages.es.xlf b/nifi-registry-web-ui/src/main/locale/messages.es.xlf new file mode 100644 index 000000000..91c9e1d5e --- /dev/null +++ b/nifi-registry-web-ui/src/main/locale/messages.es.xlf @@ -0,0 +1,46 @@ + + + + + + + + general + general + A description of the type of administration options available. + General administration tab + + + users + Usuarios + A description of the type of administration options available. + Users administration tab + + + Workflow + Flujo de trabajo + A description of the type of administration options available. + Workflow administration tab + + + Create + Crear + A button for creating a new bucket in the registry.@@nf-admin-workflow-create-bucket-button. + Create new bucket button + + + + \ No newline at end of file diff --git a/nifi-registry-web-ui/src/main/platform/core/README.md b/nifi-registry-web-ui/src/main/platform/core/README.md new file mode 100644 index 000000000..2981e882c --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/README.md @@ -0,0 +1,33 @@ +# Fluid Design System (FDS) + +FDS NiFi Registry UI/UX Platform for layouts, icons, custom components and themes. This should be added as a dependency for any project that wants to use layouts, icons and themes for Angular Material or Teradata Covalent. + +The FDS will have custom components that enforce standards and best practices through built-in design patterns. + +## Setup + +Import the **[FluidDesignSystemModule]** in your NgModule: + +```javascript +var fdsCore = require('@fluid-design-system/core'); +NfRegistryAppModule.prototype = { + constructor: NfRegistryAppModule +}; + +NfRegistryAppModule.annotations = [ + new ngCore.NgModule({ + imports: [ + fdsCore, + ... + ], + ... +}) +... +``` + + +## Styles, Icons and Theming + +See [theming](https://github.com/apache/nifi-registry.github.io) in the docs for more info (TBD). + +FDS NiFi Registry UI/UX Platform comes with a base CSS file `@fluid-design-system/core/common/styles/css/fluid-design-system.css` (includes icons). diff --git a/nifi-registry-web-ui/src/main/platform/core/common/styles/_basicElements.scss b/nifi-registry-web-ui/src/main/platform/core/common/styles/_basicElements.scss new file mode 100644 index 000000000..fc5808c5e --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_basicElements.scss @@ -0,0 +1,130 @@ +/* +* 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. +*/ + +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + src: local("Roboto Light"), local("Roboto-Light"), url("../../../../../../../roboto-fontface/fonts/Roboto/Roboto-Light.ttf") format("truetype"); +} + +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: 300; + src: local("Roboto LightItalic"), local("Roboto-LightItalic"), url("../../../../../../../roboto-fontface/fonts/Roboto/Roboto-LightItalic.ttf") format("truetype"); +} + +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: normal; + src: local("Roboto Regular"), local("Roboto-Regular"), url("../../../../../../../roboto-fontface/fonts/Roboto/Roboto-Regular.ttf") format("truetype"); +} + +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + src: local("Roboto Medium"), local("Roboto-Medium"), url("../../../../../../../roboto-fontface/fonts/Roboto/Roboto-Medium.ttf") format("truetype"); +} + +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: bold; + src: local("Roboto Bold"), local("Roboto-Bold"), url("../../../../../../../roboto-fontface/fonts/Roboto/Roboto-Bold.ttf") format("truetype"); +} + +@font-face { + font-family: 'Roboto'; + font-style: italic; + font-weight: normal; + src: local("Roboto Italic"), local("Roboto-Italic"), url("../../../../../../../roboto-fontface/fonts/Roboto/Roboto-RegularItalic.ttf") format("truetype"); +} + +@font-face { + font-family: 'Roboto Slab'; + font-style: normal; + font-weight: normal; + src: local("RobotoSlab Regular"), local("RobotoSlab-Regular"), url("../../../../../../../roboto-fontface/fonts/Roboto-Slab/Roboto-Slab-Regular.ttf") format("truetype"); +} + +@font-face { + font-family: 'Roboto Slab'; + font-style: normal; + font-weight: bold; + src: local("RobotoSlab Bold"), local("RobotoSlab-Bold"), url("../../../../../../../roboto-fontface/fonts/Roboto-Slab/Roboto-Slab-Bold.ttf") format("truetype"); +} + +body, +html { + height: 100%; +} + +body, +button, +input, +label, +select, +td, +textarea { + font-family: $fontPrimary; + font-size: 14px; +} + +body { + color: $bodyTextColor; +} + +strong { + font-weight: bold; +} + +pre { + overflow-x: auto; +} + +em { + font-style: italic; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: $fontPrimary; + font-weight: normal; + font-style: normal; + background: #FFFFFF; +} + +h1 { + color: $pageHeaderTextColor; +} + +h2 { + color: $subHeaderTextColor; +} + +table { + font-family: $fontPrimary; + font-size: 13px; + color: $grey2; +} diff --git a/nifi-registry-web-ui/src/main/platform/core/common/styles/_buttonToggles.scss b/nifi-registry-web-ui/src/main/platform/core/common/styles/_buttonToggles.scss new file mode 100644 index 000000000..73f4263b0 --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_buttonToggles.scss @@ -0,0 +1,98 @@ +/* + * 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. + */ + +body[fds] .expansion-panel-filter-toggle-group { + box-shadow: none !important; +} + +body[fds] .expansion-panel-filter-toggle-group .mat-button-toggle { + height: 75px; + width: 125px; + border: 1px solid $grey4; +} + +body[fds] .expansion-panel-filter-toggle-group .mat-button-toggle-label-content { + height: 100%; + width: 100%; + padding: 0; + line-height: 63px; + text-align: center; +} + +body[fds] .expansion-panel-filter-toggle-group .mat-button-toggle-checked { + background-color: $blue-grey1; + color: white; +} + +body[fds] .expansion-panel-filter-toggle-group .mat-button-toggle-checked .md-display-1 { + color: white; +} + +body[fds] .expansion-panel-filter-toggle-group .md-display-1 { + color: $blue-grey1; +} + +body[fds] .expansion-panel-filter-toggle-group div { + line-height: normal; +} + +body[fds] .tab-toggle-group { + box-shadow: none !important; +} + +body[fds] .tab-toggle-group .mat-button-toggle-label-content { + border-bottom: 2px solid $grey5; +} + +body[fds] .tab-toggle-group .mat-button-toggle-checked { + background: transparent; +} + +body[fds] .tab-toggle-group .mat-button-toggle-checked .mat-button-toggle-label-content { + border-bottom: 2px solid $blue-grey1; + background: transparent; +} + +body[fds] .on-off-toggle-group { + box-shadow: none !important; +} + +body[fds] .on-off-toggle-group .mat-button-toggle { + height: 20px; + width: 35px; + border: 1px solid $grey4; +} + +body[fds] .on-off-toggle-group .mat-button-toggle-label-content { + height: 100%; + width: 100%; + padding: 0; + line-height: 20px; + text-align: center; +} + +body[fds] .on-off-toggle-group .mat-button-toggle-checked { + background-color: $blue-grey1; + color: white; + border: 1px solid $blue-grey1; +} + +body[fds] .off-toggle.mat-button-toggle-checked { + background-color: $grey4; + color: $grey1; + border: 1px solid $grey4; +} diff --git a/nifi-registry-web-ui/src/main/platform/core/common/styles/_buttons.scss b/nifi-registry-web-ui/src/main/platform/core/common/styles/_buttons.scss new file mode 100644 index 000000000..c8d480234 --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_buttons.scss @@ -0,0 +1,198 @@ +/* +* 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. +*/ + +/* Buttons */ + +$buttonFontColor: #FFFFFF; +$buttonFontColorDisabled: #D1E8D1; +$buttonBgColorPrimary: $primaryColor; +$buttonBgColorPrimaryHover: $primaryColorHover; +$buttonBgColorPrimaryDisabled: $primaryColor; +$buttonBgColorPrimarySelected: $primaryColor; +$buttonBgColorSecondary: #FFFFFF; +$buttonBgColorSecondaryHover: $primaryColorHover; +$buttonBgColorSecondarySelected: #FFFFFF; +$buttonBgColorRegular: #FFFFFF; +$buttonBgColorRegularHover: #808793; +$buttonBgColorRegularDisabled: #808793; +$buttonBgColorRegularSelected: #FFFFFF; +$buttonBorderColorSecondary: $primaryColor; +$buttonBorderColorSecondaryHover: $buttonBgColorSecondaryHover; +$buttonBorderColorSecondaryDisabled: $buttonBgColorSecondaryHover; +$buttonBorderColorSecondarySelected: $primaryColor; +$buttonBorderColorRegular: #CFD3D7; +$buttonBorderColorRegularHover: $buttonBgColorRegularHover; +$buttonBorderColorRegularDisabled: $buttonBgColorRegularHover; +$buttonBorderColorRegularSelected: #CFD3D7; +$buttonFontPrimaryColor: $buttonFontColor; +$buttonFontPrimaryColorHover: $buttonFontColor; +$buttonFontPrimaryColorDisabled: $buttonFontColorDisabled; +$buttonFontPrimaryColorSelected: $buttonFontColor; +$buttonFontSecondaryColor: $primaryColorHover; +$buttonFontSecondaryColorHover: $buttonFontColor; +$buttonFontSecondaryColorDisabled: $buttonFontColorDisabled; +$buttonFontSecondaryColorSelected: $primaryColorHover; +$buttonFontRegularColor: $descriptionTextColor; +$buttonFontRegularColorHover: $buttonFontColor; +$buttonFontRegularColorDisabled: $buttonFontColorDisabled; +$buttonFontRegularColorSelected: $bodyTextColor; +$buttonFontWarnColor: $buttonFontColor; +$buttonFontWarnColorHover: $buttonFontColor; +$buttonFontWarnColorDisabled: $buttonFontColorDisabled; +$buttonFontWarnColorSelected: $buttonFontColor; +$buttonFontCriticalColor: $buttonFontColor; +$buttonFontCriticalColorHover: $buttonFontColor; +$buttonFontCriticalColorDisabled: $buttonFontColorDisabled; +$buttonFontCriticalColorSelected: $buttonFontColor; + +body[fds] .mat-raised-button { + height: 34px; + font-family: $fontPrimary; + font-weight: normal; + font-size: 14px; + text-transform: uppercase; + line-height: normal; + box-shadow: 0px 0px 0px 0px rgba(0, 0, 0, 0.2), 0px 0px 0px 0px rgba(0, 0, 0, 0.14), 0px 0px 0px 0px rgba(0, 0, 0, 0.12); +} + +body[fds] .mat-raised-button.cdk-focused:focus { + box-shadow: 0px 0px 2px 0px rgba(19, 145, 193, 1); +} + +body[fds] .mat-raised-button[disabled] { + opacity: .6; +} + +body[fds] .mat-button-focus-overlay { + background-color: transparent; +} + +body[fds] .mat-raised-button.mat-fds-primary { + border: 1px solid $buttonBgColorPrimary; + background-color: $buttonBgColorPrimary; + color: $buttonFontPrimaryColor; +} + +body[fds] .mat-raised-button.mat-fds-primary:hover { + background-color: $buttonBgColorPrimaryHover; + color: $buttonFontPrimaryColorHover; +} + +body[fds] .mat-raised-button.mat-fds-primary.mat-button-focus { + color: $buttonFontPrimaryColorSelected; + background-color: $buttonBgColorPrimarySelected; +} + +body[fds] .mat-raised-button.mat-fds-primary[disabled] { + color: $buttonFontPrimaryColorDisabled; + background-color: $buttonBgColorPrimaryDisabled; + color: $buttonFontPrimaryColorDisabled; +} + +body[fds] .mat-raised-button.mat-fds-secondary { + color: $buttonFontSecondaryColor; + border: 1px solid $buttonBorderColorSecondary; +} + +body[fds] .mat-raised-button.mat-fds-secondary:hover:not([disabled]) { + color: $buttonFontSecondaryColorHover; + background-color: $buttonBgColorSecondaryHover; + border: 1px solid $buttonBorderColorSecondaryHover; +} + +body[fds] .mat-raised-button.mat-fds-secondary.mat-button-focus { + color: $buttonFontSecondaryColorSelected; + background-color: $buttonBgColorSecondarySelected; + border: 1px solid $buttonBorderColorSecondarySelected; +} + +body[fds] .mat-raised-button.mat-fds-secondary[disabled] { + color: $buttonFontPrimaryColorDisabled; + background-color: $buttonBgColorPrimaryDisabled; +} + +body[fds] .mat-raised-button.mat-fds-regular { + color: $buttonFontRegularColor; + background-color: $buttonBgColorRegular; + border: 1px solid $buttonBorderColorRegular; +} + +body[fds] .mat-raised-button.mat-fds-regular:hover { + color: $buttonFontRegularColorHover; + background-color: $buttonBgColorRegularHover; + border: 1px solid $buttonBorderColorRegularHover; +} + +body[fds] .mat-raised-button.mat-fds-regular.mat-button-focus { + color: $buttonFontRegularColorSelected; + background-color: $buttonBgColorRegularSelected; + border: 1px solid $buttonBorderColorRegularSelected; +} + +body[fds] .mat-raised-button.mat-fds-regular[disabled] { + color: $buttonFontRegularColorDisabled; + background-color: $buttonBgColorRegularDisabled; + border: 1px solid $buttonBorderColorRegularDisabled; +} + +body[fds] .mat-raised-button.mat-fds-warn { + border: 1px solid $errorColor; + background-color: $errorColor; + color: $buttonFontWarnColor; +} + +body[fds] .mat-raised-button.mat-fds-warn:hover { + color: $buttonFontWarnColorHover; + background-color: $red2; + border: 1px solid $errorColor; +} + +body[fds] .mat-raised-button.mat-fds-warn.mat-button-focus { + color: $buttonFontWarnColorSelected; + background-color: $errorColor; + border: 1px solid $buttonBorderColorRegularSelected; +} + +body[fds] .mat-raised-button.mat-fds-warn[disabled] { + color: $buttonFontWarnColorDisabled; + background-color: $errorColor; + border: 1px solid $errorColor; +} + +body[fds] .mat-raised-button.mat-fds-critical { + color: $buttonFontCriticalColor; + background-color: $orange1; + border: 1px solid $orange1; +} + +body[fds] .mat-raised-button.mat-fds-critical:hover { + color: $buttonFontCriticalColorHover; + background-color: $orange2; + border: 1px solid $orange2; +} + +body[fds] .mat-raised-button.mat-fds-critical.mat-button-focus { + color: $buttonFontCriticalColorSelected; + background-color: $orange2; + border: 1px solid $buttonBorderColorRegularSelected; +} + +body[fds] .mat-raised-button.mat-fds-critical[disabled] { + color: $buttonFontCriticalColorDisabled; + background-color: $orange1; + border: 1px solid $orange1; +} diff --git a/nifi-registry-web-ui/src/main/platform/core/common/styles/_checkboxes.scss b/nifi-registry-web-ui/src/main/platform/core/common/styles/_checkboxes.scss new file mode 100644 index 000000000..319995e81 --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_checkboxes.scss @@ -0,0 +1,85 @@ +/* +* 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. +*/ + +/* Checkboxes */ + +body[fds] md-checkbox { + margin-bottom: 3px; +} + +body[fds] .mat-checkbox-inner-container { + height: 10px !important; + width: 10px !important; +} + +body[fds] .mat-checkbox-frame { + height: 10px; + width: 10px; + border-color: $grey7; +} + +body[fds] .mat-checkbox-ripple { + left: -7px; + top: -7px; + right: -7px; + bottom: -7px; +} + +body[fds] .mat-checkbox-indeterminate.mat-accent .mat-checkbox-background, +body[fds] .mat-checkbox-checked.mat-accent .mat-checkbox-background { + background-color: $blue-grey1; +} + +body[fds] .mat-checkbox-inner-container:hover { + background-color: $blue-grey1; + border-radius: 2px; +} + +body[fds] .mat-checkbox-background { + height: 10px; + width: 10px; +} + +/* Covalent TdDataTableComponent 'selectable' property checkboxes */ + +body[fds] .mat-pseudo-checkbox { + height: 10px !important; + width: 10px !important; + border: 1px solid $grey7; +} + +body[fds] .mat-pseudo-checkbox:hover { + background-color: $blue-grey1; + border: 1px solid $blue-grey1; +} + +body[fds] .mat-pseudo-checkbox-checked::after { + content: '\f00c'; + font-size: 8px; + font-family: fontawesome; + margin-top: -9px; + margin-left: -1px; + border: none; + transform: initial; +} + +body[fds] .mat-pseudo-checkbox-checked, body[fds] .mat-pseudo-checkbox-indeterminate { + background-color: $blue-grey1; + border: 1px solid $blue-grey1; + height: 10px; + width: 10px; +} diff --git a/nifi-registry-web-ui/src/main/platform/core/common/styles/_chips.scss b/nifi-registry-web-ui/src/main/platform/core/common/styles/_chips.scss new file mode 100644 index 000000000..755f6780e --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_chips.scss @@ -0,0 +1,67 @@ +/* +* 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. +*/ + +/* Chips */ + +body[fds] .mat-chip { + border-radius: 2px; + font-size: 10px; + font-family: $fontPrimary; + font-style: normal; + font-weight: normal; + padding: 4px 12px 4px 12px; +} + +body[fds] .mat-chip i { + margin-left: 10px; + float: right; + margin-top: 2px; +} + +body[fds] .mat-basic-chip { + color: $grey2; + height: 24px; + margin: 12px 8px 0 0; +} + +body[fds] .mat-basic-chip i { + margin-left: 10px; + float: right; + margin-top: 2px; +} + +body[fds] .mat-basic-chip .td-chip { + font-size: 10px; + padding: 0px 0px 7px 12px; + min-height: 24px; +} + +body[fds] .td-chip span { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 65px; +} + +body[fds] .td-chip-disabled .td-chip { + padding: 0px 0px 0px 12px; +} + +body[fds] .mat-basic-chip md-icon.td-chip-removal { + font-size: 15px; + margin-bottom: 7px; +} diff --git a/nifi-registry-web-ui/src/main/platform/core/common/styles/_expansionPanels.scss b/nifi-registry-web-ui/src/main/platform/core/common/styles/_expansionPanels.scss new file mode 100644 index 000000000..937bce79d --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_expansionPanels.scss @@ -0,0 +1,59 @@ +/* +* 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. +*/ + +/* Expansion Panels */ + +body[fds] td-expansion-panel:not(:last-of-type) .td-expanded { + margin-bottom: 0px; +} + +body[fds] .td-expansion-panel-header-content { + height: 80px !important; + padding: 0px 30px !important; + border-bottom: 1px solid $grey7; +} + +body[fds] .td-expansion-content form { + padding: 15px 10px 20px 20px; +} + +body[fds] .md-subhead { + font-size: 18px; + color: $grey3; +} + +body[fds] td-expansion-panel .td-expansion-panel-header .td-expansion-panel-header-content md-icon.td-expand-icon { + font-size: 28px; + color: $blue-grey1; + font-weight: bold; +} + +body[fds] td-expansion-panel { + box-shadow: none; +} + +body[fds] td-expansion-panel .td-expansion-panel-header:hover:not(.mat-disabled) { + background: $blue4; +} + +body[fds] td-expansion-panel .td-expansion-panel-header:focus { + background: #FFFFFF; +} + +body[fds] td-expansion-panel .td-expansion-panel-header:focus .td-expansion-panel-header-content { + border-bottom: 1px solid $primaryColor; +} diff --git a/nifi-registry-web-ui/src/main/platform/core/common/styles/_globalVars.scss b/nifi-registry-web-ui/src/main/platform/core/common/styles/_globalVars.scss new file mode 100644 index 000000000..acd7efbf1 --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_globalVars.scss @@ -0,0 +1,80 @@ +/* + * 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. + */ + +/* Begin Global Variables */ + +/* Text */ + +$fontPrimary: "Roboto", +sans-serif; +$fontSecondary: "Robot Slab", +sans-serif; +$fontMedium: "Roboto Medium", +sans-serif; +$fontLight: "Roboto Light", +sans-serif; + +/* Define colors */ + +$grey1: #333333; +$grey2: #666666; +$grey3: #999999; +$grey4: #CCCCCC; +$grey5: #EEEEEE; +$grey6: #F5F5F5; // or #FAFAFA +$grey7: #DDDDDD; +$grey8: #CFD3D7; +$grey9: #b2b8c1; +$grey10: #dbdee2; +$blue1: #1491C1; +$blue2: #E7f6Fc; +$blue3: #A7DFF2; +$blue4: #F3FAFF; +$blue5: #728E9B; +$blue6: #004849; +$blue7: #d0dbe0; +$blue8: #1291c1; +$red1: #EF6162; +$red2: #D14A50; +$orange1: #E98A40; +$orange2: #D3702D; +$green1: #1EB475; +$green2: #3FAE2A; +$green3: #429929; +$rose1: #9E737D; +$rose2: #915D69; +$blue-grey1: #6B8791; +$blue-grey2: #B2C1C6; + +/* Set FDS theme */ + +$primaryColor: $rose1; //$green2 or $blue5 +$primaryColorHover: $rose2; //$green3 or $blue6 +$secondaryColor: $rose1; //$green1 or $blue5 +$accentColor: $blue7; //$orange1 or $blue7 +$accentColorHover: $grey4; //$orange2 or $grey4 +$warnColor: $red1; +$errorColor: $warnColor; +$warningColor: $accentColor; +$bodyTextColor: $grey1; +$pageHeaderTextColor: $grey1; +$subHeaderTextColor: $grey2; +$descriptionTextColor: $grey2; +$linkColor: $blue-grey1; +$linkColorDisabled: $grey1; + +/*End Global Variables */ diff --git a/nifi-registry-web-ui/src/main/platform/core/common/styles/_helperClasses.scss b/nifi-registry-web-ui/src/main/platform/core/common/styles/_helperClasses.scss new file mode 100644 index 000000000..6ae237c10 --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_helperClasses.scss @@ -0,0 +1,72 @@ +/* + * 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. + */ + +/* Text */ + +.camel-case { + text-transform: capitalize; +} + +.header { + font-family: $fontMedium; + font-size: 16px; + color: $pageHeaderTextColor; + padding-bottom: 10px; +} + +.details-header { + height: 92px; +} + +.details-header-container { + position: relative; + top: 22px; + left: 10px; +} + +.description { + font-family: $fontLight; + font-size: 12px; + color: $descriptionTextColor; +} + +.description i { + padding-right: 5px; +} + +.label { + font-family: $fontMedium; + font-size: 14px; + color: $bodyTextColor; + text-transform: uppercase; +} + +.units { + font-family: $fontLight; + font-size: 14px; + color: $bodyTextColor; +} + +.align-vertical { + margin-top: auto; + margin-bottom: auto; +} + +.align-horizontal { + margin-left: auto; + margin-right: auto; +} diff --git a/nifi-registry-web-ui/src/main/platform/core/common/styles/_inputs.scss b/nifi-registry-web-ui/src/main/platform/core/common/styles/_inputs.scss new file mode 100644 index 000000000..702436389 --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_inputs.scss @@ -0,0 +1,124 @@ +/* +* 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. +*/ + +/* Inputs */ + +body[fds] .mat-input-container { + min-width: 200px; +} + +body[fds] .mat-input-wrapper { + margin: 0; + padding-bottom: 0; +} + +body[fds] input.mat-input-element, body[fds] textarea.mat-input-element { + border-radius: 2px; + color: $grey2; + border: 1px solid $grey8; + height: 32px; + padding: 0px 10px; + width: calc(100% - 22px); +} + +body[fds] textarea.mat-input-element { + padding: 10px 10px; +} + +body[fds] input.mat-input-element[disabled], body[fds] textarea.mat-input-element[disabled] { + background: $grey9; + color: $grey10; + border: 1px solid $grey9; +} + +body[fds] .mat-input-subscript-wrapper { + margin-top: 18px; + width: calc(100% - 23px); +} + +body[fds] input.mat-input-element:focus, body[fds] textarea.mat-input-element:focus { + border-color: $blue-grey1; +} + +body[fds] .mat-input-underline { + display: none; +} + +body[fds] .mat-input-placeholder { + font-size: 14px; + color: $grey3; + font-weight: 300; +} + +body[fds] .mat-input-placeholder-wrapper { + top: -20px; + padding-top: 33px; +} + +body[fds] .mat-input-placeholder { + top: 20px; + left: 10px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: calc(100% - 44px); +} + +body[fds] md-input-container.mat-focused .mat-input-placeholder { + transform: translateY(-26px) translateX(-10px) scale(0.75); +} + +body[fds] .mat-input-placeholder.mat-float:not(.mat-empty) { + transform: translateY(-26px) translateX(-10px) scale(.75); +} + +body[fds] .input-button { + top: 3.5px; + left: -24px; + z-index: 1; +} + +body[fds] .input-button.mat-raised-button[disabled] { + opacity: 1; +} + +body[fds] .mat-input-infix { + padding: 7px 23px 0px 0px; + border-top: 0; +} + +body[fds] td-chips .mat-input-placeholder-wrapper::after { + content: '\f0b0'; + display: inline-table; + font-family: FontAwesome; + float: right; + margin: 2px 10px 0px 0px; + color: $grey3; +} + +body[fds] td-chips input.mat-input-element { + border-radius: 2px; + color: $grey2; + border: 1px solid $grey8; + height: 32px; + padding: 0px 10px; + width: 100%; +} + +body[fds] .mat-hint { + color: $grey3; +} diff --git a/nifi-registry-web-ui/src/main/platform/core/common/styles/_links.scss b/nifi-registry-web-ui/src/main/platform/core/common/styles/_links.scss new file mode 100644 index 000000000..c6973c36a --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_links.scss @@ -0,0 +1,33 @@ +/* +* 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. +*/ + +/* Links */ + +body[fds] .link { + color: $linkColor; + font-size: 14px; + text-decoration: none; +} + +body[fds] .link:hover { + text-decoration: underline; +} + +body[fds] .link .disabled { + color: $linkColorDisabled; + text-decoration: none; +} diff --git a/nifi-registry-web-ui/src/main/platform/core/common/styles/_menus.scss b/nifi-registry-web-ui/src/main/platform/core/common/styles/_menus.scss new file mode 100644 index 000000000..26a233310 --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_menus.scss @@ -0,0 +1,120 @@ +/* +* 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. +*/ + +/* Menus */ + +body[fds] .mat-menu-panel { + border-radius: 2px; +} + +body[fds] .mat-menu-content { + padding-top: 0px; + padding-bottom: 0px; +} + +body[fds] .mat-menu-item { + font-size: 14px; + color: $bodyTextColor; + min-width: 200px; + text-transform: none; + height: 24px; + line-height: 24px; +} + +body[fds] .regular-button-menu .mat-menu-item:hover { + color: #ffffff; + background-color: #808793; +} + +body[fds] .mat-menu-item[disabled] { + color: rgba(0, 0, 0, 0.38); + background-color: #ffffff; +} + +body[fds] .mat-menu-item .mat-icon { + font-size: 14px; +} + +body[fds] .mat-menu-item .fa { + font-size: 14px; + width: 1em; + height: 1em; +} + +body[fds] .mat-menu-item[disabled] .mat-icon { + color: rgba(0, 0, 0, 0.38); +} + +body[fds] .mat-menu-item[disabled] .fa { + color: rgba(0, 0, 0, 0.38); +} + +body[fds] .mat-menu-item:hover:not([disabled]) .mat-icon { + color: #ffffff; +} + +body[fds] .mat-menu-item:hover:not([disabled]) .fa { + color: #ffffff; +} + +body[fds] .mat-menu-item:hover:not([disabled]), +body[fds] .mat-menu-item:focus:not([disabled]) { + color: #ffffff; + background-color: #808793; +} + +body[fds] .fds-primary-dropdown-button-menu .mat-menu-item:hover:not([disabled]), +body[fds] .fds-primary-dropdown-button-menu .mat-menu-item:focus:not([disabled]) { + color: #FFFFFF; + background-color: $primaryColorHover; +} + +.fds-primary-dropdown-button-menu .cdk-focused { + color: $buttonFontPrimaryColorSelected; + background-color: $buttonBgColorPrimarySelected; +} + +.mat-raised-button .mat-button-wrapper i { + padding-left: 10px; +} + +body[fds] .mat-option { + font-size: 14px; + color: $bodyTextColor; + text-transform: none; + height: 24px; + line-height: 24px; +} + +body[fds] .mat-autocomplete-panel.mat-autocomplete-panel-below { + top: 0; +} + +body[fds] .regular-button-menu .mat-option:hover { + color: #ffffff; + background-color: #808793; +} + +body[fds] .mat-option:hover:not([disabled]), +body[fds] .mat-option:focus:not([disabled]) { + color: #ffffff; + background-color: #808793; +} + +body[fds] .mat-select-underline { + display: none; +} diff --git a/nifi-registry-web-ui/src/main/platform/core/common/styles/_modals.scss b/nifi-registry-web-ui/src/main/platform/core/common/styles/_modals.scss new file mode 100644 index 000000000..51c7bad94 --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_modals.scss @@ -0,0 +1,23 @@ +/* +* 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. +*/ + +/* Modals */ + +body[fds] .mat-dialog-container { + padding: 20px; + width: 400px; +} diff --git a/nifi-registry-web-ui/src/main/platform/core/common/styles/_panels.scss b/nifi-registry-web-ui/src/main/platform/core/common/styles/_panels.scss new file mode 100644 index 000000000..f88a4320f --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_panels.scss @@ -0,0 +1,54 @@ +/* +* 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. +*/ + +/* Panels */ + +body[fds] .mat-card-title { + font-size: 20px; + color: $grey1; + margin-bottom: 0px; +} + +body[fds] md-card-title { + padding-top: 20px; + padding-left: 20px; + padding-right: 20px; +} + +body[fds] .mat-card-subtitle { + padding-left: 20px; + padding-right: 20px; + padding-top: 10px; + margin-bottom: 0px; +} + +body[fds] .mat-card-content { + color: $grey2; + padding: 10px 20px 20px 20px; + margin: 0px; +} + +body[fds] .mat-card .mat-card-actions:last-child, body[fds] .mat-card .mat-card .mat-card-actions:last-child { + padding: 0px 20px 20px 20px; + margin: 0px; +} + +body[fds] .fds-panel-menu-button { + position: absolute; + right: 0px; + top: 20px; +} diff --git a/nifi-registry-web-ui/src/main/platform/core/common/styles/_radios.scss b/nifi-registry-web-ui/src/main/platform/core/common/styles/_radios.scss new file mode 100644 index 000000000..2d9ca8e1b --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_radios.scss @@ -0,0 +1,56 @@ +/* +* 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. +*/ + +/* Radios */ + +body[fds] .mat-radio-container { + height: 12px; + width: 12px; +} + +body[fds] .mat-radio-outer-circle { + height: 12px; + width: 12px; + background-color: #FFFFFF; + border: 1px solid $grey7; +} + +body[fds] .mat-radio-outer-circle:hover { + background-color: $blue-grey1; + border-color: $blue-grey1; +} + +body[fds] .mat-radio-checked .mat-radio-outer-circle { + border: 1px solid $blue-grey1; + background-color: $blue-grey1; +} + +body[fds] .mat-radio-button.mat-accent.mat-radio-checked .mat-radio-outer-circle { + border-color: $blue-grey1; +} + +body[fds] .mat-radio-inner-circle { + height: 10px; + width: 10px; + left: 1px; + top: 1px; + background-color: #FFFFFF; +} + +body[fds] .mat-radio-checked .mat-radio-inner-circle { + background-color: #FFFFFF; +} diff --git a/nifi-registry-web-ui/src/main/platform/core/common/styles/_sideNav.scss b/nifi-registry-web-ui/src/main/platform/core/common/styles/_sideNav.scss new file mode 100644 index 000000000..af3514d3d --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_sideNav.scss @@ -0,0 +1,20 @@ +/* +* 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. +*/ + +body[fds] .mat-sidenav-container { + height: 100%; +} diff --git a/nifi-registry-web-ui/src/main/platform/core/common/styles/_tables.scss b/nifi-registry-web-ui/src/main/platform/core/common/styles/_tables.scss new file mode 100644 index 000000000..0dcdade45 --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_tables.scss @@ -0,0 +1,113 @@ +/* + * 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. + */ + +/* Tables */ + +body[fds] .td-data-table-cell { + font-size: 13px; + color: $grey2; + padding: 0 28px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +body[fds] .td-data-table-column { + color: $grey3; + font-weight: normal; +} + +body[fds] .td-data-table-row { + height: 34px; + border-top: 1px solid #fff; + border-left: 1px solid #fff; + border-right: 1px solid #fff; + border-bottom: 1px solid $grey5; +} + +body[fds] .td-data-table-row.selected { + background-color: $grey5; + border: 1px solid $grey5; +} + +body[fds] .td-data-table-row:hover { + background-color: $grey6; + border: 1px solid $blue-grey2; +} + +body[fds] .td-data-table-cell .mat-icon-button { + color: $linkColor; +} + +body[fds] .td-data-table-cell .mat-button, body[fds] .td-data-table-cell .mat-icon-button, body[fds] .td-data-table-cell .mat-raised-button { + height: 24px; + width: 24px; + line-height: 0; +} + +body[fds] .td-data-table-cell .mat-icon-button.badge { + border-top-left-radius: 0px; + border-top-right-radius: 0px; +} + +body[fds] .td-data-table-cell .mat-icon-button.badge[disabled] { + opacity: .3; +} + +// body[fds] .td-data-table-cell .mat-button-focus-overlay, body[fds] .td-data-table-cell .mat-button-ripple { +// display: none; +// } + +body[fds] .td-data-table-column { + font-size: 12px; + color: $grey3; + height: 34px; + line-height: 34px; + padding: 0 28px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +body[fds] .td-data-table-column .fa-caret-up, body[fds] .td-data-table-column .fa-caret-down { + color: $blue-grey1; + font-size: 12px; + margin-bottom: 2px; +} + +body[fds] td-paging-bar { + color: $grey3; +} + +body[fds] td-paging-bar md-select .mat-select-value, body[fds] td-paging-bar md-select .mat-select-arrow { + color: $blue-grey1; +} + +body[fds] .table-title { + font-size: 20px; + color: $grey1; + min-width: 250px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 50%; + margin-right: 10px; +} + +body[fds] div .td-data-table { + border-bottom: 2px solid $grey7; +} diff --git a/nifi-registry-web-ui/src/main/platform/core/common/styles/_tabs.scss b/nifi-registry-web-ui/src/main/platform/core/common/styles/_tabs.scss new file mode 100644 index 000000000..df5d653a0 --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_tabs.scss @@ -0,0 +1,41 @@ +/* +* 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. +*/ + +/* Tabs */ + +body[fds] .mat-tab-label { + line-height: 72px; + text-transform: uppercase; + color: $grey2; +} + +body[fds] .mat-tab-label:hover:not([disabled]) { + color: $grey1; +} + +body[fds] .mat-tab-label:focus:not([disabled]) { + background-color: #FFFFFF; +} + +body[fds] .mat-tab-label-active { + color: $grey1; +} + +body[fds] .mat-tab-nav-bar, +body[fds] .mat-tab-header { + border-bottom: 0px; +} diff --git a/nifi-registry-web-ui/src/main/platform/core/common/styles/_tooltips.scss b/nifi-registry-web-ui/src/main/platform/core/common/styles/_tooltips.scss new file mode 100644 index 000000000..563565f91 --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/_tooltips.scss @@ -0,0 +1,24 @@ +/* +* 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. +*/ + +/* Tooltips */ + +body[fds] .mat-tooltip { + background: $grey2; + opacity: .9; + box-shadow: inset 0px 0px 3px 0px rgba(19, 145, 193, 1); +} diff --git a/nifi-registry-web-ui/src/main/platform/core/common/styles/fluid-design-system.scss b/nifi-registry-web-ui/src/main/platform/core/common/styles/fluid-design-system.scss new file mode 100644 index 000000000..0a29fe832 --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/common/styles/fluid-design-system.scss @@ -0,0 +1,55 @@ +/* + * 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 '../../../..//node_modules/@angular/material/theming'; +@import '../../../../node_modules/@covalent/core/theming/all-theme'; +@import 'globalVars'; +@import 'basicElements'; +@import 'helperClasses'; +@import 'buttons'; +@import 'buttonToggles'; +@import 'checkboxes'; +@import 'radios'; +@import 'chips'; +@import 'modals'; +@import 'tabs'; +@import 'inputs'; +@import 'panels'; +@import 'links'; +@import 'sideNav'; +@import 'tooltips'; +@import 'expansionPanels'; +@import 'menus'; +@import 'tables'; +@import '../../dialogs/fds-dialog-component'; +// Include the base styles for Angular Material core. We include this here so that you only +// have to load a single css file for Angular Material in your app. +@include mat-core; +// Define the palettes +$fds-base-palette: (50: #89df79, 100: $primaryColorHover, 200: #65d550, 300: #53d03b, 400: #46c32f, 500: $primaryColor, 600: $primaryColor, 700: #89df79, 800: #29701b, 900: #215c16, A100: #9be48d, A200: #ade9a2, A400: #bfedb6, A700: #1a4711, contrast: (50: $black-87-opacity, 100: $black-87-opacity, 200: $black-87-opacity, 300: white, 400: white, 500: $white-87-opacity, 600: $white-87-opacity, 700: $white-87-opacity, 800: $white-87-opacity, 900: $white-87-opacity, A100: $black-87-opacity, A200: white, A400: white, A700: $white-87-opacity)); +$fds-accent-palette: (50: #89df79, 100: $accentColorHover, 200: #65d550, 300: #53d03b, 400: #46c32f, 500: $accentColor, 600: $accentColor, 700: #89df79, 800: #29701b, 900: #215c16, A100: #9be48d, A200: #ade9a2, A400: #bfedb6, A700: #1a4711, contrast: (50: $black-87-opacity, 100: $black-87-opacity, 200: $black-87-opacity, 300: white, 400: white, 500: $white-87-opacity, 600: $white-87-opacity, 700: $white-87-opacity, 800: $white-87-opacity, 900: $white-87-opacity, A100: $black-87-opacity, A200: white, A400: white, A700: $white-87-opacity)); +$fds-warn-palette: (50: #81410f, 100: #D14A50, 200: #af5814, 300: #c66317, 400: #dd6f19, 500: $warnColor, 600: $warnColor, 700: #eea66e, 800: #f1b485, 900: #f4c29b, A100: #ec9857, A200: #89df79, A400: #89df79, A700: #f6d0b2, contrast: (50: $black-87-opacity, 100: $black-87-opacity, 200: $black-87-opacity, 300: white, 400: white, 500: $white-87-opacity, 600: $white-87-opacity, 700: $white-87-opacity, 800: $white-87-opacity, 900: $white-87-opacity, A100: $black-87-opacity, A200: white, A400: white, A700: $white-87-opacity)); +$fds-primary: mat-palette($fds-base-palette, 500, 100, 500); +$fds-accent: mat-palette($fds-accent-palette, 500, 100, 500); +$fds-warn: mat-palette($fds-warn-palette, 500, 100, 500); +// Optionally specify a default, lighter, and darker hue. +$fds-theme: mat-light-theme($fds-primary, $fds-accent, $fds-warn); +// Include theme styles for core and each component used in your app. +// Alternatively, you can import and @include the theme mixins for each component +// that you are using. +@include angular-material-theme($fds-theme); +@include covalent-theme($fds-theme); diff --git a/nifi-registry-web-ui/src/main/platform/core/dialogs/_fds-dialog-component.scss b/nifi-registry-web-ui/src/main/platform/core/dialogs/_fds-dialog-component.scss new file mode 100644 index 000000000..f8784a474 --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/dialogs/_fds-dialog-component.scss @@ -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. + */ + +.fds-dialog-title { + margin-top: 0; + margin-bottom: 20px; +} \ No newline at end of file diff --git a/nifi-registry-web-ui/src/main/platform/core/dialogs/confirm-dialog/confirm-dialog.component.html b/nifi-registry-web-ui/src/main/platform/core/dialogs/confirm-dialog/confirm-dialog.component.html new file mode 100644 index 000000000..101cd9ea3 --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/dialogs/confirm-dialog/confirm-dialog.component.html @@ -0,0 +1,45 @@ + + + + +
+ {{title}} + +
+
+ + {{message}} + + + + + +
\ No newline at end of file diff --git a/nifi-registry-web-ui/src/main/platform/core/dialogs/confirm-dialog/confirm-dialog.component.js b/nifi-registry-web-ui/src/main/platform/core/dialogs/confirm-dialog/confirm-dialog.component.js new file mode 100644 index 000000000..4236b1a9b --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/dialogs/confirm-dialog/confirm-dialog.component.js @@ -0,0 +1,64 @@ +/* + * 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. + */ + +var ngCore = require('@angular/core'); + +/** + * FdsConfirmDialogComponent constructor. + * + * @constructor + */ +function FdsConfirmDialogComponent() { + this.title = ''; + this.message = ''; + this.acceptButton = 'ACCEPT'; + this.acceptButtonColor = 'fds-primary'; + this.cancelButton = 'CANCEL'; + this.cancelButtonColor = 'fds-regular'; + this.dialogRef = undefined; + this.viewContainerRef = undefined; + this.disableClose = true; +}; + +FdsConfirmDialogComponent.prototype = { + constructor: FdsConfirmDialogComponent, + + /** + * Close the dialog and send a cancel response to any subscribers. + */ + cancel: function () { + this.dialogRef.close(false); + }, + + /** + * Close the dialog and send an accept response to any subscribers. + */ + accept: function () { + this.dialogRef.close(true); + } +}; + +FdsConfirmDialogComponent.annotations = [ + new ngCore.Component({ + selector: 'fds-confirm-dialog', + template: require('./confirm-dialog.component.html!text') + }) +]; + +FdsConfirmDialogComponent.parameters = []; + +module.exports = FdsConfirmDialogComponent; diff --git a/nifi-registry-web-ui/src/main/platform/core/dialogs/fds-dialog.component.html b/nifi-registry-web-ui/src/main/platform/core/dialogs/fds-dialog.component.html new file mode 100644 index 000000000..233bc647f --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/dialogs/fds-dialog.component.html @@ -0,0 +1,29 @@ + + +
+

+ +

+
+ +
+
+ + +
+
diff --git a/nifi-registry-web-ui/src/main/platform/core/dialogs/fds-dialog.component.js b/nifi-registry-web-ui/src/main/platform/core/dialogs/fds-dialog.component.js new file mode 100644 index 000000000..d71a2923a --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/dialogs/fds-dialog.component.js @@ -0,0 +1,82 @@ +/* + * 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. + */ + +var ngCore = require('@angular/core'); + +var FdsDialogTitleDirective = new ngCore.Class({ + extends: ngCore.Directive({selector: 'fds-dialog-title'}), + constructor: function () { + } +}); +var FdsDialogContentDirective = new ngCore.Class({ + extends: ngCore.Directive({selector: 'fds-dialog-content'}), + constructor: function () { + } +}); +var FdsDialogActionsDirective = new ngCore.Class({ + extends: ngCore.Directive({selector: 'fds-dialog-actions'}), + constructor: function () { + } +}); + +/** + * FdsDialogComponent constructor + * + * @constructor + */ +function FdsDialogComponent() { +}; + +FdsDialogComponent.prototype = { + constructor: FdsDialogComponent, + + /** + * Respond after Angular projects external content into the component's view. + */ + ngAfterContentInit: function () { + if (this.dialogTitle.length > 1) { + throw new Error('Duplicate fds-dialog-title component at in fds-dialog.'); + } + if (this.dialogContent.length > 1) { + throw new Error('Duplicate fds-dialog-content component at in fds-dialog.'); + } + if (this.dialogActions.length > 1) { + throw new Error('Duplicate fds-dialog-actions component at in fds-dialog.'); + } + } +} + +FdsDialogComponent.annotations = [ + new ngCore.Component({ + selector: 'fds-dialog', + template: require('./fds-dialog.component.html!text'), + queries: { + dialogTitle: new ngCore.ContentChildren(FdsDialogTitleDirective), + dialogContent: new ngCore.ContentChildren(FdsDialogContentDirective), + dialogActions: new ngCore.ContentChildren(FdsDialogActionsDirective) + } + }) +]; + +FdsDialogComponent.parameters = []; + +module.exports = { + FdsDialogTitleDirective: FdsDialogTitleDirective, + FdsDialogContentDirective: FdsDialogContentDirective, + FdsDialogActionsDirective: FdsDialogActionsDirective, + FdsDialogComponent: FdsDialogComponent +}; \ No newline at end of file diff --git a/nifi-registry-web-ui/src/main/platform/core/dialogs/fds-dialogs.module.js b/nifi-registry-web-ui/src/main/platform/core/dialogs/fds-dialogs.module.js new file mode 100644 index 000000000..3b9b6103e --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/dialogs/fds-dialogs.module.js @@ -0,0 +1,87 @@ +/* + * 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. + */ + +var ngCore = require('@angular/core'); +var ngMaterial = require('@angular/material'); +var ngFlex = require('@angular/flex-layout'); +var ngCommon = require('@angular/common'); +var ngForms = require('@angular/forms'); +var fdsDialogComponentModule = require('@fluid-design-system/dialog-component'); +var fdsDialogServiceModule = require('@fluid-design-system/dialog-service'); +var FdsConfirmDialogComponent = require('@fluid-design-system/confirm-dialog-component'); + +var FDS_DIALOGS = [ + fdsDialogComponentModule.FdsDialogComponent, + fdsDialogComponentModule.FdsDialogTitleDirective, + fdsDialogComponentModule.FdsDialogActionsDirective, + fdsDialogComponentModule.FdsDialogContentDirective, + FdsConfirmDialogComponent +]; + +var FDS_DIALOGS_ENTRY_COMPONENTS = [ + FdsConfirmDialogComponent +]; + +/** + * FdsDialogsModule constructor. + * + * @constructor + */ +function FdsDialogsModule() { + +}; + +FdsDialogsModule.prototype = { + constructor: FdsDialogsModule +}; + +FdsDialogsModule.annotations = [ + new ngCore.NgModule({ + imports: [ + ngFlex.FlexLayoutModule, + ngForms.FormsModule, + ngCommon.CommonModule, + ngMaterial.MdDialogModule, + ngMaterial.MdInputModule, + ngMaterial.MdButtonModule, + ngMaterial.MdIconModule + ], + declarations: [ + FDS_DIALOGS + ], + exports: [ + FDS_DIALOGS + ], + providers: [ + fdsDialogServiceModule.FdsDialogService + ], + entryComponents: [ + FDS_DIALOGS_ENTRY_COMPONENTS + ] + }) +]; + +module.exports = { + FdsDialogsModule: FdsDialogsModule, + IConfirmConfig: fdsDialogServiceModule.IConfirmConfig, + FdsDialogService: fdsDialogServiceModule.FdsDialogService, + FdsDialogComponent: fdsDialogComponentModule.FdsDialogComponent, + FdsDialogTitleDirective: fdsDialogComponentModule.FdsDialogTitleDirective, + FdsDialogContentDirective: fdsDialogComponentModule.FdsDialogContentDirective, + FdsDialogActionsDirective: fdsDialogComponentModule.FdsDialogActionsDirective, + FdsConfirmDialogComponent: FdsConfirmDialogComponent +}; diff --git a/nifi-registry-web-ui/src/main/platform/core/dialogs/services/dialog.service.js b/nifi-registry-web-ui/src/main/platform/core/dialogs/services/dialog.service.js new file mode 100644 index 000000000..06ecf43dd --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/dialogs/services/dialog.service.js @@ -0,0 +1,130 @@ +/* + * 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. + */ + +var ngCore = require('@angular/core'); +var ngMaterial = require('@angular/material'); +var FdsConfirmDialogComponent = require('@fluid-design-system/confirm-dialog-component'); + +var IDialogConfig = new ngCore.Class({ + extends: ngMaterial.MdDialogConfig, + constructor: function () { + this.title = ''; + this.message = ''; + this.dialogRef = undefined; + this.viewContainerRef = undefined; + this.disableClose = true; + } +}); + +var IConfirmConfig = new ngCore.Class({ + extends: IDialogConfig, + constructor: function () { + this.acceptButton = 'ACCEPT'; + this.acceptButtonColor = 'fds-primary'; + this.cancelButton = 'CANCEL'; + this.cancelButtonColor = 'fds-secondary'; + } +}); + +function createConfig(config) { + var dialogConfig = new IConfirmConfig(); + dialogConfig.viewContainerRef = config.viewContainerRef; + dialogConfig.disableClose = config.disableClose; + return dialogConfig; +} + +/** + * FdsDialogService constructor. + * + * @param MdDialog The angular material MdDialog. + * @constructor + */ +function FdsDialogService(MdDialog) { + this.dialogService = MdDialog; +} + +FdsDialogService.prototype = { + contstructor: FdsDialogService, + + /** + * Wrapper function over the open() method in MdDialog. + * Opens a modal dialog containing the given component. + * + * @param component The angular ComponentType. + * @param config The angular material MdDialogConfig. + * + */ + open: function (component, config) { + return this.dialogService.open(component, config); + }, + + /** + * Wrapper function over the closeAll() method in MdDialog. + * Closes all of the currently-open dialogs. + */ + closeAll: function () { + this.dialogService.closeAll(); + }, + + /** + * Opens a confirm dialog with the provided config. + * Returns an MdDialogRef object. + * + * @param config IConfirmConfig { + * message: string; + * title?: string; + * viewContainerRef?: ViewContainerRef; + * acceptButton?: string; + * acceptButtonColor?: string; + * cancelButton?: string; + * cancelButtonColor?: string; + * } + */ + openConfirm: function (config) { + var dialogConfig = createConfig(config); + var dialogRef = this.dialogService.open(FdsConfirmDialogComponent, dialogConfig); + var confirmDialogComponent = dialogRef.componentInstance; + confirmDialogComponent.dialogRef = dialogRef; + if (config.title) { + confirmDialogComponent.title = config.title; + } + if (config.message) { + confirmDialogComponent.message = config.message; + } + if (config.acceptButton) { + confirmDialogComponent.acceptButton = config.acceptButton; + } + if (config.acceptButtonColor) { + confirmDialogComponent.acceptButtonColor = config.acceptButtonColor; + } + if (config.cancelButton) { + confirmDialogComponent.cancelButton = config.cancelButton; + } + if (config.cancelButtonColor) { + confirmDialogComponent.cancelButtonColor = config.cancelButtonColor; + } + return dialogRef; + }, +} + +FdsDialogService.parameters = [ngMaterial.MdDialog]; + +module.exports = { + IDialogConfig: IDialogConfig, + IConfirmConfig: IConfirmConfig, + FdsDialogService: FdsDialogService +}; \ No newline at end of file diff --git a/nifi-registry-web-ui/src/main/platform/core/fluid-design-system.module.js b/nifi-registry-web-ui/src/main/platform/core/fluid-design-system.module.js new file mode 100644 index 000000000..46cf881c9 --- /dev/null +++ b/nifi-registry-web-ui/src/main/platform/core/fluid-design-system.module.js @@ -0,0 +1,99 @@ +/* + * 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. + */ + +var $ = require('jquery'); +var ngCore = require('@angular/core'); +var ngFlex = require('@angular/flex-layout'); +var ngMaterial = require('@angular/material'); +var ngCommon = require('@angular/common'); +var ngHttp = require('@angular/http'); +var ngPlatformBrowser = require('@angular/platform-browser'); +var ngAnimations = require('@angular/platform-browser/animations'); +var covalentCore = require('@covalent/core'); +var fdsDialogsModule = require('@fluid-design-system/dialogs'); + +/** + * FluidDesignSystemModule constructor. + * + * @constructor + */ +function FluidDesignSystemModule() { + $(document).ready(function () { + //add fds attr to body tag to allow fine grain style overrides + document.body.setAttribute('fds', ''); + + //override the hover styles for checkbox borders + $(document.body).on('mouseenter', '.mat-checkbox-inner-container', function () { + $(this).find('.mat-checkbox-frame').css('border-color', '#1491C1'); + }); + $(document.body).on('mouseleave', '.mat-checkbox-inner-container', function () { + $(this).find('.mat-checkbox-frame').css('border-color', '#DDDDDD'); + }); + }); +}; + +FluidDesignSystemModule.prototype = { + constructor: FluidDesignSystemModule +}; + +FluidDesignSystemModule.annotations = [ + new ngCore.NgModule({ + imports: [ + ngFlex.FlexLayoutModule, + ngAnimations.BrowserAnimationsModule, + ngCommon.CommonModule, + ngPlatformBrowser.BrowserModule, + ngHttp.HttpModule, + ngHttp.JsonpModule, + ngMaterial.MaterialModule, + covalentCore.CovalentCommonModule, + covalentCore.CovalentChipsModule, + covalentCore.CovalentDataTableModule, + covalentCore.CovalentDialogsModule, + fdsDialogsModule.FdsDialogsModule, + covalentCore.CovalentExpansionPanelModule, + covalentCore.CovalentLoadingModule, + covalentCore.CovalentMenuModule, + covalentCore.CovalentNotificationsModule, + covalentCore.CovalentPagingModule, + covalentCore.CovalentSearchModule, + covalentCore.CovalentStepsModule + ], + exports: [ + ngFlex.FlexLayoutModule, + ngAnimations.BrowserAnimationsModule, + ngCommon.CommonModule, + ngPlatformBrowser.BrowserModule, + ngHttp.HttpModule, + ngHttp.JsonpModule, + ngMaterial.MaterialModule, + covalentCore.CovalentCommonModule, + covalentCore.CovalentChipsModule, + covalentCore.CovalentDataTableModule, + covalentCore.CovalentDialogsModule, + fdsDialogsModule.FdsDialogsModule, + covalentCore.CovalentExpansionPanelModule, + covalentCore.CovalentLoadingModule, + covalentCore.CovalentMenuModule, + covalentCore.CovalentNotificationsModule, + covalentCore.CovalentPagingModule, + covalentCore.CovalentSearchModule, + covalentCore.CovalentStepsModule + ] + }) +]; +module.exports = FluidDesignSystemModule; \ No newline at end of file diff --git a/nifi-registry-web-ui/src/main/resources/filters/registry-min.properties b/nifi-registry-web-ui/src/main/resources/filters/registry-min.properties new file mode 100644 index 000000000..b0b7a2605 --- /dev/null +++ b/nifi-registry-web-ui/src/main/resources/filters/registry-min.properties @@ -0,0 +1,19 @@ +# 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. + +nf.registry.script.tags= +nf.registry.style.tags=\n\ +\n\ + \ No newline at end of file diff --git a/nifi-registry-web-ui/src/main/resources/filters/registry.properties b/nifi-registry-web-ui/src/main/resources/filters/registry.properties new file mode 100644 index 000000000..60ce777d6 --- /dev/null +++ b/nifi-registry-web-ui/src/main/resources/filters/registry.properties @@ -0,0 +1,23 @@ +# 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. + +nf.registry.script.tags=\n\ + +nf.registry.style.tags=\n\ +\n\ + \ No newline at end of file diff --git a/nifi-registry-web-ui/src/main/webapp/WEB-INF/pages/index.jsp b/nifi-registry-web-ui/src/main/webapp/WEB-INF/pages/index.jsp index c78f06a5b..0e8a950fd 100644 --- a/nifi-registry-web-ui/src/main/webapp/WEB-INF/pages/index.jsp +++ b/nifi-registry-web-ui/src/main/webapp/WEB-INF/pages/index.jsp @@ -17,14 +17,19 @@ <%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %> - - NiFi Registry - - - - -
-

NiFi Registry

-
- + + NiFi Registry + + + + + + + ${nf.registry.style.tags} + + + + + +${nf.registry.script.tags} \ No newline at end of file diff --git a/nifi-registry-web-ui/src/main/webapp/WEB-INF/web.xml b/nifi-registry-web-ui/src/main/webapp/WEB-INF/web.xml index 442b4b3cd..2be7ffff3 100644 --- a/nifi-registry-web-ui/src/main/webapp/WEB-INF/web.xml +++ b/nifi-registry-web-ui/src/main/webapp/WEB-INF/web.xml @@ -16,17 +16,38 @@ nifi-registry - + - index + FluidDesignSystem /WEB-INF/pages/index.jsp - index - /index + FluidDesignSystem + /fluid-design-system + + + + + Administration + /WEB-INF/pages/index.jsp + + + Administration + /administration/* + + + + + Explorer + /WEB-INF/pages/index.jsp + + + Explorer + /explorer/* + index.jsp /WEB-INF/pages/index.jsp diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/general/nf-registry-general-administration.html b/nifi-registry-web-ui/src/main/webapp/components/administration/general/nf-registry-general-administration.html new file mode 100644 index 000000000..4246cab0b --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/administration/general/nf-registry-general-administration.html @@ -0,0 +1,30 @@ + + +
+
+ Settings +
+ + + + +
+
+
+ diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/general/nf-registry-general-administration.js b/nifi-registry-web-ui/src/main/webapp/components/administration/general/nf-registry-general-administration.js new file mode 100644 index 000000000..bdf9d51ed --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/administration/general/nf-registry-general-administration.js @@ -0,0 +1,61 @@ +/* + * 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. + */ +var ngCore = require('@angular/core'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var nfRegistryAnimations = require('nifi-registry/nf-registry.animations.js'); + +/** + * NfRegistryGeneralAdministration constructor + * + * @param nfRegistryService The nf-registry.service module. + * @constructor + */ +function NfRegistryGeneralAdministration(nfRegistryService) { + this.nfRegistryService = nfRegistryService; +}; + +NfRegistryGeneralAdministration.prototype = { + constructor: NfRegistryGeneralAdministration, + + /** + * Initialize the component. + */ + ngOnInit: function () { + this.nfRegistryService.adminPerspective = 'general'; + }, + + /** + * Destroy the component. + */ + ngOnDestroy: function () { + this.nfRegistryService.adminPerspective = ''; + } +}; + +NfRegistryGeneralAdministration.annotations = [ + new ngCore.Component({ + template: require('./nf-registry-general-administration.html!text'), + animations: [nfRegistryAnimations.slideInLeftAnimation], + host: { + '[@routeAnimation]': 'routeAnimation' + } + }) +]; + +NfRegistryGeneralAdministration.parameters = [NfRegistryService]; + +module.exports = NfRegistryGeneralAdministration; diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.html b/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.html new file mode 100644 index 000000000..8770fade0 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.html @@ -0,0 +1,39 @@ + + +
+ + + general + + + Users + + + Workflow + + +
+ diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.js b/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.js new file mode 100644 index 000000000..6bf1a6bed --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.js @@ -0,0 +1,84 @@ +/* + * 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. + */ +var ngCore = require('@angular/core'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var nfRegistryAnimations = require('nifi-registry/nf-registry.animations.js'); +var ngRouter = require('@angular/router'); + +/** + * NfRegistryAdministration constructor. + * + * @param nfRegistryService The nf-registry.service module. + * @param ActivatedRoute The angular activated route module. + * @constructor + */ +function NfRegistryAdministration(nfRegistryService, ActivatedRoute) { + this.route = ActivatedRoute; + this.nfRegistryService = nfRegistryService; +}; + +NfRegistryAdministration.prototype = { + constructor: NfRegistryAdministration, + + /** + * Initialize the component. + */ + ngOnInit: function () { + var self = this; + this.nfRegistryService.perspective = 'administration'; + this.route.params + .switchMap(function (params) { + self.nfRegistryService.setBreadcrumbState('out'); + return self.nfRegistryService.getRegistry(params['registryId']); + }) + .subscribe(function (registry) { + self.nfRegistryService.registry = registry; + self.nfRegistryService.setBreadcrumbState('in'); + }); + }, + + /** + * Destroy the component. + */ + ngOnDestroy: function () { + this.nfRegistryService.perspective = ''; + this.nfRegistryService.registry = {}; + }, + + /** + * Navigate to administer the registry. + * + * @param id The registry id.. + */ + navigateToAdministration: function (id) { + this.route.navigateByUrl('nifi-registry/administration/' + id); + } +}; + +NfRegistryAdministration.annotations = [ + new ngCore.Component({ + template: require('./nf-registry-administration.html!text'), + animations: [nfRegistryAnimations.slideInLeftAnimation], + host: { + '[@routeAnimation]': 'routeAnimation' + } + }) +]; + +NfRegistryAdministration.parameters = [NfRegistryService, ngRouter.ActivatedRoute]; + +module.exports = NfRegistryAdministration; diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.spec.js b/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.spec.js new file mode 100644 index 000000000..91a2da2a8 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/administration/nf-registry-administration.spec.js @@ -0,0 +1,152 @@ +/* + * 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. + */ + +var NfRegistryRoutes = require('nifi-registry/nf-registry.routes.js'); +var ngCoreTesting = require('@angular/core/testing'); +var ngCommon = require('@angular/common'); +var ngRouter = require('@angular/router'); +var ngPlatformBrowser = require('@angular/platform-browser'); +var FdsDemo = require('nifi-registry/components/fluid-design-system/fds-demo.js'); +var NfRegistry = require('nifi-registry/nf-registry.js'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var NfPageNotFoundComponent = require('nifi-registry/components/page-not-found/nf-registry-page-not-found.js'); +var NfRegistryExplorer = require('nifi-registry/components/explorer/nf-registry-explorer.js'); +var NfRegistryExplorerGridListViewer = require('nifi-registry/components/explorer/grid-list/nf-registry-explorer-grid-list-viewer.js'); +var NfRegistryAdministration = require('nifi-registry/components/administration/nf-registry-administration.js'); +var NfRegistryGeneralAdministration = require('nifi-registry/components/administration/general/nf-registry-general-administration.js'); +var NfRegistryUsersAdministration = require('nifi-registry/components/administration/users/nf-registry-users-administration.js'); +var NfRegistryAddUser = require('nifi-registry/components/administration/users/add/nf-registry-add-user.js'); +var NfRegistryUserDetails = require('nifi-registry/components/administration/users/details/nf-registry-user-details.js'); +var NfRegistryUserPermissions = require('nifi-registry/components/administration/users/permissions/nf-registry-user-permissions.js'); +var NfRegistryBucketDetails = require('nifi-registry/components/administration/workflow/buckets/details/nf-registry-bucket-details.js'); +var NfRegistryBucketPermissions = require('nifi-registry/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js'); +var NfRegistryWorkflowAdministration = require('nifi-registry/components/administration/workflow/nf-registry-workflow-administration.js'); +var NfRegistryGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.js'); +var NfRegistryBucketGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/bucket/nf-registry-bucket-grid-list-viewer.js'); +var NfRegistryDropletGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/bucket/droplet/nf-registry-droplet-grid-list-viewer.js'); +var fdsCore = require('@fluid-design-system/core'); +var rxjs = require('rxjs/Rx'); + +describe('NfRegistryAdministration Component', function () { + var comp; + var fixture; + var de; + var el; + var nfRegistryService; + var originalTimeout; + + function ActivatedRouteStub() { + this._testParamMap = ngRouter.ParamMap; + this.subject = new rxjs.BehaviorSubject(ngRouter.convertToParamMap(this.testParamMap)); + this.paramMap = this.subject.asObservable(); + + this.params = { + switchMap: function () { + return Observable.of({ + id: '1234', + name: "Test Registry", + certifications: [], + users: [], + buckets: [] + }); + } + }; + }; + + ActivatedRouteStub.prototype = { + constructor: ActivatedRouteStub, + navigateByUrl: function (url) { + return url; + } + }; + + Object.defineProperty(ActivatedRouteStub.prototype, "testParamMap", { + get: function () { + return this._testParamMap; + }, + set: function (params) { + this._testParamMap = ngRouter.convertToParamMap(params); + this.subject.next(this._testParamMap); + } + }); + + beforeEach(function () { + originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; + jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; + }); + + afterEach(function () { + jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout; + }); + + beforeEach(ngCoreTesting.async(function () { + ngCoreTesting.TestBed.configureTestingModule({ + imports: [ + fdsCore, + NfRegistryRoutes + ], + declarations: [FdsDemo, NfRegistry, NfRegistryExplorer, NfRegistryExplorerGridListViewer, NfRegistryAdministration, NfRegistryGeneralAdministration, NfRegistryUsersAdministration, NfRegistryUserDetails, NfRegistryUserPermissions, NfRegistryBucketDetails, NfRegistryBucketPermissions, NfRegistryAddUser, NfRegistryWorkflowAdministration, NfRegistryGridListViewer, NfRegistryBucketGridListViewer, NfRegistryDropletGridListViewer, NfPageNotFoundComponent], + providers: [NfRegistryService, { + provide: ngCommon.APP_BASE_HREF, + useValue: '/' + }, {provide: ngRouter.ActivatedRoute, useClass: ActivatedRouteStub}] + }); + })); + + beforeEach(function () { + fixture = ngCoreTesting.TestBed.createComponent(NfRegistryAdministration); + + // NfRegistryAdministration test instance + comp = fixture.componentInstance; + + // NfRegistryService from the root injector + nfRegistryService = ngCoreTesting.TestBed.get(NfRegistryService); + // spyOn(nfRegistryService, 'getRegistries').and.returnValue(Promise.resolve([{ + // id: '1234', + // name: "Test Registry", + // certifications: [], + // users: [], + // buckets: [] + // }])); + + de = fixture.debugElement.query(ngPlatformBrowser.By.css('#nifi-registry-administration-perspective')); + el = de.nativeElement; + }); + + it('should have a defined component', function () { + fixture.detectChanges(); + expect(comp).toBeDefined(); + expect(de).toBeDefined(); + }); + + it('should call Router.navigateByUrl("nifi-registry/administration/:registryId") with the ID of the registry', ngCoreTesting.inject([ngRouter.ActivatedRoute], function (router) { + fixture.detectChanges(); + var spy = spyOn(router, 'navigateByUrl'); + comp.navigateToAdministration('23f6cc59-0156-1000-06b4-2b0810089090'); + var url = spy.calls.first().args[0]; + expect(url).toBe('nifi-registry/administration/23f6cc59-0156-1000-06b4-2b0810089090'); + })); + + xit('should call `NfRegistryService.getRegistry` when the route ID changes', ngCoreTesting.inject([ngRouter.ActivatedRoute], function (activeRoute) { + spyOn(nfRegistryService, 'getRegistry'); + activeRoute.testParamMap = {registryId: 1234}; + fixture = ngCoreTesting.TestBed.createComponent(NfRegistryAdministration); + comp = fixture.componentInstance; // NfRegistryAdministration test instance + fixture.detectChanges(); + expect(nfRegistryService.getRegistry).toHaveBeenCalledWith(1234); + })); +}); \ No newline at end of file diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/users/add/nf-registry-add-user.html b/nifi-registry-web-ui/src/main/webapp/components/administration/users/add/nf-registry-add-user.html new file mode 100644 index 000000000..6cdf6314f --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/administration/users/add/nf-registry-add-user.html @@ -0,0 +1,28 @@ + + +
+
+ Add User + +
+ +
diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/users/add/nf-registry-add-user.js b/nifi-registry-web-ui/src/main/webapp/components/administration/users/add/nf-registry-add-user.js new file mode 100644 index 000000000..2cbeb3bec --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/administration/users/add/nf-registry-add-user.js @@ -0,0 +1,66 @@ +/* + * 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. + */ +var ngCore = require('@angular/core'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var ngRouter = require('@angular/router'); + +/** + * NfRegistryAddUser constructor. + * + * @param nfRegistryService The nf-registry.service module. + * @param Router The angular router module. + * @constructor + */ +function NfRegistryAddUser(nfRegistryService, Router) { + this.nfRegistryService = nfRegistryService; + this.router = Router; +}; + +NfRegistryAddUser.prototype = { + constructor: NfRegistryAddUser, + + /** + * Initialize the component. + */ + ngOnInit: function () { + this.nfRegistryService.sidenav.open(); + }, + + /** + * Destroy the component. + */ + ngOnDestroy: function () { + this.nfRegistryService.sidenav.close(); + }, + + /** + * Navigate to administer users for current registry. + */ + closeSideNav: function () { + this.router.navigateByUrl('/nifi-registry/administration/' + this.nfRegistryService.registry.id + '/users'); + } +}; + +NfRegistryAddUser.annotations = [ + new ngCore.Component({ + template: require('./nf-registry-add-user.html!text') + }) +]; + +NfRegistryAddUser.parameters = [NfRegistryService, ngRouter.Router]; + +module.exports = NfRegistryAddUser; diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/users/details/nf-registry-user-details.html b/nifi-registry-web-ui/src/main/webapp/components/administration/users/details/nf-registry-user-details.html new file mode 100644 index 000000000..49dd37e5e --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/administration/users/details/nf-registry-user-details.html @@ -0,0 +1,28 @@ + + +
+
+ User Details + +
+ +
diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/users/details/nf-registry-user-details.js b/nifi-registry-web-ui/src/main/webapp/components/administration/users/details/nf-registry-user-details.js new file mode 100644 index 000000000..500158693 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/administration/users/details/nf-registry-user-details.js @@ -0,0 +1,66 @@ +/* + * 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. + */ +var ngCore = require('@angular/core'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var ngRouter = require('@angular/router'); + +/** + * NfRegistryUserDetails constructor. + * + * @param nfRegistryService The nf-registry.service module. + * @param Router The angular router module. + * @constructor + */ +function NfRegistryUserDetails(nfRegistryService, Router) { + this.nfRegistryService = nfRegistryService; + this.router = Router; +}; + +NfRegistryUserDetails.prototype = { + constructor: NfRegistryUserDetails, + + /** + * Initialize the component. + */ + ngOnInit: function () { + this.nfRegistryService.sidenav.open(); + }, + + /** + * Destroy the component. + */ + ngOnDestroy: function () { + this.nfRegistryService.sidenav.close(); + }, + + /** + * Navigate to administer users for current registry. + */ + closeSideNav: function () { + this.router.navigateByUrl('/nifi-registry/administration/' + this.nfRegistryService.registry.id + '/users'); + } +}; + +NfRegistryUserDetails.annotations = [ + new ngCore.Component({ + template: require('./nf-registry-user-details.html!text') + }) +]; + +NfRegistryUserDetails.parameters = [NfRegistryService, ngRouter.Router]; + +module.exports = NfRegistryUserDetails; diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.html b/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.html new file mode 100644 index 000000000..4dd9055c2 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.html @@ -0,0 +1,122 @@ + + +
+
+ Authorized Users ({{usersPagingBar.range}}) of {{usersPagingBar.total}} +
+ + + +
+ + + +
+
+
+
+ {{column.label}} + + +
+
+
+ +
+
+
+
+
+
+
+ {{column.format ? column.format(row[column.name]) : row[column.name]}} +
+
+ +
+
+
+
+
+ + +
+
+ + + + + +
+
+
+ +
+
+
+
+
+

No results to display.

+
+ + Row per page: + +
+
+ diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.js b/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.js new file mode 100644 index 000000000..272df0cfc --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/administration/users/nf-registry-users-administration.js @@ -0,0 +1,128 @@ +/* + * 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. + */ +var ngCore = require('@angular/core'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var ngRouter = require('@angular/router'); +var nfRegistryAnimations = require('nifi-registry/nf-registry.animations.js'); +var fdsDialogsModule = require('@fluid-design-system/dialogs'); + +/** + * NfRegistryUsersAdministration constructor. + * + * @param nfRegistryService The nf-registry.service module. + * @param ActivatedRoute The angular activated route module. + * @param Router The angular router module. + * @param FdsDialogService The FDS dialog service. + * @constructor + */ +function NfRegistryUsersAdministration(nfRegistryService, ActivatedRoute, Router, FdsDialogService) { + this.route = ActivatedRoute; + this.nfRegistryService = nfRegistryService; + this.router = Router; + this.dialogService = FdsDialogService; +}; + +NfRegistryUsersAdministration.prototype = { + constructor: NfRegistryUsersAdministration, + + /** + * Initialize the component. + */ + ngOnInit: function () { + var self = this; + this.route.params + .switchMap(function (params) { + self.nfRegistryService.adminPerspective = 'users'; + return self.nfRegistryService.getUsers(self.nfRegistryService.registry.id); + }) + .subscribe(function (users) { + self.nfRegistryService.users = self.nfRegistryService.filteredUsers = users; + self.nfRegistryService.filterUsers(); + }); + }, + + /** + * Destroy the component. + */ + ngOnDestroy: function () { + this.nfRegistryService.adminPerspective = ''; + this.nfRegistryService.users = this.nfRegistryService.filteredUsers = []; + }, + + /** + * Execute the given user action. + * + * @param action The action object. + * @param user The user object the `action` will act upon. + */ + execute: function (action, user) { + var self = this; + if (user) { + user.checked = !user.checked; + } + switch (action.name.toLowerCase()) { + case 'delete': + this.dialogService.openConfirm({ + title: 'Delete User', + message: 'User will be deleted.', + cancelButton: 'Cancel', + acceptButton: 'Delete', + acceptButtonColor: 'fds-warn' + }).afterClosed().subscribe( + function (accept) { + if (accept) { + self.nfRegistryService.deleteUser(user.id); + } + }); + break; + case 'suspend': + this.dialogService.openConfirm({ + title: 'Suspend User', + message: 'User permissions will be suspended.', + cancelButton: 'Cancel', + acceptButton: 'Confirm', + acceptButtonColor: 'fds-critical' + }).afterClosed().subscribe( + function (accept) { + if (accept) { + self.nfRegistryService.suspendUser(user.id); + } + }); + break; + case 'add': + this.router.navigateByUrl('/nifi-registry/administration/' + this.nfRegistryService.registry.id + '/users(sidenav:user/add)'); + break; + default: + this.router.navigateByUrl('/nifi-registry/administration/' + this.nfRegistryService.registry.id + '/users(' + action.type + ':user/' + action.name + '/' + user.id + ')'); + break; + } + } +}; + +NfRegistryUsersAdministration.annotations = [ + new ngCore.Component({ + template: require('./nf-registry-users-administration.html!text'), + animations: [nfRegistryAnimations.slideInLeftAnimation], + host: { + '[@routeAnimation]': 'routeAnimation' + } + }) +]; + +NfRegistryUsersAdministration.parameters = [NfRegistryService, ngRouter.ActivatedRoute, ngRouter.Router, fdsDialogsModule.FdsDialogService]; + +module.exports = NfRegistryUsersAdministration; diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/users/permissions/nf-registry-user-permissions.html b/nifi-registry-web-ui/src/main/webapp/components/administration/users/permissions/nf-registry-user-permissions.html new file mode 100644 index 000000000..155482167 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/administration/users/permissions/nf-registry-user-permissions.html @@ -0,0 +1,28 @@ + + +
+
+ User Permissions + +
+ +
diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/users/permissions/nf-registry-user-permissions.js b/nifi-registry-web-ui/src/main/webapp/components/administration/users/permissions/nf-registry-user-permissions.js new file mode 100644 index 000000000..056940994 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/administration/users/permissions/nf-registry-user-permissions.js @@ -0,0 +1,66 @@ +/* + * 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. + */ +var ngCore = require('@angular/core'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var ngRouter = require('@angular/router'); + +/** + * NfRegistryUserPermissions constructor. + * + * @param nfRegistryService The nf-registry.service module. + * @param Router The angular router module. + * @constructor + */ +function NfRegistryUserPermissions(nfRegistryService, Router) { + this.nfRegistryService = nfRegistryService; + this.router = Router; +}; + +NfRegistryUserPermissions.prototype = { + constructor: NfRegistryUserPermissions, + + /** + * Initialize the component. + */ + ngOnInit: function () { + this.nfRegistryService.sidenav.open(); + }, + + /** + * Destroy the component. + */ + ngOnDestroy: function () { + this.nfRegistryService.sidenav.close(); + }, + + /** + * Navigate to administer users for current registry. + */ + closeSideNav: function () { + this.router.navigateByUrl('/nifi-registry/administration/' + this.nfRegistryService.registry.id + '/users'); + } +}; + +NfRegistryUserPermissions.annotations = [ + new ngCore.Component({ + template: require('./nf-registry-user-permissions.html!text') + }) +]; + +NfRegistryUserPermissions.parameters = [NfRegistryService, ngRouter.Router]; + +module.exports = NfRegistryUserPermissions; diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.html b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.html new file mode 100644 index 000000000..ff6bbddc6 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.html @@ -0,0 +1,28 @@ + + +
+
+ {{nfRegistryService.bucket.name}} + +
+ +
diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js new file mode 100644 index 000000000..98c5b0f18 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js @@ -0,0 +1,77 @@ +/* + * 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. + */ +var ngCore = require('@angular/core'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var ngRouter = require('@angular/router'); + +/** + * NfRegistryBucketPermissions constructor. + * + * @param nfRegistryService The nf-registry.service module. + * @param ActivatedRoute The angular activated route module. + * @param Router The angular router module. + * @constructor + */ +function NfRegistryBucketPermissions(nfRegistryService, ActivatedRoute, Router) { + this.nfRegistryService = nfRegistryService; + this.route = ActivatedRoute; + this.router = Router; +}; + +NfRegistryBucketPermissions.prototype = { + constructor: NfRegistryBucketPermissions, + + /** + * Initialize the component. + */ + ngOnInit: function () { + var self = this; + this.nfRegistryService.sidenav.open(); + this.route.params + .switchMap(function (params) { + return self.nfRegistryService.getBucket(self.nfRegistryService.registry.id, params['bucketId']); + }) + .subscribe(function (bucket) { + self.nfRegistryService.bucket = bucket; + }); + }, + + /** + * Destroy the component. + */ + ngOnDestroy: function () { + this.nfRegistryService.sidenav.close(); + this.nfRegistryService.bucket = {}; + }, + + /** + * Navigate to administer the buckets of the current registry. + */ + closeSideNav: function () { + this.router.navigateByUrl('/nifi-registry/administration/' + this.nfRegistryService.registry.id + '/workflow'); + } +}; + +NfRegistryBucketPermissions.annotations = [ + new ngCore.Component({ + template: require('./nf-registry-bucket-permissions.html!text') + }) +]; + +NfRegistryBucketPermissions.parameters = [NfRegistryService, ngRouter.ActivatedRoute, ngRouter.Router]; + +module.exports = NfRegistryBucketPermissions; diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.html b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.html new file mode 100644 index 000000000..a00c41916 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.html @@ -0,0 +1,170 @@ + + +
+
+ Buckets ({{nfRegistryService.buckets.length}}) +
+ + + + +
+
+
+ {{column.label}} + + +
+
+
+
+
+
+
+ {{column.format ? column.format(row[column.name]) : row[column.name]}} +
+
+
+
+
+ + +
+
+ + + + + +
+
+
+ +
+
+
+
+
+
+
+
+ Certifications ({{nfRegistryService.certifications.length}}) +
+ + + + +
+
+
+ {{column.label}} + + +
+
+
+
+
+
+
+ {{column.format ? column.format(row[column.name]) : row[column.name]}} +
+
+ + + ON + + + OFF + + +
+
+ +
+
+
+
+
+ +
+
+ + + + +
+
+
+
+
+
+
+ diff --git a/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.js b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.js new file mode 100644 index 000000000..eb64298d4 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/administration/workflow/nf-registry-workflow-administration.js @@ -0,0 +1,121 @@ +/* + * 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. + */ +var ngCore = require('@angular/core'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var ngRouter = require('@angular/router'); +var nfRegistryAnimations = require('nifi-registry/nf-registry.animations.js'); +var fdsDialogsModule = require('@fluid-design-system/dialogs'); + +/** + * NfRegistryWorkflowAdministration constructor. + * + * @param nfRegistryService The nf-registry.service module. + * @param ActivatedRoute The angular activated route module. + * @param Router The angular router module. + * @param FdsDialogService The FDS dialog service. + * @constructor + */ +function NfRegistryWorkflowAdministration(nfRegistryService, ActivatedRoute, Router, FdsDialogService) { + this.route = ActivatedRoute; + this.nfRegistryService = nfRegistryService; + this.router = Router; + this.dialogService = FdsDialogService; +}; + +NfRegistryWorkflowAdministration.prototype = { + constructor: NfRegistryWorkflowAdministration, + + /** + * Initialize the component. + */ + ngOnInit: function () { + var self = this; + this.route.params + .subscribe(function () { + self.nfRegistryService.adminPerspective = 'workflow'; + // TODO: implement certifications + // self.nfRegistryService.getCertifications(self.nfRegistryService.registry.id).then(function(certifications) { + // self.nfRegistryService.certifications = self.nfRegistryService.filteredCertifications = certifications; + // self.nfRegistryService.filterCertifications(); + // }); + + self.nfRegistryService.getBuckets(self.nfRegistryService.registry.id).then(function (buckets) { + self.nfRegistryService.buckets = self.nfRegistryService.filteredBuckets = buckets; + self.nfRegistryService.filterBuckets(); + }); + + }); + + }, + + /** + * Destroy the component. + */ + ngOnDestroy: function () { + this.nfRegistryService.adminPerspective = ''; + this.nfRegistryService.certifications = this.nfRegistryService.filteredCertifications = []; + this.nfRegistryService.buckets = []; + this.nfRegistryService.filteredBuckets = []; + this.autoCompleteBuckets = []; + }, + + /** + * Execute the given bucket action. + * + * @param action The action object. + * @param bucket The bucket object the `action` will act upon. + */ + execute: function (action, bucket) { + var self = this; + bucket.checked = !bucket.checked; + switch (action.name.toLowerCase()) { + case 'delete': + this.dialogService.openConfirm({ + title: 'Delete Bucket', + message: 'All versions of all flows will be deleted.', + cancelButton: 'Cancel', + acceptButton: 'Delete', + acceptButtonColor: 'fds-warn' + }).afterClosed().subscribe( + function (accept) { + if (accept) { + self.nfRegistryService.deleteBucket(bucket.id); + } + }); + break; + case 'permissions': + this.router.navigateByUrl('/nifi-registry/administration/' + this.nfRegistryService.registry.id + '/workflow(' + action.type + ':bucket/' + action.name + '/' + bucket.id + ')'); + break; + default: + break; + } + } +}; + +NfRegistryWorkflowAdministration.annotations = [ + new ngCore.Component({ + template: require('./nf-registry-workflow-administration.html!text'), + animations: [nfRegistryAnimations.slideInLeftAnimation], + host: { + '[@routeAnimation]': 'routeAnimation' + } + }) +]; + +NfRegistryWorkflowAdministration.parameters = [NfRegistryService, ngRouter.ActivatedRoute, ngRouter.Router, fdsDialogsModule.FdsDialogService]; + +module.exports = NfRegistryWorkflowAdministration; diff --git a/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/nf-registry-explorer-grid-list-viewer.html b/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/nf-registry-explorer-grid-list-viewer.html new file mode 100644 index 000000000..694065be4 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/nf-registry-explorer-grid-list-viewer.html @@ -0,0 +1,18 @@ + + + diff --git a/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/nf-registry-explorer-grid-list-viewer.js b/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/nf-registry-explorer-grid-list-viewer.js new file mode 100644 index 000000000..9aa528a3a --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/nf-registry-explorer-grid-list-viewer.js @@ -0,0 +1,43 @@ +/* + * 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. + */ +var ngCore = require('@angular/core'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); + +/** + * NfRegistryExplorerGridListViewer constructor. + * + * @param nfRegistryService The nf-registry.service module. + * @constructor + */ + +function NfRegistryExplorerGridListViewer(nfRegistryService) { + this.nfRegistryService = nfRegistryService; +}; + +NfRegistryExplorerGridListViewer.prototype = { + constructor: NfRegistryExplorerGridListViewer +}; + +NfRegistryExplorerGridListViewer.annotations = [ + new ngCore.Component({ + template: require('./nf-registry-explorer-grid-list-viewer.html!text') + }) +]; + +NfRegistryExplorerGridListViewer.parameters = [NfRegistryService]; + +module.exports = NfRegistryExplorerGridListViewer; diff --git a/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/bucket/droplet/nf-registry-droplet-grid-list-viewer.html b/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/bucket/droplet/nf-registry-droplet-grid-list-viewer.html new file mode 100644 index 000000000..e277b486b --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/bucket/droplet/nf-registry-droplet-grid-list-viewer.html @@ -0,0 +1,17 @@ + + diff --git a/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/bucket/droplet/nf-registry-droplet-grid-list-viewer.js b/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/bucket/droplet/nf-registry-droplet-grid-list-viewer.js new file mode 100644 index 000000000..9a681d2de --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/bucket/droplet/nf-registry-droplet-grid-list-viewer.js @@ -0,0 +1,75 @@ +/* + * 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. + */ +var ngCore = require('@angular/core'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var ngRouter = require('@angular/router'); + +/** + * NfRegistryDropletGridListViewer constructor. + * + * @param nfRegistryService The nf-registry.service module. + * @param ActivatedRoute The angular activated route module. + * @constructor + */ +function NfRegistryDropletGridListViewer(nfRegistryService, ActivatedRoute) { + this.route = ActivatedRoute; + this.nfRegistryService = nfRegistryService; +}; + +NfRegistryDropletGridListViewer.prototype = { + constructor: NfRegistryDropletGridListViewer, + + /** + * Initialize the component. + */ + ngOnInit: function () { + var self = this; + this.route.params + .switchMap(function (params) { + return self.nfRegistryService.getDroplets(self.nfRegistryService.registry.id, self.nfRegistryService.bucket.id, params['dropletId']); + }) + .subscribe(function (droplets) { + self.nfRegistryService.droplet = droplets[0]; + self.nfRegistryService.droplets = self.nfRegistryService.filteredDroplets = droplets; + self.nfRegistryService.filterDroplets(); + }); + }, + + /** + * Destroy the component. + */ + ngOnDestroy: function () { + var self = this; + this.nfRegistryService.droplet = {}; + this.nfRegistryService.getDroplets(this.nfRegistryService.registry.id, + this.nfRegistryService.bucket.id).then( + function (droplets) { + self.nfRegistryService.droplets = self.nfRegistryService.filteredDroplets = droplets; + self.nfRegistryService.filterDroplets(); + }); + } +}; + +NfRegistryDropletGridListViewer.annotations = [ + new ngCore.Component({ + template: require('./nf-registry-droplet-grid-list-viewer.html!text') + }) +]; + +NfRegistryDropletGridListViewer.parameters = [NfRegistryService, ngRouter.ActivatedRoute]; + +module.exports = NfRegistryDropletGridListViewer; diff --git a/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/bucket/nf-registry-bucket-grid-list-viewer.html b/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/bucket/nf-registry-bucket-grid-list-viewer.html new file mode 100644 index 000000000..694065be4 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/bucket/nf-registry-bucket-grid-list-viewer.html @@ -0,0 +1,18 @@ + + + diff --git a/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/bucket/nf-registry-bucket-grid-list-viewer.js b/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/bucket/nf-registry-bucket-grid-list-viewer.js new file mode 100644 index 000000000..a9927689d --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/bucket/nf-registry-bucket-grid-list-viewer.js @@ -0,0 +1,76 @@ +/* + * 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. + */ +var ngCore = require('@angular/core'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var ngRouter = require('@angular/router'); + +/** + * NfRegistryBucketGridListViewer constructor. + * + * @param nfRegistryService The nf-registry.service module. + * @param ActivatedRoute The angular activated route module. + * @constructor + */ +function NfRegistryBucketGridListViewer(nfRegistryService, ActivatedRoute) { + this.route = ActivatedRoute; + this.nfRegistryService = nfRegistryService; +}; + +NfRegistryBucketGridListViewer.prototype = { + constructor: NfRegistryBucketGridListViewer, + + /** + * Initialize the component. + */ + ngOnInit: function () { + var self = this; + this.route.params + .switchMap(function (params) { + return self.nfRegistryService.getBuckets(self.nfRegistryService.registry.id, params['bucketId']); + }) + .subscribe(function (buckets) { + self.nfRegistryService.bucket = buckets[0]; + self.nfRegistryService.getDroplets(self.nfRegistryService.registry.id, self.nfRegistryService.bucket.id).then(function (droplets) { + self.nfRegistryService.droplets = self.nfRegistryService.filteredDroplets = droplets; + self.nfRegistryService.filterDroplets(); + }); + }); + }, + + /** + * Destroy the component. + */ + ngOnDestroy: function () { + var self = this; + this.nfRegistryService.bucket = {}; + this.nfRegistryService.getDroplets(this.nfRegistryService.registry.id).then( + function (droplets) { + self.nfRegistryService.droplets = self.nfRegistryService.filteredDroplets = droplets; + self.nfRegistryService.filterDroplets(); + }); + } +}; + +NfRegistryBucketGridListViewer.annotations = [ + new ngCore.Component({ + template: require('./nf-registry-bucket-grid-list-viewer.html!text') + }) +]; + +NfRegistryBucketGridListViewer.parameters = [NfRegistryService, ngRouter.ActivatedRoute]; + +module.exports = NfRegistryBucketGridListViewer; diff --git a/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.html b/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.html new file mode 100644 index 000000000..d6113c045 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.html @@ -0,0 +1,186 @@ + + +
+
+ + +
+
+ {{nfRegistryService.getDropletTypeCount('asset')}} +
+
Assets
+
+
+ +
+
+ {{nfRegistryService.getDropletTypeCount('extension')}} +
+
Extensions
+
+
+ +
+
{{nfRegistryService.getDropletTypeCount('flow')}} +
+
Flows
+
+
+ +
+
+ {{nfRegistryService.getDropletCertificationCount('compliant')}} +
+
Compliant
+
+
+ +
+
+ {{nfRegistryService.getDropletCertificationCount('fleet')}} +
+
Fleet
+
+
+ +
+
+ {{nfRegistryService.getDropletCertificationCount('prod')}} +
+
Production Ready
+
+
+ +
+
+ {{nfRegistryService.getDropletCertificationCount('secure')}} +
+
Secure
+
+
+
+
+ Clear Grouping +
+
+
+
+ + Sort by: +
+
{{nfRegistryService.getSortByLabel()}}
+ +
+
+ +
+ +
+
+
+
+
+
+ + +
+ {{droplet.displayName}} + {{droplet.type}} +
+
+ +
+
+ Versions {{droplet.versions.length}} +
+
+
+
+
+
+ + + + +
+
+
+ Description +
+
+ Change Log +
+
+
+
+

{{droplet.description}}

+
+
+ + + + {{version.created | amTimeAgo}} + +
+
+ {{version.comment}} +
+
+ {{version.created}} +
+
+
+
+
+
+
+
+
+
+
+
+
+

No results match this query.

+
+ diff --git a/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.js b/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.js new file mode 100644 index 000000000..a7aa2fd78 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.js @@ -0,0 +1,106 @@ +/* + * 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. + */ +var ngCore = require('@angular/core'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var ngRouter = require('@angular/router'); +var nfRegistryAnimations = require('nifi-registry/nf-registry.animations.js'); +var fdsDialogsModule = require('@fluid-design-system/dialogs'); + +/** + * NfRegistryGridListViewer constructor. + * + * @param nfRegistryService The nf-registry.service module. + * @param ActivatedRoute The angular activated route module. + * @param TdDialogService The covalent dialog service module. + * @constructor + */ +function NfRegistryGridListViewer(nfRegistryService, ActivatedRoute, FdsDialogService) { + this.route = ActivatedRoute; + this.nfRegistryService = nfRegistryService; + this.dialogService = FdsDialogService; +}; + +NfRegistryGridListViewer.prototype = { + constructor: NfRegistryGridListViewer, + + /** + * Initialize the component. + */ + ngOnInit: function () { + var self = this; + this.nfRegistryService.explorerViewType = 'grid-list'; + this.route.params + .switchMap(function (params) { + return self.nfRegistryService.getRegistry(params['registryId']); + }) + .subscribe(function (registry) { + self.nfRegistryService.registry = registry; + self.nfRegistryService.getBuckets(self.nfRegistryService.registry.id).then(function (buckets) { + self.nfRegistryService.buckets = buckets; + self.nfRegistryService.getDroplets(self.nfRegistryService.registry.id, self.nfRegistryService.bucket.id, self.nfRegistryService.droplet.id).then(function (droplets) { + self.nfRegistryService.droplets = self.nfRegistryService.filteredDroplets = droplets; + self.nfRegistryService.filterDroplets(); + }); + }) + }); + }, + + /** + * Destroy the component. + */ + ngOnDestroy: function () { + this.nfRegistryService.registry = {}; + this.nfRegistryService.buckets = []; + this.nfRegistryService.droplets = []; + this.nfRegistryService.filteredDroplets = []; + }, + + /** + * Execute the given droplet action. + * + * @param action The action object. + * @param droplet The droplet object the `action` will act upon. + */ + execute: function (action, droplet) { + var self = this; + if (action.name.toLowerCase() === 'delete') { + this.dialogService.openConfirm({ + title: 'Delete Data Flow', + message: 'All versions of this data flow will be deleted.', + cancelButton: 'Cancel', + acceptButton: 'Delete', + acceptButtonColor: 'fds-warn' + }).afterClosed().subscribe( + function (accept) { + if (accept) { + self.nfRegistryService.deleteDroplet(droplet.id); + } + }); + } + } +}; + +NfRegistryGridListViewer.annotations = [ + new ngCore.Component({ + template: require('./nf-registry-grid-list-viewer.html!text'), + animations: [nfRegistryAnimations.flyInOutAnimation] + }) +]; + +NfRegistryGridListViewer.parameters = [NfRegistryService, ngRouter.ActivatedRoute, fdsDialogsModule.FdsDialogService]; + +module.exports = NfRegistryGridListViewer; diff --git a/nifi-registry-web-ui/src/main/webapp/components/explorer/nf-registry-explorer.html b/nifi-registry-web-ui/src/main/webapp/components/explorer/nf-registry-explorer.html new file mode 100644 index 000000000..694065be4 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/explorer/nf-registry-explorer.html @@ -0,0 +1,18 @@ + + + diff --git a/nifi-registry-web-ui/src/main/webapp/components/explorer/nf-registry-explorer.js b/nifi-registry-web-ui/src/main/webapp/components/explorer/nf-registry-explorer.js new file mode 100644 index 000000000..3c7007733 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/explorer/nf-registry-explorer.js @@ -0,0 +1,61 @@ +/* + * 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. + */ +var ngCore = require('@angular/core'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var nfRegistryAnimations = require('nifi-registry/nf-registry.animations.js'); + +/** + * NfRegistryExplorer constructor. + * + * @param nfRegistryService The nf-registry.service module. + * @constructor + */ +function NfRegistryExplorer(nfRegistryService) { + this.nfRegistryService = nfRegistryService; +}; + +NfRegistryExplorer.prototype = { + constructor: NfRegistryExplorer, + + /** + * Initialize the component + */ + ngOnInit: function () { + this.nfRegistryService.perspective = 'explorer'; + }, + + /** + * Destroy the component. + */ + ngOnDestroy: function () { + this.nfRegistryService.perspective = ''; + } +}; + +NfRegistryExplorer.annotations = [ + new ngCore.Component({ + template: require('./nf-registry-explorer.html!text'), + animations: [nfRegistryAnimations.slideInLeftAnimation], + host: { + '[@routeAnimation]': 'routeAnimation' + } + }) +]; + +NfRegistryExplorer.parameters = [NfRegistryService]; + +module.exports = NfRegistryExplorer; diff --git a/nifi-registry-web-ui/src/main/webapp/components/fluid-design-system/fds-demo.html b/nifi-registry-web-ui/src/main/webapp/components/fluid-design-system/fds-demo.html new file mode 100644 index 000000000..7e9baf770 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/fluid-design-system/fds-demo.html @@ -0,0 +1,3060 @@ + + + + +
+

You can also open a dialog from a side nav.

+ +
+
+
+ + Fluid Design System + + +

With the Fluid Design System module, we get an atomic, reusable component platform for the Apache Nifi Registry to consume, while collaborating in an open source model. This module packages the Angular Material module as well as the Teradata Covalent module. These modules have been themed to match the FDS color palette.

+
+
+ + Setup + + +

Import the FDS Core NgModule into your AppModule

+

HTML:

+
+        
+    
+

The core FDS styles also need to be included in your `index.html` like:

+

HTML:

+
+        
+        ]]>
+    
+

Or, if you are using the Angular CLI you will need to add a new entry to the "styles" list in .angular-cli.json.

+

JSON:

+
+        
+    
+
+
+ + Typography + + +

Angular Material provides typography CSS classes you can use to create visual consistency across your application.

+

+ Note: + Base font size is 10px for easy rem units (1.2rem = 12px). Body font size is 14px. sp = scalable pixels. +

+

Header Styles

+ +

To preserve semantic structures, you can optionally style the <h1> - <h6> heading tags with the styling classes shown below:

+

CSS:

+
+
+ .md-display-4 + Light 112px +
+
+ .md-display-3 + Regular 56px +
+
+ .md-display-2 + Regular 45px +
+
+ .md-display-1 + Regular 34px +
+
+ .md-headline + Regular 24px +
+
+ .md-title + Medium 20px +
+
+ .md-subhead + Regular 16px +
+
+

Usage

+

HTML:

+
+    
+        

Roboto is the standard typeface on Android.

+

Roboto and Noto are the standard typefaces on Android and Chrome.

+

Noto is the standard typeface for all languages on Chrome and Android for all languages not covered by Roboto.

+ +

Roboto is the standard typeface on Android.

+

Roboto and Noto are the standard typefaces on Android and Chrome.

+

Noto is the standard typeface for all languages on Chrome and Android for all languages not covered by Roboto.

+ ]]> +
+

Body Copy

+ +

CSS:

+
+
+ .md-body-1 + Regular 14px +
+
+ .md-body-2 + Medium 14px +
+
+ .md-button + Medium 14px +
+
+ .md-caption + Regular 12px +
+
+

Usage

+

HTML:

+
+    
+        

Roboto is the standard typeface on Android.

+

Roboto and Noto are the standard typefaces on Android and Chrome.

+

Roboto and Noto are the standard typefaces on Android and Chrome.

+

Noto is the standard typeface for all languages on Chrome and Android for all languages not covered by Roboto.

+ ]]> +
+
+
+ + Raised Buttons + + +

Tip: Use UPPERCASE text for 1-2 words, and Titlecase text for 3+ words.

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

Usage

+

HTML:

+
+    
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+    ]]>
+    
+
+
+ + Links + + + Angular Material +

Usage

+

HTML:

+
+                Angular Material
+                ]]>
+            
+
+
+ + Flat Buttons + + + + + + + + + + + + +

Usage

+

HTML:

+
+    
+        
+        
+        
+        
+        
+        
+        
+        
+        
+    ]]>
+    
+
+
+ + Fab Buttons + + + + + + + + + + +

Usage

+

HTML:

+
+    
+        
+        
+        
+        
+        
+        
+        
+    ]]>
+    
+
+
+ + Button Toggles + + + + + format_align_left + + + format_align_center + + + format_align_right + + + format_align_justify + + +
+ + + ON + + + OFF + + +
+ + +
+
34
+
Assets
+
+
+ +
+
300
+
Extensions
+
+
+ +
+
5000
+
Flows
+
+
+ +
+
0
+
Certifications
+
+
+
+
+ + + general + +
+ + Users + +
+ + Workflow + +
+

Usage

+

HTML:

+
+      
+            
+                format_align_left
+            
+            
+                format_align_center
+            
+            
+                format_align_right
+            
+            
+                format_align_justify
+            
+        
+        
+ + + ON + + + OFF + + +
+ + +
+
34
+
Assets
+
+
+ +
+
300
+
Extensions
+
+
+ +
+
5000
+
Flows
+
+
+ +
+
0
+
Certifications
+
+
+
+
+ + + general + +
+ + Users + +
+ + Workflow + +
+ ]]> +
+
+
+ + Input + + +
+
+ + + +
+
+ + + + + + +
+
+
+ + + + + + + + + + +
+
+ + + + +
+
+
+
+ + + + +
+
+ + + + +
+
+
+ + + +
+
+ + + +
+
+ + + + + + + + + {{postalCode.value.length}} / 5 + +
+
+

Usage

+

HTML:

+
+    
+        
+
+ + + +
+
+ + + + + + +
+
+
+ + + + + + + + + + +
+
+ + + + +
+
+
+
+ + + + +
+
+ + + + +
+
+
+ + + +
+
+ + + +
+
+ + + + + + + + + {{postalCode.value.length}} / 5 + +
+
+ ]]> +
+
+
+ + Tabs + + + + + One +

First tab content

+

Plaid echo park knausgaard normcore franzen cronut. Pickled humblebrag tofu hoodie, umami salvia farm-to-table schlitz try-hard food truck knausgaard pabst. Yuccie portland jean shorts, authentic mixtape waistcoat gentrify blue bottle. Fixie kickstarter church-key small batch seitan, shabby chic vegan listicle before they sold out. Hammock raw denim flannel tousled seitan you probably haven't heard of them. Trust fund man bun pug, kickstarter artisan selvage letterpress cornhole tote bag butcher locavore. Affogato try-hard kickstarter seitan, DIY pickled hella godard pork belly four loko ugh.

+
+ + Two +

Second tab content

+

Hashtag distillery skateboard man bun gochujang, salvia man braid art party meggings heirloom kitsch farm-to-table. Franzen beard fingerstache gentrify, heirloom portland ennui XOXO microdosing kitsch plaid. Chicharrones bushwick chia, banh mi irony tattooed hammock butcher shabby chic taxidermy semiotics marfa post-ironic. Blue bottle keffiyeh farm-to-table ennui, chambray pitchfork art party pinterest artisan pop-up. Etsy banjo marfa, blue bottle kombucha crucifix XOXO tousled beard. Tilde disrupt kale chips bicycle rights skateboard master cleanse hella shoreditch, meditation retro shabby chic vice heirloom. Etsy listicle vice actually, iPhone chia hoodie four loko.

+
+
+

Usage

+

HTML:

+
+      
+          
+            First tab content
+            

First content

+

...

+
+ + Second tab content +

Second tab content

+

...

+
+ + ]]> +
+
+
+ + Autocomplete + + +
+ + + +
+
+ + + +
+ + + {{ state.name }} + ({{state.code}}) + + +

Usage

+

HTML:

+
+      
+            
+                
+            
+        
+
+ + + +
+ + + { { state.name } } + ({ {state.code} }) + + + ]]> + +

Javascript:

+
+       s.name.match(new RegExp(val, 'gi'))) : this.states;
+        },
+
+        ...
+        ]]>
+      
+ + + + Chips + + +

Chips (with colors)

+ + + {{chip.name}} + + + +

Chip Stacked (with colors)

+
+ + + {{chip.name}} + + +
+

Usage

+

HTML:

+
+      
+            
+                { {chip.name} }
+            
+        
+        ]]>
+      
+

Javascript:

+
+      
+      
+
+
+ + Filter + + +

Autocomplete with chips and no custom inputs

+ + + + Demo +
+
Type and select a preset option:
+ +
+
+ + Code + +

HTML:

+
+                            
+          ]]>
+                        
+

Javascript:

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

Autocomplete with custom inputs

+ + + + Demo +
+
Type and select option or enter custom text and press enter:
+ +
+
+ + Code + +

HTML:

+
+                            
+          ]]>
+                        
+

Javascript:

+
+                            
+                        
+
+
+
+
+ +

Demo allowing custom inputs for tags

+ + + + Demo +
+
Type any test and press enter:
+ +
+
+ + Code + +

HTML:

+
+                            
+          ]]>
+                        
+
+
+
+
+
+ + Searchable/Filterable Expansion Panels + + + + + Demo +
+
+ + +
+
{{getDropletTypeCount('asset')}}
+
Assets
+
+
+ +
+
{{getDropletTypeCount('extension')}}
+
Extensions
+
+
+ +
+
{{getDropletTypeCount('flow')}}
+
Flows
+
+
+ +
+
{{getDropletCertificationCount('compliant')}}
+
Compliant
+
+
+ +
+
{{getDropletCertificationCount('fleet')}}
+
Fleet
+
+
+ +
+
{{getDropletCertificationCount('prod')}}
+
Production Ready
+
+
+ +
+
{{getDropletCertificationCount('secure')}}
+
Secure
+
+
+
+
+ Clear Grouping +
+
+
+
+ + Sort by: + +
+ +
+ +
+
+
+
+
+
+ + +
+ {{droplet.displayName}} + {{droplet.type}} +
+
+ +
+
+ Versions {{droplet.versions.length}} +
+
+ Flows {{droplet.flows.length}} +
+
+ Extensions {{droplet.extensions.length}} +
+
+ Assests {{droplet.assets.length}} +
+
+
+
+
+
+ + + + +
+
+
+ Description +

Blah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah bla

+
+
+ + + + + +
+
+ Change Log +
+
+
+
+
+
+
+
+
+ + Code +

HTML:

+
+                        
+            
+ + +
+
{ {getDropletTypeCount('asset')} }
+
Assets
+
+
+ +
+
{ {getDropletTypeCount('extension')} }
+
Extensions
+
+
+ +
+
{ {getDropletTypeCount('flow')} }
+
Flows
+
+
+ +
+
{ {getDropletCertificationCount('compliant')} }
+
Compliant
+
+
+ +
+
{ {getDropletCertificationCount('fleet')} }
+
Fleet
+
+
+ +
+
{ {getDropletCertificationCount('prod')} }
+
Production Ready
+
+
+ +
+
{ {getDropletCertificationCount('secure')} }
+
Secure
+
+
+
+ +
+
+
+ + Sort by: + +
+ +
+ +
+
+
+ +
+
+ + +
+ { {droplet.displayName} } + { {droplet.type} } +
+
+ +
+
+ Versions { {droplet.versions.length} } +
+
+ Flows { {droplet.flows.length} } +
+
+ Extensions { {droplet.extensions.length} } +
+
+ Assests { {droplet.assets.length} } +
+
+
+
+
+
+ + + + +
+
+
+ Description +

Blah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah blaBlah blah bla, bla bla, blah blah bla

+
+
+ + + + + +
+
+ Change Log +
+
+
+
+
+
+
+
+ ]]> +
+

Javascript:

+
+                         -1);
+        },
+
+        getDropletTypeCount: function(type) {
+            return this.filteredDroplets.filter(function(droplet) {
+                return droplet.type === type;
+            }).length;
+        },
+
+        getDropletCertificationCount: function(certification) {
+            return this.filteredDroplets.filter(droplet => {
+                return Object.keys(droplet).find((key) => {
+                    if (key === certification && droplet[certification].type === 'certification') {
+                        return droplet;
+                    }
+                });
+            }).length;
+        },
+
+        getSortBy: function() {
+            var sortByColumnLabel;
+            var arrayLength = this.dropletColumns.length;
+            for (var i = 0; i < arrayLength; i++) {
+                if (this.dropletColumns[i].active === true) {
+                    sortByColumnLabel = this.dropletColumns[i].label;
+                    break;
+                }
+            }
+            return sortByColumnLabel;
+        },
+
+        sortDroplets: function(sortEvent, column) {
+            if (column.sortable === true) {
+                // toggle column sort order
+                var sortOrder = column.sortOrder = (column.sortOrder === 'ASC') ? 'DESC' : 'ASC';
+                this.filterDroplets(column.name, sortOrder);
+                this.activeColumn = column;
+                //only one column can be actively sorted so we reset all to inactive
+                this.dropletColumns.forEach(c => c.active = false);
+                //and set this column as the actively sorted column
+                column.active = true;
+            }
+        },
+
+        dropletsSearchRemove: function(searchTerm) {
+            this.filterDroplets(this.activeColumn.name, this.activeColumn.sortOrder);
+        },
+
+        dropletsSearchAdd: function(searchTerm) {
+            this.filterDroplets(this.activeColumn.name, this.activeColumn.sortOrder);
+        },
+
+        toggleDropletsFilter: function(searchTerm) {
+            var applySearchTerm = true;
+            // check if the search term is already applied and remove it if true
+            if (this.dropletsSearchTerms.length > 0) {
+                var arrayLength = this.dropletsSearchTerms.length;
+                for (var i = 0; i < arrayLength; i++) {
+                    var index = this.dropletsSearchTerms.indexOf(searchTerm);
+                    if (index > -1) {
+                        this.dropletsSearchTerms.splice(index, 1);
+                        applySearchTerm = false;
+                    }
+                }
+            }
+
+            // if we just removed the search term do NOT apply it again
+            if (applySearchTerm) {
+                this.dropletsSearchTerms.push(searchTerm);
+            }
+
+            this.filterDroplets(this.activeColumn.name, this.activeColumn.sortOrder);
+        },
+
+        filterDroplets: function(sortBy, sortOrder) {
+            // if `sortBy` is `undefined` then find the first sortable column in this.dropletColumns
+            if (sortBy === undefined) {
+                var arrayLength = this.dropletColumns.length;
+                for (var i = 0; i < arrayLength; i++) {
+                    if (this.dropletColumns[i].sortable === true) {
+                        sortBy = this.dropletColumns[i].name;
+                        this.activeColumn = this.dropletColumns[i];
+                        //only one column can be actively sorted so we reset all to inactive
+                        this.dropletColumns.forEach(c => c.active = false);
+                        //and set this column as the actively sorted column
+                        this.dropletColumns[i].active = true;
+                        break;
+                    }
+                }
+            }
+
+            // if `sortOrder` is `undefined` then use 'ASC'
+            if (sortOrder === undefined) {
+                sortOrder = 'ASC'
+            }
+
+            var newData = this.droplets;
+
+            for (var i = 0; i < this.dropletsSearchTerms.length; i++) {
+                newData = this.filterData(newData, this.dropletsSearchTerms[i], true, this.activeColumn.name);
+            }
+
+            newData = this.dataTableService.sortData(newData, sortBy, sortOrder);
+            this.filteredDroplets = newData;
+            this.getAutoCompleteDroplets();
+        },
+
+        getAutoCompleteDroplets: function() {
+            this.autoCompleteDroplets = [];
+            this.dropletColumns.forEach(c => this.filteredDroplets.forEach(r => (r[c.name.toLowerCase()]) ? this.autoCompleteDroplets.push(r[c.name.toLowerCase()].toString()) : ''));
+        },
+
+        filterData: function(data, searchTerm, ignoreCase) {
+            var field = '';
+            if (searchTerm.indexOf(":") > -1) {
+                field = searchTerm.split(':')[0].trim();
+                searchTerm = searchTerm.split(':')[1].trim();
+            }
+            var filter = searchTerm ? (ignoreCase ? searchTerm.toLowerCase() : searchTerm) : '';
+
+            if (filter) {
+                data = data.filter(item => {
+                    var res = Object.keys(item).find((key) => {
+                        if (field.indexOf(".") > -1) {
+                            var objArray = field.split(".");
+                            var obj = item;
+                            var arrayLength = objArray.length;
+                            for (var i = 0; i < arrayLength; i++) {
+                                try {
+                                    obj = obj[objArray[i]];
+                                } catch (e) {
+                                    return false;
+                                }
+                            }
+                            var preItemValue = ('' + obj);
+                            var itemValue = ignoreCase ? preItemValue.toLowerCase() : preItemValue;
+                            return itemValue.indexOf(filter) > -1;
+                        } else {
+                            if (key !== field && field !== '') {
+                                return false;
+                            }
+                            var preItemValue = ('' + item[key]);
+                            var itemValue = ignoreCase ? preItemValue.toLowerCase() : preItemValue;
+                            return itemValue.indexOf(filter) > -1;
+                        }
+                    });
+                    return !(typeof res === 'undefined');
+                });
+            }
+            return data;
+        },
+
+        ...
+          ]]>
+                    
+
+
+
+ +
+ + Table + + +

Example table with: Paging Bar / Filter / Sortable Columns / Multi-select with available Actions

+ + + Demo +
+ + Table title + +
+ + +
+ + + + +
+
+
+
+ {{column.label}} + + +
+
+
+ +
+
+
+
+
+
+
+ {{column.format ? column.format(row[column.name]) : row[column.name]}} +
+
+
+
+
+ + +
+
+ + + + + +
+
+
+ +
+
+
+
+
+

No results to display.

+
+ + Row per page: {{pagingBar.range}} of {{pagingBar.total}} + +
+
+ + Code +

HTML:

+
+                        
+            
+            Table title
+            
+            
+ + +
+ + + + + +
+
+
+ { { column.label } } + + +
+
+
+ +
+
+
+
+
+
+
+ { { column.format ? column.format(row[column.name]) : row[column.name] } } +
+
+
+
+
+ + +
+
+ + + + + +
+
+
+ +
+
+
+
+
+

No results to display.

+
+ + Row per page: { { pagingBar.range } } of { { pagingBar.total } } + +
+ ]]> +
+

Javascript:

+
+                         c.active = false);
+                //and set this column as the actively sorted column
+                column.active = true;
+            }
+        },
+
+        searchRemove: function(searchTerm) {
+            //only remove the first occurrence of the search term
+            var index = this.searchTerm.indexOf(searchTerm);
+            if (index !== -1) {
+                this.searchTerm.splice(index, 1);
+            }
+            this.filter();
+        },
+
+        searchAdd: function(searchTerm) {
+            this.searchTerm.push(searchTerm);
+            this.filter();
+        },
+
+        page: function(pagingEvent) {
+            this.fromRow = pagingEvent.fromRow;
+            this.currentPage = pagingEvent.page;
+            this.pageSize = pagingEvent.pageSize;
+            this.filter();
+        },
+
+        filterData: function(data, searchTerm, ignoreCase) {
+            var field = '';
+            if (searchTerm.indexOf(":") > -1) {
+                field = searchTerm.split(':')[0].trim();
+                searchTerm = searchTerm.split(':')[1].trim();
+            }
+            var filter = searchTerm ? (ignoreCase ? searchTerm.toLowerCase() : searchTerm) : '';
+
+            if (filter) {
+                data = data.filter(item => {
+                    var res = Object.keys(item).find((key) => {
+                        if (field.indexOf(".") > -1) {
+                            var objArray = field.split(".");
+                            var obj = item;
+                            var arrayLength = objArray.length;
+                            for (var i = 0; i < arrayLength; i++) {
+                                try {
+                                    obj = obj[objArray[i]];
+                                } catch (e) {
+                                    return false;
+                                }
+                            }
+                            var preItemValue = ('' + obj);
+                            var itemValue = ignoreCase ? preItemValue.toLowerCase() : preItemValue;
+                            return itemValue.indexOf(filter) > -1;
+                        } else {
+                            if (key !== field && field !== '') {
+                                return false;
+                            }
+                            var preItemValue = ('' + item[key]);
+                            var itemValue = ignoreCase ? preItemValue.toLowerCase() : preItemValue;
+                            return itemValue.indexOf(filter) > -1;
+                        }
+                    });
+                    return !(typeof res === 'undefined');
+                });
+            }
+            return data;
+        },
+
+        filter: function(sortBy, sortOrder) {
+            if (this.allRowsSelected) {
+                this.toggleSelectAll();
+            }
+            this.deselectAll();
+            var newData = this.data;
+
+            if (this.searchTerm.length > 0) {
+                for (var i = 0; i < this.searchTerm.length; i++) {
+                    //account for column/field name specific search syntax
+                    if (this.searchTerm[i].indexOf(":") > -1) {
+                        newData = this.filterData(newData, this.searchTerm[i].split(':')[1].trim(), true, this.searchTerm[i].split(':')[0].trim());
+                    } else { //otherwise search all cells
+                        newData = this.filterData(newData, this.searchTerm[i], true);
+                    }
+                }
+            } else {
+                newData = this.dataTableService.filterData(newData, '', true);
+            }
+            this.filteredTotal = newData.length;
+            newData = this.dataTableService.sortData(newData, sortBy, sortOrder);
+            newData = this.dataTableService.pageData(newData, this.fromRow, this.currentPage * this.pageSize);
+            this.filteredData = newData;
+            this.getAutoCompleteData();
+        },
+
+        toggleSelect: function(row) {
+            if (!row.checked) {
+                this.allRowsSelected = false;
+            } else {
+                if (this.allFilteredRowsSelected()) {
+                    this.allRowsSelected = true;
+                } else {
+                    this.allRowsSelected = false;
+                }
+            }
+        },
+
+        toggleSelectAll: function() {
+            this.allRowsSelected = !this.allRowsSelected;
+            if (this.allRowsSelected) {
+                this.selectAll();
+            } else {
+                this.deselectAll();
+            }
+        },
+
+        selectAll: function() {
+            this.filteredData.forEach(c => c.checked = true);
+        },
+
+        deselectAll: function() {
+            this.filteredData.forEach(c => c.checked = false);
+        },
+
+        allFilteredRowsSelected: function() {
+            var allFilteredRowsSelected = true;
+            this.filteredData.forEach(function(c) {
+                if (c.checked === undefined || c.checked === false) {
+                    allFilteredRowsSelected = false;
+                }
+            });
+
+            return allFilteredRowsSelected;
+        },
+
+        areTooltipsOn: function() {
+            return this.columns[0].hasOwnProperty('tooltip');
+        },
+
+        toggleTooltips: function() {
+            if (this.columns[0].tooltip) {
+                this.columns.forEach(c => delete c.tooltip);
+            } else {
+                this.columns.forEach(c => c.tooltip = `This is ${c.label}!`);
+            }
+        },
+
+        openDataTablePrompt: function(row, name) {
+            this.dialogService.openPrompt({
+                message: 'Enter comment?',
+                value: row[name],
+            }).afterClosed().subscribe(value => {
+                if (value !== undefined) {
+                    row[name] = value;
+                }
+            })
+        },
+
+        getAutoCompleteData: function() {
+            this.autoCompleteData = [];
+            this.columns.forEach(c => this.filteredData.forEach(r => (r[c.name.toLowerCase()]) ? this.autoCompleteData.push(r[c.name.toLowerCase()].toString()):''));
+        },
+
+        ...
+          ]]>
+                    
+
+
+
+ + + + +
+ + Checkbox + + +

Basic Usage

+ + + + + {{grocery.name}} + + + +

Usage

+

HTML:

+
+                        
+        
+            { {grocery.name} }
+        
+                        ]]>
+                    
+

Javascript:

+
+                        
+                    
+

Usage within Forms

+ +
+
+ + I agree to the terms + + +
+ + + I come after my label. + + + I come before my label +
+

Usage

+

HTML:

+
+        
+        
+
+ + I agree to the terms + + +
+ + + I come after my label. + + + I come before my label +
+ ]]> +
+

Javascript:

+
+                        
+                    
+
+
+ + Radios + + +
+ +

Basic Radios

+ + + Option 1 + Option 2 + Option 3 (disabled) + +

Usage

+

HTML:

+
+                
+        
+            Option 1 
+            Option 2 
+            Option 3 (disabled) 
+        
+        ]]>
+        
+
+
+ +

Dynamic Radios

+ + + + {{season}} + + +

Your favorite season is: {{favoriteSeason}}

+

Usage

+

HTML:

+
+      
+        
+          
+            { {season} }
+          
+        
+        

Your favorite season is: { { favoriteSeason } }

+ ]]> +
+

Javascript:

+
+      
+      
+
+
+
+ + Tooltips + + + + + + +

Usage

+

HTML:

+
+      Bottom Tooltip
+        
+        
+        
+        ]]>
+      
+
+
+ + Panels + + +

Standard Card

+ + + + + + + + + Title + + +

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do tempor incididunt ut labore et dolore magna aliqua. Ut enim ad

+
+ + + +
+

Usage

+

HTML:

+
+                
+        
+            
+            
+                
+                
+            
+            
+                Title
+            
+            
+                

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do tempor incididunt ut labore et dolore magna aliqua. Ut enim ad

+
+ + + +
+ ]]> +
+

Tabbed Card

+ + + + + + + + + + + One +

First tab content

+

Plaid echo park knausgaard normcore franzen cronut. Pickled humblebrag tofu hoodie, umami salvia farm-to-table schlitz try-hard food truck knausgaard pabst. Yuccie portland jean shorts, authentic mixtape waistcoat gentrify blue bottle. Fixie kickstarter church-key small batch seitan, shabby chic vegan listicle before they sold out. Hammock raw denim flannel tousled seitan you probably haven't heard of them. Trust fund man bun pug, kickstarter artisan selvage letterpress cornhole tote bag butcher locavore. Affogato try-hard kickstarter seitan, DIY pickled hella godard pork belly four loko ugh.

+
+ + Two +

Second tab content

+

Hashtag distillery skateboard man bun gochujang, salvia man braid art party meggings heirloom kitsch farm-to-table. Franzen beard fingerstache gentrify, heirloom portland ennui XOXO microdosing kitsch plaid. Chicharrones bushwick chia, banh mi irony tattooed hammock butcher shabby chic taxidermy semiotics marfa post-ironic. Blue bottle keffiyeh farm-to-table ennui, chambray pitchfork art party pinterest artisan pop-up. Etsy banjo marfa, blue bottle kombucha crucifix XOXO tousled beard. Tilde disrupt kale chips bicycle rights skateboard master cleanse hella shoreditch, meditation retro shabby chic vice heirloom. Etsy listicle vice actually, iPhone chia hoodie four loko.

+
+
+
+ + + +
+

Usage

+

HTML:

+
+                
+        
+            
+            
+                
+                
+            
+            
+                
+                    
+                        One
+                        

First tab content

+

Plaid echo park knausgaard normcore franzen cronut. Pickled humblebrag tofu hoodie, umami salvia farm-to-table schlitz try-hard food truck knausgaard pabst. Yuccie portland jean shorts, authentic mixtape waistcoat gentrify blue bottle. Fixie kickstarter church-key small batch seitan, shabby chic vegan listicle before they sold out. Hammock raw denim flannel tousled seitan you probably haven't heard of them. Trust fund man bun pug, kickstarter artisan selvage letterpress cornhole tote bag butcher locavore. Affogato try-hard kickstarter seitan, DIY pickled hella godard pork belly four loko ugh.

+
+ + Two +

Second tab content

+

Hashtag distillery skateboard man bun gochujang, salvia man braid art party meggings heirloom kitsch farm-to-table. Franzen beard fingerstache gentrify, heirloom portland ennui XOXO microdosing kitsch plaid. Chicharrones bushwick chia, banh mi irony tattooed hammock butcher shabby chic taxidermy semiotics marfa post-ironic. Blue bottle keffiyeh farm-to-table ennui, chambray pitchfork art party pinterest artisan pop-up. Etsy banjo marfa, blue bottle kombucha crucifix XOXO tousled beard. Tilde disrupt kale chips bicycle rights skateboard master cleanse hella shoreditch, meditation retro shabby chic vice heirloom. Etsy listicle vice actually, iPhone chia hoodie four loko.

+
+
+
+ + + +
+ ]]> +
+
+
+ + Select + + +
+
+ + + {{food.viewValue}} + + +
+
+
Selected food value: {{selectedValue}}
+
+
+

Usage

+

HTML:

+
+      
+            
+ + + { {food.viewValue} } + + +
+
+
Selected food value: { {selectedValue} }
+
+ + ]]> +
+

Javascript:

+
+      
+      
+
+
+ + Menus (dropdowns) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Usage

+

HTML:

+
+      
+            more_vert
+        
+        
+            
+            
+            
+            
+        
+        
+        
+            
+            
+            
+            
+        
+        
+        
+            
+            
+            
+            
+        
+        
+        
+            
+            
+            
+        
+        
+        
+            
+            
+        
+        ]]>
+      
+
+
+ + Dialog + + + +

Usage

+

HTML:

+
+      Show simple dialog
+      ]]>
+    
+

Javascript:

+
+      
+      
+
+
+ + Simple Dialogs + + +
+ +
+

Usage

+

HTML:

+
+      Open Confirm
+        ]]>
+      
+

Javascript:

+
+      
+      
+
+
+ + Snack Bar + + + +

Usage

+

HTML:

+
+      Show Snack Bar
+      ]]>
+    
+

Javascript:

+
+      
+      
+
+
+ + Expansion Panels + + +

Expand/Collapse Event for Expansion 1: {{expandCollapseExpansion1Msg}}

+
+ + +
+
+
+ + + + + pin_drop +

Google

+

Headquarters

+

+ 1600 Amphitheatre Pkwy +
Mountain View, CA 94043, USA +

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

md-padding class

+
Demo 1
+
Demo 2
+
Demo 3
+
Demo 4
+
+
+ + + star + Custom Label (template) + + + list + Custom Sublabel (template) + +
+

md-padding class

+
Phase 1
+
Phase 2
+
Phase 3
+
+
+
+
+

Usage

+

HTML:

+
+      
+            
+                
+                    
+                        pin_drop
+                        

Google

+

Headquarters

+

+ 1600 Amphitheatre Pkwy +
Mountain View, CA 94043, USA +

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

md-padding class

+
Demo 1
+
Demo 2
+
Demo 3
+
Demo 4
+
+
+ + + star + Custom Label (template) + + + list + Custom Sublabel (template) + +
+

md-padding class

+
Phase 1
+
Phase 2
+
Phase 3
+
+
+ ]]> +
+

Javascript:

+
+          
+          
+
+
+ + Progress + + +
+

Progress Bars

+ +

Determinate

+ +

Indeterminate

+ +

Buffer

+ +

Query

+ +

Colors

+ + + + + +

Usage

+

HTML:

+
+      
+        
+
+        
+        
+
+        
+        
+
+        
+        
+
+        
+        
+
+        
+
+        
+      ]]>
+      
+
+
+ +

Progress Spinner

+ +
+
+

Determinate

+ +
+
+

indeterminate

+ +
+
+

Spinner

+ +
+
+
+

Colors

+
+ + + +
+
+

Usage

+

HTML:

+
+      
+        
+        
+        
+        
+        
+        
+        
+        
+        
+      ]]>
+      
+
+
+
+ + Side Nav + + +

The side nav can be opened at the `start` or `end` of a container and can be displayed in `over`, `side`, or `push` mode. You can also define its width.

+ +

Usage

+

HTML:

+
+        
+        
+            ...
+        
+        ]]>
+        
+
+
+ + Slide Toggle + + +

Basic Usage

+ + + + + {{system.name}} + + + +

Usage

+

HTML:

+
+        
+        
+            
+              
+                { {system.name} }
+              
+            
+        
+        ]]>
+        
+

Javascript:

+
+          
+          
+

Usage within Forms

+ +
+ + + + Lock? + + lock + + + + I am disabled. + + + +
+

Usage

+

HTML:

+
+        
+        
+ + + + Lock? + + lock + + + + I am disabled. + + + +
+ ]]> +
+

Javascript:

+
+          
+          
+
+
+ + Ripples + + + +

Usage

+

HTML:

+
+      Click me
+        ]]>
+      
+
+
+ + Slider + + +

Horizontal Slider

+ + + + +

Usage

+

HTML:

+
+      
+        
+        
+        ]]>
+      
+

Vertical Slider

+ + +

Usage

+

HTML:

+
+      
+        ]]>
+      
+

Inverted Slider

+ + +

Usage

+

HTML:

+
+      
+        ]]>
+      
+
+
+ +
diff --git a/nifi-registry-web-ui/src/main/webapp/components/fluid-design-system/fds-demo.js b/nifi-registry-web-ui/src/main/webapp/components/fluid-design-system/fds-demo.js new file mode 100644 index 000000000..84d6212e5 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/fluid-design-system/fds-demo.js @@ -0,0 +1,1029 @@ +/* + * 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. + */ + +var ngCore = require('@angular/core'); +var NfRegistryExplorer = require('nifi-registry/components/explorer/nf-registry-explorer.js'); +var covalentCore = require('@covalent/core'); +var ngRouter = require('@angular/router'); +var ngMaterial = require('@angular/material'); +var nfRegistryAnimations = require('nifi-registry/nf-registry.animations.js'); +var fdsDialogsModule = require('@fluid-design-system/dialogs'); + +var NUMBER_FORMAT = function (v) { + return v; +}; +var DECIMAL_FORMAT = function (v) { + return v.toFixed(2); +}; +var date = new Date(); + +/** + * FdsDemo constructor. + * + * @param snackBarService The angular material snack bar service module. + * @param dialog The angular material dialog module. + * @param TdDialogService The covalent dialog service module. + * @param TdDataTableService The covalent data table service module. + * @constructor + */ +function FdsDemo(snackBarService, dialog, TdDataTableService, FdsDialogService) { + + // + + this.snackBarService = snackBarService; + + // + + // + + this.dialog = dialog; + + // + + // + + this.dialogService = FdsDialogService; + + // + + // + + this.expandCollapseExpansion1Msg = 'No expanded/collapsed detected yet'; + this.expansion1 = false; + this.disabled = false; + + // + + // + + this.currentState = ''; + this.reactiveStates = ''; + this.tdStates = []; + this.tdDisabled = false; + this.states = [ + {code: 'AL', name: 'Alabama'}, + {code: 'AK', name: 'Alaska'}, + {code: 'AZ', name: 'Arizona'}, + {code: 'AR', name: 'Arkansas'}, + {code: 'CA', name: 'California'}, + {code: 'CO', name: 'Colorado'}, + {code: 'CT', name: 'Connecticut'}, + {code: 'DE', name: 'Delaware'}, + {code: 'FL', name: 'Florida'}, + {code: 'GA', name: 'Georgia'}, + {code: 'HI', name: 'Hawaii'}, + {code: 'ID', name: 'Idaho'}, + {code: 'IL', name: 'Illinois'}, + {code: 'IN', name: 'Indiana'}, + {code: 'IA', name: 'Iowa'}, + {code: 'KS', name: 'Kansas'}, + {code: 'KY', name: 'Kentucky'}, + {code: 'LA', name: 'Louisiana'}, + {code: 'ME', name: 'Maine'}, + {code: 'MD', name: 'Maryland'}, + {code: 'MA', name: 'Massachusetts'}, + {code: 'MI', name: 'Michigan'}, + {code: 'MN', name: 'Minnesota'}, + {code: 'MS', name: 'Mississippi'}, + {code: 'MO', name: 'Missouri'}, + {code: 'MT', name: 'Montana'}, + {code: 'NE', name: 'Nebraska'}, + {code: 'NV', name: 'Nevada'}, + {code: 'NH', name: 'New Hampshire'}, + {code: 'NJ', name: 'New Jersey'}, + {code: 'NM', name: 'New Mexico'}, + {code: 'NY', name: 'New York'}, + {code: 'NC', name: 'North Carolina'}, + {code: 'ND', name: 'North Dakota'}, + {code: 'OH', name: 'Ohio'}, + {code: 'OK', name: 'Oklahoma'}, + {code: 'OR', name: 'Oregon'}, + {code: 'PA', name: 'Pennsylvania'}, + {code: 'RI', name: 'Rhode Island'}, + {code: 'SC', name: 'South Carolina'}, + {code: 'SD', name: 'South Dakota'}, + {code: 'TN', name: 'Tennessee'}, + {code: 'TX', name: 'Texas'}, + {code: 'UT', name: 'Utah'}, + {code: 'VT', name: 'Vermont'}, + {code: 'VA', name: 'Virginia'}, + {code: 'WA', name: 'Washington'}, + {code: 'WV', name: 'West Virginia'}, + {code: 'WI', name: 'Wisconsin'}, + {code: 'WY', name: 'Wyoming'}, + ]; + + // + + // + + this.dataTableService = TdDataTableService; + + this.droplets = [{ + id: '23f6cc59-0156-1000-09b4-2b0610089090', + name: "Decompression_Circular_Flow", + displayName: 'Decompressed Circular flow', + type: 'flow', + sublabel: 'A sublabel', + compliant: { + id: '25fd6vv87-3549-0001-05g6-4d4567890765', + label: 'Compliant', + type: 'certification' + }, + fleet: { + id: '23f6cc59-3549-0001-05g6-4d4567890765', + label: 'Fleet', + type: 'certification' + }, + prod: { + id: '52fd6vv87-3549-0001-05g6-4d4567890765', + label: 'Production Ready', + type: 'certification' + }, + secure: { + id: '32f6cc59-3549-0001-05g6-4d4567890765', + label: 'Secure', + type: 'certification' + }, + versions: [{ + id: '23f6cc59-0156-1000-06b4-2b0810089090', + revision: '1', + dependentFlows: [{ + id: '25fd6vv87-3549-0001-05g6-4d4567890765' + }], + created: date.setDate(date.getDate() - 1), + updated: new Date() + }, { + id: '25fd6vv87-3549-0001-05g6-4d4567890765', + revision: '2', + dependentFlows: [{ + id: '23f6cc59-0156-1000-06b4-2b0810089090' + }], + created: new Date(), + updated: new Date() + }], + flows: [], + extensions: [], + assets: [], + actions: [{ + 'name': 'Delete', + 'icon': 'fa fa-close', + 'tooltip': 'Delete User' + }, { + 'name': 'Manage', + 'icon': 'fa fa-user', + 'tooltip': 'Manage User' + }, { + 'name': 'Action 3', + 'icon': 'fa fa-question', + 'tooltip': 'Whatever else we want to do...' + }] + }, { + id: '25fd6vv87-3249-0001-05g6-4d4767890765', + name: "DateConversion", + displayName: 'Date conversion', + type: 'asset', + sublabel: 'A sublabel', + compliant: { + id: '25fd6vv34-3549-0001-05g6-4d4567890765', + label: 'Compliant', + type: 'certification' + }, + prod: { + id: '52vn6vv87-3549-0001-05g6-4d4567890765', + label: 'Production Ready', + type: 'certification' + }, + versions: [{ + id: '23f6ic59-0156-1000-06b4-2b0810089090', + revision: '1', + dependentFlows: [{ + id: '23f6cc19-0156-1000-06b4-2b0810089090' + }], + created: new Date(), + updated: new Date() + }], + flows: [], + extensions: [], + assets: [], + actions: [{ + 'name': 'Delete', + 'icon': 'fa fa-close', + 'tooltip': 'Delete User' + }] + }, { + id: '52fd6vv87-3294-0001-05g6-4d4767890765', + name: "nifi-email-bundle", + displayName: 'nifi-email-bundle', + type: 'extension', + sublabel: 'A sublabel', + compliant: { + id: '33fd6vv87-3549-0001-05g6-4d4567890765', + label: 'Compliant', + test: { + label: 'test' + }, + type: 'certification' + }, + versions: [{ + id: '23d3cc59-0156-1000-06b4-2b0810089090', + revision: '1', + dependentFlows: [{ + id: '23f6cc89-0156-1000-06b4-2b0810089090' + }], + created: new Date(), + updated: new Date() + }], + flows: [], + extensions: [], + assets: [], + actions: [{ + 'name': 'Delete', + 'icon': 'fa fa-close', + 'tooltip': 'Delete User' + }, { + 'name': 'Manage', + 'icon': 'fa fa-user', + 'tooltip': 'Manage User' + },] + }]; + + this.filteredDroplets = []; + + this.dropletColumns = [ + {name: 'id', label: 'ID', sortable: true}, + {name: 'name', label: 'Name', sortable: true,}, + {name: 'displayName', label: 'Display Name', sortable: true}, + {name: 'sublabel', label: 'Label', sortable: true}, + {name: 'type', label: 'Type', sortable: true} + ]; + + this.autoCompleteDroplets = []; + this.dropletsSearchTerms = []; + + // + + // + + this.data = [{ + 'id': 1, + 'name': 'Frozen yogurt', + 'type': 'Ice cream', + 'calories': 159.0, + 'fat': 6.0, + 'carbs': 24.0, + 'protein': 4.0, + 'sodium': 87.0, + 'calcium': 14.0, + 'iron': 1.0, + 'comments': 'I love froyo!', + 'actions': [{ + 'name': 'Action 1', + 'icon': 'fa fa-user', + 'tooltip': 'Manage Users' + }, { + 'name': 'Action 2', + 'icon': 'fa fa-key', + 'tooltip': 'Manage Permissions' + }] + }, { + 'id': 2, + 'name': 'Ice cream sandwich', + 'type': 'Ice cream', + 'calories': 237.0, + 'fat': 9.0, + 'carbs': 37.0, + 'protein': 4.3, + 'sodium': 129.0, + 'calcium': 8.0, + 'iron': 1.0, + 'actions': [{ + 'name': 'Action 1', + 'icon': 'fa fa-user', + 'tooltip': 'Manage Users' + }, { + 'name': 'Action 2', + 'icon': 'fa fa-key', + 'tooltip': 'Manage Permissions' + }, { + 'name': 'Action 3', + 'tooltip': 'Action 3' + }, { + 'name': 'Action 4', + 'disabled': true, + 'tooltip': 'Action 4' + }, { + 'name': 'Action 5', + 'tooltip': 'Action 5' + }] + }, { + 'id': 3, + 'name': 'Eclair', + 'type': 'Pastry', + 'calories': 262.0, + 'fat': 16.0, + 'carbs': 24.0, + 'protein': 6.0, + 'sodium': 337.0, + 'calcium': 6.0, + 'iron': 7.0, + 'actions': [{ + 'name': 'Action 1', + 'icon': 'fa fa-user', + 'tooltip': 'Manage Users' + }, { + 'name': 'Action 2', + 'icon': 'fa fa-key', + 'tooltip': 'Manage Permissions' + }, { + 'name': 'Action 3', + 'tooltip': 'Action 3' + }, { + 'name': 'Action 4', + 'disabled': true, + 'tooltip': 'Action 4' + }, { + 'name': 'Action 5', + 'tooltip': 'Action 5' + }], + }, { + 'id': 4, + 'name': 'Cupcake', + 'type': 'Pastry', + 'calories': 305.0, + 'fat': 3.7, + 'carbs': 67.0, + 'protein': 4.3, + 'sodium': 413.0, + 'calcium': 3.0, + 'iron': 8.0, + 'actions': [{ + 'name': 'Action 1', + 'icon': 'fa fa-user', + 'tooltip': 'Manage Users' + }, { + 'name': 'Action 2', + 'icon': 'fa fa-key', + 'tooltip': 'Manage Permissions' + }, { + 'name': 'Action 3', + 'tooltip': 'Action 3' + }, { + 'name': 'Action 4', + 'disabled': true, + 'tooltip': 'Action 4' + }, { + 'name': 'Action 5', + 'tooltip': 'Action 5' + }], + }, { + 'id': 5, + 'name': 'Jelly bean', + 'type': 'Candy', + 'calories': 375.0, + 'fat': 0.0, + 'carbs': 94.0, + 'protein': 0.0, + 'sodium': 50.0, + 'calcium': 0.0, + 'iron': 0.0, + }, { + 'id': 6, + 'name': 'Lollipop', + 'type': 'Candy', + 'calories': 392.0, + 'fat': 0.2, + 'carbs': 98.0, + 'protein': 0.0, + 'sodium': 38.0, + 'calcium': 0.0, + 'iron': 2.0, + }, { + 'id': 7, + 'name': 'Honeycomb', + 'type': 'Other', + 'calories': 408.0, + 'fat': 3.2, + 'carbs': 87.0, + 'protein': 6.5, + 'sodium': 562.0, + 'calcium': 0.0, + 'iron': 45.0, + }, { + 'id': 8, + 'name': 'Donut', + 'type': 'Pastry', + 'calories': 452.0, + 'fat': 25.0, + 'carbs': 51.0, + 'protein': 4.9, + 'sodium': 326.0, + 'calcium': 2.0, + 'iron': 22.0, + }, { + 'id': 9, + 'name': 'KitKat', + 'type': 'Candy', + 'calories': 518.0, + 'fat': 26.0, + 'carbs': 65.0, + 'protein': 7.0, + 'sodium': 54.0, + 'calcium': 12.0, + 'iron': 6.0, + }, { + 'id': 10, + 'name': 'Chocolate', + 'type': 'Candy', + 'calories': 518.0, + 'fat': 26.0, + 'carbs': 65.0, + 'protein': 7.0, + 'sodium': 54.0, + 'calcium': 12.0, + 'iron': 6.0, + }, { + 'id': 11, + 'name': 'Chamoy', + 'type': 'Candy', + 'calories': 518.0, + 'fat': 26.0, + 'carbs': 65.0, + 'protein': 7.0, + 'sodium': 54.0, + 'calcium': 12.0, + 'iron': 6.0, + },]; + + this.filteredData = this.data; + this.filteredTotal = this.data.length; + + this.columns = [ + {name: 'comments', label: 'Comments', width: 10}, + {name: 'name', label: 'Dessert (100g serving)', sortable: true, width: 10}, + {name: 'type', label: 'Type', sortable: true, width: 10}, + {name: 'calories', label: 'Calories', numeric: true, format: NUMBER_FORMAT, sortable: true, width: 10}, + {name: 'fat', label: 'Fat (g)', numeric: true, format: DECIMAL_FORMAT, sortable: true, width: 10}, + {name: 'carbs', label: 'Carbs (g)', numeric: true, format: NUMBER_FORMAT, sortable: true, width: 10}, + {name: 'protein', label: 'Protein (g)', numeric: true, format: DECIMAL_FORMAT, sortable: true, width: 10}, + {name: 'sodium', label: 'Sodium (mg)', numeric: true, format: NUMBER_FORMAT, sortable: true, width: 10}, + {name: 'calcium', label: 'Calcium (%)', numeric: true, format: NUMBER_FORMAT, sortable: true, width: 10}, + {name: 'iron', label: 'Iron (%)', numeric: true, format: NUMBER_FORMAT, width: 10}, + ]; + + this.allRowsSelected = false; + this.autoCompleteData = []; + this.selectedRows = []; + + this.searchTerm = []; + this.fromRow = 1; + this.currentPage = 1; + this.pageSize = 5; + this.pageCount = 0; + + // + + // + + this.readOnly = false; + + this.items = [ + 'stepper', + 'expansion-panel', + 'markdown', + 'highlight', + 'loading', + 'media', + 'chips', + 'http', + 'json-formatter', + 'pipes', + 'need more?', + ]; + + this.itemsRequireMatch = this.items.slice(0, 6); + + // + + // + + this.favoriteSeason = 'Autumn'; + + this.seasonOptions = [ + 'Winter', + 'Spring', + 'Summer', + 'Autumn', + ]; + + // + + // + + this.selectedValue = ''; + + this.foods = [ + {value: 'steak-0', viewValue: 'Steak'}, + {value: 'pizza-1', viewValue: 'Pizza'}, + {value: 'tacos-2', viewValue: 'Tacos'}, + ]; + + // + + // + + this.chips = [ + {name: 'Default', color: '', selected: false}, + {name: 'Default (selected)', color: '', selected: true}, + {name: 'Primary (selected)', color: 'primary', selected: true}, + {name: 'Accent (selected)', color: 'accent', selected: true}, + {name: 'Warn (selected)', color: 'warn', selected: true}, + ]; + + // + + // + + this.user = { + agreesToTOS: false + }; + + this.groceries = [{ + bought: true, + name: 'Seitan', + }, { + bought: false, + name: 'Almond Meal Flour', + }, { + bought: false, + name: 'Organic Eggs', + },]; + + // + + // + + this.systems = [{ + name: 'Lights', + on: false, + color: 'primary', + }, { + name: 'Surround Sound', + on: true, + color: 'accent', + }, { + name: 'T.V.', + on: true, + color: 'warn', + },]; + + this.house = { + lockHouse: false, + }; + + // +}; + +FdsDemo.prototype = { + constructor: FdsDemo, + + // + + displayFn: function (value) { + return value && typeof value === 'object' ? value.name : value; + }, + + filterStates: function (val) { + return val ? this.states.filter(function (s) { + return s.name.match(new RegExp(val, 'gi')); + }) : this.states; + }, + + // + + // + + showSnackBar: function () { + var snackBarRef = this.snackBarService.open('Message', 'Action', {duration: 3000}); + }, + + // + + // + + openDialog: function () { + this.dialog.open(NfRegistryExplorer, { + height: '50%', // can be px or % + width: '60%', // can be px or % + }); + }, + + // + + // + + toggleExpansion1: function () { + if (!this.disabled) { + this.expansion1 = !this.expansion1; + } + }, + + toggleDisabled: function () { + this.disabled = !this.disabled; + }, + + expandExpansion1Event: function () { + this.expandCollapseExpansion1Msg = 'Expand event emitted.'; + }, + + collapseExpansion1Event: function () { + this.expandCollapseExpansion1Msg = 'Collapse event emitted.'; + }, + + // + + // + + openAlert: function () { + this.dialogService.openAlert({ + title: 'Alert', + disableClose: true, + message: 'This is how simple it is to create an alert with this wrapper service.', + }); + }, + + openConfirm: function () { + this.dialogService.openConfirm({ + title: 'Confirm', + message: 'This is how simple it is to create a confirm with this wrapper service. Do you agree?', + cancelButton: 'Disagree', + acceptButton: 'Agree', + }); + }, + + openPrompt: function () { + this.dialogService.openPrompt({ + title: 'Prompt', + message: 'This is how simple it is to create a prompt with this wrapper service. Prompt something.', + value: 'Populated value', + cancelButton: 'Cancel', + acceptButton: 'Ok', + }); + }, + + // + + // + + isDropletFilterChecked: function (term) { + return (this.dropletsSearchTerms.indexOf(term) > -1); + }, + + getDropletTypeCount: function (type) { + return this.filteredDroplets.filter(function (droplet) { + return droplet.type === type; + }).length; + }, + + getDropletCertificationCount: function (certification) { + return this.filteredDroplets.filter(function (droplet) { + return Object.keys(droplet).find(function (key) { + if (key === certification && droplet[certification].type === 'certification') { + return droplet; + } + }); + }).length; + }, + + getSortBy: function () { + var sortByColumnLabel; + var arrayLength = this.dropletColumns.length; + for (var i = 0; i < arrayLength; i++) { + if (this.dropletColumns[i].active === true) { + sortByColumnLabel = this.dropletColumns[i].label; + break; + } + } + return sortByColumnLabel; + }, + + sortDroplets: function (sortEvent, column) { + if (column.sortable === true) { + // toggle column sort order + var sortOrder = column.sortOrder = (column.sortOrder === 'ASC') ? 'DESC' : 'ASC'; + this.filterDroplets(column.name, sortOrder); + this.activeColumn = column; + //only one column can be actively sorted so we reset all to inactive + this.dropletColumns.forEach(function (c) { + c.active = false; + }); + //and set this column as the actively sorted column + column.active = true; + } + }, + + dropletsSearchRemove: function (searchTerm) { + this.filterDroplets(this.activeColumn.name, this.activeColumn.sortOrder); + }, + + dropletsSearchAdd: function (searchTerm) { + this.filterDroplets(this.activeColumn.name, this.activeColumn.sortOrder); + }, + + toggleDropletsFilter: function (searchTerm) { + var applySearchTerm = true; + // check if the search term is already applied and remove it if true + if (this.dropletsSearchTerms.length > 0) { + var arrayLength = this.dropletsSearchTerms.length; + for (var i = 0; i < arrayLength; i++) { + var index = this.dropletsSearchTerms.indexOf(searchTerm); + if (index > -1) { + this.dropletsSearchTerms.splice(index, 1); + applySearchTerm = false; + } + } + } + + // if we just removed the search term do NOT apply it again + if (applySearchTerm) { + this.dropletsSearchTerms.push(searchTerm); + } + + this.filterDroplets(this.activeColumn.name, this.activeColumn.sortOrder); + }, + + filterDroplets: function (sortBy, sortOrder) { + // if `sortOrder` is `undefined` then use 'ASC' + if (sortOrder === undefined) { + sortOrder = 'ASC' + } + // if `sortBy` is `undefined` then find the first sortable column in this.dropletColumns + if (sortBy === undefined) { + var arrayLength = this.dropletColumns.length; + for (var i = 0; i < arrayLength; i++) { + if (this.dropletColumns[i].sortable === true) { + sortBy = this.dropletColumns[i].name; + this.activeColumn = this.dropletColumns[i]; + //only one column can be actively sorted so we reset all to inactive + this.dropletColumns.forEach(function (c) { + c.active = false; + }); + //and set this column as the actively sorted column + this.dropletColumns[i].active = true; + this.dropletColumns[i].sortOrder = sortOrder; + break; + } + } + } + + var newData = this.droplets; + + for (var i = 0; i < this.dropletsSearchTerms.length; i++) { + newData = this.filterData(newData, this.dropletsSearchTerms[i], true, this.activeColumn.name); + } + + newData = this.dataTableService.sortData(newData, sortBy, sortOrder); + this.filteredDroplets = newData; + this.getAutoCompleteDroplets(); + }, + + getAutoCompleteDroplets: function () { + var self = this; + this.autoCompleteDroplets = []; + this.dropletColumns.forEach(function (c) { + self.filteredDroplets.forEach(function (r) { + (r[c.name.toLowerCase()]) ? self.autoCompleteDroplets.push(r[c.name.toLowerCase()].toString()) : ''; + }); + }); + }, + + // + + filterData: function (data, searchTerm, ignoreCase) { + var field = ''; + if (searchTerm.indexOf(":") > -1) { + field = searchTerm.split(':')[0].trim(); + searchTerm = searchTerm.split(':')[1].trim(); + } + var filter = searchTerm ? (ignoreCase ? searchTerm.toLowerCase() : searchTerm) : ''; + + if (filter) { + data = data.filter(function (item) { + var res = Object.keys(item).find(function (key) { + if (field.indexOf(".") > -1) { + var objArray = field.split("."); + var obj = item; + var arrayLength = objArray.length; + for (var i = 0; i < arrayLength; i++) { + try { + obj = obj[objArray[i]]; + } catch (e) { + return false; + } + } + var preItemValue = ('' + obj); + var itemValue = ignoreCase ? preItemValue.toLowerCase() : preItemValue; + return itemValue.indexOf(filter) > -1; + } else { + if (key !== field && field !== '') { + return false; + } + var preItemValue = ('' + item[key]); + var itemValue = ignoreCase ? preItemValue.toLowerCase() : preItemValue; + return itemValue.indexOf(filter) > -1; + } + }); + return !(typeof res === 'undefined'); + }); + } + return data; + }, + + // + + sort: function (sortEvent, column) { + if (column.sortable) { + var sortBy = column.name; + var sortOrder = column.sortOrder = (column.sortOrder === 'ASC') ? 'DESC' : 'ASC'; + this.filter(sortBy, sortOrder); + + //only one column can be actively sorted so we reset all to inactive + this.columns.forEach(function (c) { + c.active = false; + }); + //and set this column as the actively sorted column + column.active = true; + } + }, + + searchRemove: function (searchTerm) { + //only remove the first occurrence of the search term + var index = this.searchTerm.indexOf(searchTerm); + if (index !== -1) { + this.searchTerm.splice(index, 1); + } + this.fromRow = 1; + this.currentPage = 1; + this.pageSize = 1; + this.filter(); + }, + + searchAdd: function (searchTerm) { + this.searchTerm.push(searchTerm); + this.fromRow = 1; + this.currentPage = 1; + this.pageSize = 1; + this.filter(); + }, + + page: function (pagingEvent) { + this.fromRow = pagingEvent.fromRow; + this.currentPage = pagingEvent.page; + this.pageSize = pagingEvent.pageSize; + this.filter(); + }, + + filter: function (sortBy, sortOrder) { + if (this.allRowsSelected) { + this.toggleSelectAll(); + } + this.deselectAll(); + var newData = this.data; + + for (var i = 0; i < this.searchTerm.length; i++) { + newData = this.filterData(newData, this.searchTerm[i], true); + } + this.filteredTotal = newData.length; + newData = this.dataTableService.sortData(newData, sortBy, sortOrder); + this.pageCount = newData.length; + newData = this.dataTableService.pageData(newData, this.fromRow, this.currentPage * this.pageSize); + this.filteredData = newData; + this.getAutoCompleteData(); + }, + + toggleSelect: function (row) { + if (this.allFilteredRowsSelected()) { + this.allRowsSelected = true; + } else { + this.allRowsSelected = false; + } + }, + + toggleSelectAll: function () { + if (this.allRowsSelected) { + this.selectAll(); + } else { + this.deselectAll(); + } + }, + + selectAll: function () { + this.filteredData.forEach(function (c) { + c.checked = true; + }); + }, + + deselectAll: function () { + this.filteredData.forEach(function (c) { + c.checked = false; + }); + }, + + allFilteredRowsSelected: function () { + var allFilteredRowsSelected = true; + this.filteredData.forEach(function (c) { + if (c.checked === undefined || c.checked === false) { + allFilteredRowsSelected = false; + } + }); + + return allFilteredRowsSelected; + }, + + areTooltipsOn: function () { + return this.columns[0].hasOwnProperty('tooltip'); + }, + + toggleTooltips: function () { + if (this.columns[0].tooltip) { + this.columns.forEach(function (c) { + delete c.tooltip; + }); + } else { + this.columns.forEach(function (c) { + c.tooltip = 'This is ' + c.label + '!'; + }); + } + }, + + openDataTablePrompt: function (row, name) { + this.dialogService.openPrompt({ + message: 'Enter comment?', + value: row[name], + }).afterClosed().subscribe(function (value) { + if (value !== undefined) { + row[name] = value; + } + }) + }, + + getAutoCompleteData: function () { + var self = this; + this.autoCompleteData = []; + this.columns.forEach(function (c) { + self.filteredData.forEach(function (r) { + (r[c.name.toLowerCase()]) ? self.autoCompleteData.push(r[c.name.toLowerCase()].toString()) : ''; + }); + }); + }, + + // + + // + + toggleReadOnly: function () { + this.readOnly = !this.readOnly; + }, + + // + + // + + /** + * Initialize the component + */ + ngOnInit: function () { + this.filter(); + this.filterDroplets(); + } + + // +}; + +FdsDemo.annotations = [ + new ngCore.Component({ + template: require('./fds-demo.html!text'), + animations: [nfRegistryAnimations.slideInLeftAnimation], + host: { + '[@routeAnimation]': 'routeAnimation' + } + }) +]; + +FdsDemo.parameters = [ngMaterial.MdSnackBar, ngMaterial.MdDialog, covalentCore.TdDataTableService, fdsDialogsModule.FdsDialogService]; + +module.exports = FdsDemo; diff --git a/nifi-registry-web-ui/src/main/webapp/components/page-not-found/nf-registry-page-not-found.js b/nifi-registry-web-ui/src/main/webapp/components/page-not-found/nf-registry-page-not-found.js new file mode 100644 index 000000000..26c676b27 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/components/page-not-found/nf-registry-page-not-found.js @@ -0,0 +1,36 @@ +/* + * 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. + */ +var ngCore = require('@angular/core'); + +/** + * NfPageNotFoundComponent constructor. + */ +function NfPageNotFoundComponent() { + this.title = "Page Not Found!!!!"; +}; + +NfPageNotFoundComponent.prototype = { + constructor: NfPageNotFoundComponent +}; + +NfPageNotFoundComponent.annotations = [ + new ngCore.Component({ + template: '

Hello {{title}}!

' + }) +]; + +module.exports = NfPageNotFoundComponent; diff --git a/nifi-registry-web-ui/src/main/webapp/images/registry-favicon.png b/nifi-registry-web-ui/src/main/webapp/images/registry-favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..87dc8c96b15770f9d5e3d235753d7a8e18837189 GIT binary patch literal 388 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4(FKVD$EMaSXBOO-^WN`v3ob@`G=d z+^x5s>zEu@V`ui^iEuc6$CXL8SiIE0z+g{8Lc)s_AaSGQ!wT=?Pckn{N=gP^IaKLs z>ib_(LPElBPvzMMj}p#*_;@;;4Ftr}(%2+9Ki28_oeKeS=VedVJGbJ@>2pV3H_6-A zAG$gJ-rm#)j~|{)PDpr=2sHS@rOW3tUcAdal-bbGp>cR-@pH)^l{@}B@K*o+^YZfl z6Im4%Kev3?)zCb>|Ka25>vsd~U#$CqG&8{C}mdHAx$;Q^!Zor(l@!+8b_8hBuVe|I7&daP84g4XSIrUgucnpA|X-Aeb+@0^j++%P+yyFMMwGxLlX=~UfERsCT g5M*i$3?2ps&WY24T0b`31%@tzr>mdKI;Vst0OQK2^Z)<= literal 0 HcmV?d00001 diff --git a/nifi-registry-web-ui/src/main/webapp/images/registry-logo-web-app.svg b/nifi-registry-web-ui/src/main/webapp/images/registry-logo-web-app.svg new file mode 100644 index 000000000..25cf2ae2c --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/images/registry-logo-web-app.svg @@ -0,0 +1,17 @@ + +registry-logo-web-app \ No newline at end of file diff --git a/nifi-registry-web-ui/src/main/webapp/nf-registry-bootstrap.js b/nifi-registry-web-ui/src/main/webapp/nf-registry-bootstrap.js new file mode 100644 index 000000000..91cb63895 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/nf-registry-bootstrap.js @@ -0,0 +1,52 @@ +/* + * 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. + */ + +require('core-js'); +require('zone.js'); +require('hammerjs'); +require('switchMap'); +var $ = require('jquery'); +var NfRegistryModule = require('nifi-registry/nf-registry.module.js'); +var ngPlatformBrowserDynamic = require('@angular/platform-browser-dynamic'); +var ngCore = require('@angular/core'); + +// Comment out this line when developing to assert for unidirectional data flow +ngCore.enableProdMode(); + +// Get the locale id from the global +var locale = navigator.language; + +var providers = []; + +// No locale or U.S. English: no translation providers so go ahead and bootstrap the app +if (!locale || locale === 'en-US') { + ngPlatformBrowserDynamic.platformBrowserDynamic().bootstrapModule(NfRegistryModule, {providers: providers}); +} else { //load the translation providers and bootstrap the module + var translationFile = './nifi-registry/messages.' + locale + '.xlf'; + + $.ajax({ + url: translationFile + }).done(function (translations) { + // add providers if translation file for locale is loaded + if (translations) { + providers.push({provide: ngCore.TRANSLATIONS, useValue: translations}); + providers.push({provide: ngCore.TRANSLATIONS_FORMAT, useValue: 'xlf'}); + providers.push({provide: ngCore.LOCALE_ID, useValue: locale}); + } + ngPlatformBrowserDynamic.platformBrowserDynamic().bootstrapModule(NfRegistryModule, {providers: providers}); + }).fail(ngPlatformBrowserDynamic.platformBrowserDynamic().bootstrapModule(NfRegistryModule, {providers: providers})); +} \ No newline at end of file diff --git a/nifi-registry-web-ui/src/main/webapp/nf-registry.animations.js b/nifi-registry-web-ui/src/main/webapp/nf-registry.animations.js new file mode 100644 index 000000000..c44601278 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/nf-registry.animations.js @@ -0,0 +1,119 @@ +/* + * 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. + */ + +var ngAnimate = require('@angular/animations'); + +/** + * NfAnimations constructor. + * + * @constructor + */ +function NfAnimations() { +}; + +NfAnimations.prototype = { + constructor: NfAnimations, + + /** + * Fade animation + */ + fadeAnimation: ngAnimate.trigger('routeAnimation', [ + ngAnimate.state('*', + ngAnimate.style({ + opacity: 1 + }) + ), + ngAnimate.transition(':enter', [ + ngAnimate.style({ + opacity: 0 + }), + ngAnimate.animate('0.3s ease-in') + ]), + ngAnimate.transition(':leave', [ + ngAnimate.animate('0.5s ease-out', ngAnimate.style({ + opacity: 0 + })) + ]) + ]), + + /** + * Slide in from the left animation + */ + slideInLeftAnimation: ngAnimate.trigger('routeAnimation', [ + ngAnimate.state('*', + ngAnimate.style({ + opacity: 1, + transform: 'translateX(0)' + }) + ), + ngAnimate.transition(':enter', [ + ngAnimate.style({ + opacity: 0, + transform: 'translateX(-100%)' + }), + ngAnimate.animate('0.3s ease-in') + ]), + ngAnimate.transition(':leave', [ + ngAnimate.animate('0.5s ease-out', ngAnimate.style({ + opacity: 0, + transform: 'translateX(100%)' + })) + ]) + ]), + + /** + * Slide in from the top animation + */ + slideInDownAnimation: ngAnimate.trigger('routeAnimation', [ + ngAnimate.state('*', + ngAnimate.style({ + opacity: 1, + transform: 'translateY(0)' + }) + ), + ngAnimate.transition(':enter', [ + ngAnimate.style({ + opacity: 0, + transform: 'translateY(-100%)' + }), + ngAnimate.animate('0.3s ease-in') + ]), + ngAnimate.transition(':leave', [ + ngAnimate.animate('0.5s ease-out', ngAnimate.style({ + opacity: 0, + transform: 'translateY(100%)' + })) + ]) + ]), + + /** + * Fly in/out animation + */ + flyInOutAnimation: ngAnimate.trigger('flyInOut', [ + ngAnimate.state('in', + ngAnimate.style({transform: 'translateX(0)'}) + ), + ngAnimate.transition('void => *', [ + ngAnimate.style({transform: 'translateX(100%)'}), + ngAnimate.animate('0.5s 0.1s ease-in') + ]), + ngAnimate.transition('* => void', ngAnimate.animate('0.3s ease-out', ngAnimate.style({transform: 'translateX(-100%)'}))) + ]) + +}; + +module.exports = new NfAnimations(); \ No newline at end of file diff --git a/nifi-registry-web-ui/src/main/webapp/nf-registry.e2e-spec.js b/nifi-registry-web-ui/src/main/webapp/nf-registry.e2e-spec.js new file mode 100644 index 000000000..fdf10bd14 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/nf-registry.e2e-spec.js @@ -0,0 +1,30 @@ +/* + * 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. + */ + +var protractor = require('protractor'); + +describe('NifiRegistry E2E Tests', function () { + + beforeEach(function () { + protractor.browser.get(''); + }); + + it('true is true', function () { + expect(true).toEqual(true); + }); + +}); diff --git a/nifi-registry-web-ui/src/main/webapp/nf-registry.html b/nifi-registry-web-ui/src/main/webapp/nf-registry.html new file mode 100644 index 000000000..f8798dd3e --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/nf-registry.html @@ -0,0 +1,88 @@ + + + + + + +
+ + +
+ {{nfRegistryService.registry.name}} + + + + / Administration + / {{nfRegistryService.bucket.name}} + / All + + + + + / {{nfRegistryService.droplet.name}} + / All + + + + +
+
+ {{nfRegistryService.alerts.length}} +
+ + + +
+
+ +
+
+
diff --git a/nifi-registry-web-ui/src/main/webapp/nf-registry.js b/nifi-registry-web-ui/src/main/webapp/nf-registry.js new file mode 100644 index 000000000..4c9263b87 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/nf-registry.js @@ -0,0 +1,59 @@ +/* + * 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. + */ + +var ngCore = require('@angular/core'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var nfRegistryAnimations = require('nifi-registry/nf-registry.animations.js'); + +function NfRegistry(nfRegistryService, changeDetectorRef) { + this.nfRegistryService = nfRegistryService; + this.cd = changeDetectorRef; +}; + +NfRegistry.prototype = { + constructor: NfRegistry, + + ngOnInit: function () { + var self = this; + this.nfRegistryService.sidenav = this.sidenav; + this.nfRegistryService.getRegistries().then(function (registries) { + self.nfRegistryService.registries = registries; + }); + }, + + ngAfterViewChecked: function () { + // since the child views are updating the nfRegistryService values that are used to display + // the breadcrumbs in this component's view we need to manually detect changes at the correct + // point in the lifecycle. + this.cd.detectChanges(); + } +}; + +NfRegistry.annotations = [ + new ngCore.Component({ + selector: 'nf-registry-app', + template: require('./nf-registry.html!text'), + queries: { + sidenav: new ngCore.ViewChild('sidenav') + }, + animations: [nfRegistryAnimations.flyInOutAnimation] + }) +]; + +NfRegistry.parameters = [NfRegistryService, ngCore.ChangeDetectorRef]; + +module.exports = NfRegistry; diff --git a/nifi-registry-web-ui/src/main/webapp/nf-registry.module.js b/nifi-registry-web-ui/src/main/webapp/nf-registry.module.js new file mode 100644 index 000000000..9e83795df --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/nf-registry.module.js @@ -0,0 +1,60 @@ +/* + * 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. + */ + +var ngCore = require('@angular/core'); +var ngMoment = require('angular2-moment'); +var NfRegistryRoutes = require('nifi-registry/nf-registry.routes.js'); +var FdsDemo = require('nifi-registry/components/fluid-design-system/fds-demo.js'); +var NfRegistry = require('nifi-registry/nf-registry.js'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var NfPageNotFoundComponent = require('nifi-registry/components/page-not-found/nf-registry-page-not-found.js'); +var NfRegistryExplorer = require('nifi-registry/components/explorer/nf-registry-explorer.js'); +var NfRegistryExplorerGridListViewer = require('nifi-registry/components/explorer/grid-list/nf-registry-explorer-grid-list-viewer.js'); +var NfRegistryAdministration = require('nifi-registry/components/administration/nf-registry-administration.js'); +var NfRegistryGeneralAdministration = require('nifi-registry/components/administration/general/nf-registry-general-administration.js'); +var NfRegistryUsersAdministration = require('nifi-registry/components/administration/users/nf-registry-users-administration.js'); +var NfRegistryAddUser = require('nifi-registry/components/administration/users/add/nf-registry-add-user.js'); +var NfRegistryUserDetails = require('nifi-registry/components/administration/users/details/nf-registry-user-details.js'); +var NfRegistryUserPermissions = require('nifi-registry/components/administration/users/permissions/nf-registry-user-permissions.js'); +var NfRegistryBucketPermissions = require('nifi-registry/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js'); +var NfRegistryWorkflowAdministration = require('nifi-registry/components/administration/workflow/nf-registry-workflow-administration.js'); +var NfRegistryGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.js'); +var NfRegistryBucketGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/bucket/nf-registry-bucket-grid-list-viewer.js'); +var NfRegistryDropletGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/bucket/droplet/nf-registry-droplet-grid-list-viewer.js'); +var fdsCore = require('@fluid-design-system/core'); + +function NfRegistryModule() { +}; + +NfRegistryModule.prototype = { + constructor: NfRegistryModule +}; + +NfRegistryModule.annotations = [ + new ngCore.NgModule({ + imports: [ + ngMoment.MomentModule, + fdsCore, + NfRegistryRoutes + ], + declarations: [FdsDemo, NfRegistry, NfRegistryExplorer, NfRegistryExplorerGridListViewer, NfRegistryAdministration, NfRegistryGeneralAdministration, NfRegistryUsersAdministration, NfRegistryUserDetails, NfRegistryUserPermissions, NfRegistryBucketPermissions, NfRegistryAddUser, NfRegistryWorkflowAdministration, NfRegistryGridListViewer, NfRegistryBucketGridListViewer, NfRegistryDropletGridListViewer, NfPageNotFoundComponent], + providers: [NfRegistryService], + bootstrap: [NfRegistry] + }) +]; + +module.exports = NfRegistryModule; \ No newline at end of file diff --git a/nifi-registry-web-ui/src/main/webapp/nf-registry.routes.js b/nifi-registry-web-ui/src/main/webapp/nf-registry.routes.js new file mode 100644 index 000000000..46bcbeca8 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/nf-registry.routes.js @@ -0,0 +1,104 @@ +/* + * 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. + */ + +var ngRouter = require('@angular/router'); +var FdsDemo = require('nifi-registry/components/fluid-design-system/fds-demo.js'); +var NfPageNotFoundComponent = require('nifi-registry/components/page-not-found/nf-registry-page-not-found.js'); +var NfRegistryExplorer = require('nifi-registry/components/explorer/nf-registry-explorer.js'); +var NfRegistryExplorerGridListViewer = require('nifi-registry/components/explorer/grid-list/nf-registry-explorer-grid-list-viewer.js'); +var NfRegistryAdministration = require('nifi-registry/components/administration/nf-registry-administration.js'); +var NfRegistryGeneralAdministration = require('nifi-registry/components/administration/general/nf-registry-general-administration.js'); +var NfRegistryUsersAdministration = require('nifi-registry/components/administration/users/nf-registry-users-administration.js'); +var NfRegistryAddUser = require('nifi-registry/components/administration/users/add/nf-registry-add-user.js'); +var NfRegistryUserDetails = require('nifi-registry/components/administration/users/details/nf-registry-user-details.js'); +var NfRegistryUserPermissions = require('nifi-registry/components/administration/users/permissions/nf-registry-user-permissions.js'); +var NfRegistryBucketPermissions = require('nifi-registry/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js'); +var NfRegistryWorkflowAdministration = require('nifi-registry/components/administration/workflow/nf-registry-workflow-administration.js'); +var NfRegistryGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.js'); +var NfRegistryBucketGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/bucket/nf-registry-bucket-grid-list-viewer.js'); +var NfRegistryDropletGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/bucket/droplet/nf-registry-droplet-grid-list-viewer.js'); + +var NfRegistryRoutes = new ngRouter.RouterModule.forRoot([{ + path: 'nifi-registry/explorer', + component: NfRegistryExplorer, + children: [{ + path: 'grid-list', + component: NfRegistryExplorerGridListViewer, + children: [{ + path: ':registryId', + component: NfRegistryGridListViewer, + children: [{ + path: ':bucketId', + component: NfRegistryBucketGridListViewer, + children: [{ + path: ':dropletId', + component: NfRegistryDropletGridListViewer + }] + }] + }] + }] + // canActivate: [AuthGuard] //TODO: https://angular.io/api/router/CanActivate https://scotch.io/tutorials/routing-angular-2-single-page-apps-with-the-component-router +}, { + path: 'nifi-registry/fluid-design-system', + component: FdsDemo +}, { + path: 'nifi-registry/administration/:registryId', + component: NfRegistryAdministration, + children: [{ + path: '', + redirectTo: 'general', + pathMatch: 'full' + }, { + path: 'general', + component: NfRegistryGeneralAdministration + }, { + path: 'users', + component: NfRegistryUsersAdministration + }, { + path: 'workflow', + component: NfRegistryWorkflowAdministration + }] +}, { + path: 'nifi-registry', + redirectTo: '/nifi-registry/explorer/grid-list/23f6cc59-0156-1000-06b4-2b0810089090', + pathMatch: 'full' +}, { + path: '', + redirectTo: '/nifi-registry/explorer/grid-list/23f6cc59-0156-1000-06b4-2b0810089090', + pathMatch: 'full' +}, { + path: '**', + component: NfPageNotFoundComponent +}, { + path: 'user/details/:userId', + component: NfRegistryUserDetails, + outlet: 'sidenav' +}, { + path: 'user/permissions/:userId', + component: NfRegistryUserPermissions, + outlet: 'sidenav' +}, { + path: 'user/add', + component: NfRegistryAddUser, + outlet: 'sidenav' +}, { + path: 'bucket/permissions/:bucketId', + component: NfRegistryBucketPermissions, + outlet: 'sidenav' +}]); + +module.exports = NfRegistryRoutes; \ No newline at end of file diff --git a/nifi-registry-web-ui/src/main/webapp/nf-registry.spec.js b/nifi-registry-web-ui/src/main/webapp/nf-registry.spec.js new file mode 100644 index 000000000..7ed120603 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/nf-registry.spec.js @@ -0,0 +1,63 @@ +/* + * 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. + */ + +var NfRegistryRoutes = require('nifi-registry/nf-registry.routes.js'); +var ngCoreTesting = require('@angular/core/testing'); +var ngCommon = require('@angular/common'); +var FdsDemo = require('nifi-registry/components/fluid-design-system/fds-demo.js'); +var NfRegistry = require('nifi-registry/nf-registry.js'); +var NfRegistryService = require('nifi-registry/services/nf-registry.service.js'); +var NfPageNotFoundComponent = require('nifi-registry/components/page-not-found/nf-registry-page-not-found.js'); +var NfRegistryExplorer = require('nifi-registry/components/explorer/nf-registry-explorer.js'); +var NfRegistryExplorerGridListViewer = require('nifi-registry/components/explorer/grid-list/nf-registry-explorer-grid-list-viewer.js'); +var NfRegistryAdministration = require('nifi-registry/components/administration/nf-registry-administration.js'); +var NfRegistryGeneralAdministration = require('nifi-registry/components/administration/general/nf-registry-general-administration.js'); +var NfRegistryUsersAdministration = require('nifi-registry/components/administration/users/nf-registry-users-administration.js'); +var NfRegistryAddUser = require('nifi-registry/components/administration/users/add/nf-registry-add-user.js'); +var NfRegistryUserDetails = require('nifi-registry/components/administration/users/details/nf-registry-user-details.js'); +var NfRegistryUserPermissions = require('nifi-registry/components/administration/users/permissions/nf-registry-user-permissions.js'); +var NfRegistryBucketDetails = require('nifi-registry/components/administration/workflow/buckets/details/nf-registry-bucket-details.js'); +var NfRegistryBucketPermissions = require('nifi-registry/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js'); +var NfRegistryWorkflowAdministration = require('nifi-registry/components/administration/workflow/nf-registry-workflow-administration.js'); +var NfRegistryGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.js'); +var NfRegistryBucketGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/bucket/nf-registry-bucket-grid-list-viewer.js'); +var NfRegistryDropletGridListViewer = require('nifi-registry/components/explorer/grid-list/registry/bucket/droplet/nf-registry-droplet-grid-list-viewer.js'); +var fdsCore = require('@fluid-design-system/core'); + +describe('NfRegistry Component', function () { + var comp; + var fixture; + + beforeEach(ngCoreTesting.async(function () { + ngCoreTesting.TestBed.configureTestingModule({ + imports: [ + fdsCore, + NfRegistryRoutes + ], + declarations: [FdsDemo, NfRegistry, NfRegistryExplorer, NfRegistryExplorerGridListViewer, NfRegistryAdministration, NfRegistryGeneralAdministration, NfRegistryUsersAdministration, NfRegistryUserDetails, NfRegistryUserPermissions, NfRegistryBucketDetails, NfRegistryBucketPermissions, NfRegistryAddUser, NfRegistryWorkflowAdministration, NfRegistryGridListViewer, NfRegistryBucketGridListViewer, NfRegistryDropletGridListViewer, NfPageNotFoundComponent], + providers: [NfRegistryService, {provide: ngCommon.APP_BASE_HREF, useValue: '/'}], + bootstrap: [NfRegistry] + }); + })); + + it('should create component', function () { + fixture = ngCoreTesting.TestBed.createComponent(NfRegistry); + fixture.detectChanges(); + comp = fixture.componentInstance; + expect(comp).toBeDefined() + }); +}); \ No newline at end of file diff --git a/nifi-registry-web-ui/src/main/webapp/services/nf-registry.service.js b/nifi-registry-web-ui/src/main/webapp/services/nf-registry.service.js new file mode 100644 index 000000000..55f58d120 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/services/nf-registry.service.js @@ -0,0 +1,981 @@ +/* + * 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. + */ + +var covalentCore = require('@covalent/core'); + +function filterData(data, searchTerm, ignoreCase) { + var field = ''; + if (searchTerm.indexOf(":") > -1) { + field = searchTerm.split(':')[0].trim(); + searchTerm = searchTerm.split(':')[1].trim(); + } + var filter = searchTerm ? (ignoreCase ? searchTerm.toLowerCase() : searchTerm) : ''; + + if (filter) { + data = data.filter(function (item) { + var res = Object.keys(item).find(function (key) { + if (field.indexOf(".") > -1) { + var objArray = field.split("."); + var obj = item; + var arrayLength = objArray.length; + for (var i = 0; i < arrayLength; i++) { + try { + obj = obj[objArray[i]]; + } catch (e) { + return false; + } + } + var preItemValue = ('' + obj); + var itemValue = ignoreCase ? preItemValue.toLowerCase() : preItemValue; + return itemValue.indexOf(filter) > -1; + } else { + if (key !== field && field !== '') { + return false; + } + var preItemValue = ('' + item[key]); + var itemValue = ignoreCase ? preItemValue.toLowerCase() : preItemValue; + return itemValue.indexOf(filter) > -1; + } + }); + return !(typeof res === 'undefined'); + }); + } + return data; +}; + +function NfRegistryService(TdDataTableService) { + this.registries = []; + this.registry = {}; + this.bucket = {}; + this.buckets = []; + this.droplet = {}; + this.droplets = []; + this.certifications = []; + this.user = {}; + this.users = []; + this.alerts = []; + this.explorerViewType = ''; + this.perspective = ''; + this.breadCrumbState = 'out'; + this.dataTableService = TdDataTableService; + + this.filteredDroplets = []; + + this.dropletColumns = [ + {name: 'name', label: 'Name', sortable: true}, + {name: 'updated', label: 'Updated', sortable: true} + ]; + + this.autoCompleteDroplets = []; + this.dropletsSearchTerms = []; + + this.filteredBuckets = []; + + this.bucketColumns = [ + {name: 'name', label: 'Bucket Name', sortable: true, tooltip: 'Sort Buckets by name.'} + ]; + + this.allBucketsSelected = false; + this.autoCompleteBuckets = []; + this.bucketsSearchTerms = []; + + this.filteredUsers = []; + + this.userColumns = [ + {name: 'status', label: 'Status', sortable: true, tooltip: 'User Status.', width: 18}, + {name: 'name', label: 'Name', sortable: true, tooltip: 'User name.', width: 30}, + {name: 'provider', label: 'Provider', sortable: true, tooltip: 'Authentication provider.', width: 30} + ]; + + this.allUsersSelected = false; + this.autoCompleteUsers = []; + this.selectedUsers = []; + + this.usersSearchTerms = []; + this.usersFromRow = 1; + this.usersCurrentPage = 1; + this.usersPageSize = 5; + this.usersPageCount = 0; + + this.filteredCertifications = []; + + this.certificationColumns = [ + {name: 'name', label: 'Label Name', sortable: true, tooltip: 'Sort Certifications by name.', width: 40}, + {name: 'usage', label: 'Usage', sortable: true, tooltip: 'Sort Certifications by usage.', width: 30}, + {name: 'badge', label: 'Badge Design', sortable: false, tooltip: 'Certification badge.', width: 30} + ]; + + this.autoCompleteCertifications = []; + this.certificationsSearchTerms = []; +}; + +NfRegistryService.prototype = { + constructor: NfRegistryService, + + deleteDroplet: function (id) { + //TODO: REST call to API to delete droplet by id. + }, + + deleteBucket: function (id) { + //TODO: REST call to API to delete bucket by id. + }, + + deleteUser: function (id) { + //TODO: REST call to API to delete user by id. + }, + + suspendUser: function (id) { + //TODO: REST call to API to suspend user by id. + }, + + getRegistries: function () { + //TODO: leverage $http service to make call to nifi registry api. For now just return mock data... + var self = this; + var date = new Date(); + return new Promise( + function (resolve) { + setTimeout( + function () { + resolve(self.registries = [{ + id: '23f6cc59-0156-1000-06b4-2b0810089090', + name: "Nifi Registry", + users: [{ + id: '23f6cc59-0156-1000-06b4-2b0810089090', + name: 'Scotty 2 Hotty', + status: 'authorized', + provider: 'Friendly LDAP Provider', + type: 'user', + activities: [{ + id: '25fd6vv87-3249-0001-05g6-4d4767890765', + description: 'Saved something...', + created: date.setDate(date.getDate() - 1), + updated: new Date() + }], + actions: [{ + 'name': 'details', + 'icon': 'fa fa-info-circle', + 'tooltip': 'User Details', + 'type': 'sidenav', + + }, { + 'name': 'permissions', + 'icon': 'fa fa-key', + 'tooltip': 'Manage User Policies', + 'type': 'sidenav' + }, { + 'name': 'Delete', + 'icon': 'fa fa-trash', + 'tooltip': 'Delete User' + }, { + 'name': 'Suspend', + 'icon': 'fa fa-ban', + 'tooltip': 'Suspend User' + }] + }, { + id: '25fd6vv87-3249-0001-05g6-4d4767890765', + name: 'Group 1', + status: 'suspended', + provider: 'IOAT', + type: 'group', + actions: [{ + 'name': 'details', + 'icon': 'fa fa-info-circle', + 'tooltip': 'User Details', + 'type': 'sidenav' + }, { + 'name': 'permissions', + 'icon': 'fa fa-key', + 'tooltip': 'Manage User Policies', + 'type': 'sidenav' + }, { + 'name': 'Delete', + 'icon': 'fa fa-trash', + 'tooltip': 'Delete User' + }, { + 'name': 'Reauthorize', + 'icon': 'fa fa-check-circle', + 'tooltip': 'Reauthorize User' + }] + }, { + id: '98f6cc59-0156-1000-06b4-2b0810089090', + name: 'G$', + status: 'authorized', + provider: 'Friendly LDAP Provider', + type: 'user', + actions: [{ + 'name': 'details', + 'icon': 'fa fa-info-circle', + 'tooltip': 'User Details', + 'type': 'sidenav' + }, { + 'name': 'permissions', + 'icon': 'fa fa-key', + 'tooltip': 'Manage User Policies', + 'type': 'sidenav' + }, { + 'name': 'Delete', + 'icon': 'fa fa-trash', + 'tooltip': 'Delete User' + }, { + 'name': 'Suspend', + 'icon': 'fa fa-ban', + 'tooltip': 'Suspend User' + }] + }, { + id: '65fd6vv87-3249-0001-05g6-4d4767890765', + name: 'Group 2', + status: 'suspended', + provider: 'IOAT', + type: 'group', + actions: [{ + 'name': 'details', + 'icon': 'fa fa-info-circle', + 'tooltip': 'User Details', + 'type': 'sidenav' + }, { + 'name': 'permissions', + 'icon': 'fa fa-key', + 'tooltip': 'Manage User Policies', + 'type': 'sidenav' + }, { + 'name': 'Delete', + 'icon': 'fa fa-trash', + 'tooltip': 'Delete User' + }, { + 'name': 'Reauthorize', + 'icon': 'fa fa-check-circle', + 'tooltip': 'Reauthorize User' + }] + }], + buckets: [{ + id: '25fd6vv87-3549-0001-05g6-4d4567890765', + name: "My Flows", + actions: [{ + 'name': 'permissions', + 'icon': 'fa fa-key', + 'tooltip': 'Manage Bucket Policies', + 'type': 'sidenav' + }, { + 'name': 'Delete', + 'icon': 'fa fa-trash', + 'tooltip': 'Delete Bucket' + }], + droplets: [{ + id: '23f6cc59-0156-1000-09b4-2b0610089090', + name: "Security_Dev_Ops", + displayName: 'Security Dev Ops', + type: 'Data Flow', + sublabel: 'Some info', + updated: new Date(), + description: 'This is the most secure flow ever!', + versions: [{ + id: '23f6cc59-0156-1000-06b4-2b0810089090', + revision: '1', + dependentFlows: [{ + id: '25fd6vv87-3549-0001-05g6-4d4567890765' + }], + author: '2Hot', + comment: 'delete ListenHttp', + created: new Date(date.setDate(date.getDate() - 1)), + updated: new Date() + }, { + id: '25fd6vv87-3549-0001-05g6-4d4567890765', + revision: '2', + dependentFlows: [{ + id: '23f6cc59-0156-1000-06b4-2b0810089090' + }], + author: '2Hot', + comment: 'added Labels for better description of groups of processors', + created: new Date(), + updated: new Date() + }], + flows: [], + extensions: [], + assets: [], + actions: [{ + 'name': 'Delete', + 'icon': 'fa fa-close', + 'tooltip': 'Delete User' + }] + }] + }, { + id: '23f6cc59-0156-1000-09b4-2b0810089080', + name: "Development Flows", + droplets: [{ + id: '23f6cc59-0156-1000-09b4-2b0610089090', + name: "Fraud Detection Flow", + displayName: 'Fraud Detection Flow', + type: 'Data Flow', + sublabel: 'A sublabel', + updated: new Date(date.setDate(date.getDate() - 2)), + description: 'This flow detects fraud!', + versions: [{ + id: '23f6cc59-0156-1000-06b4-2b0810089090', + revision: '1', + dependentFlows: [{ + id: '25fd6vv87-3549-0001-05g6-4d4567890765' + }], + author: 'G$', + comment: 'added funnel', + created: new Date(date.setDate(date.getDate() - 1)), + updated: new Date() + }, { + id: '25fd6vv87-3549-0001-05g6-4d4567890765', + revision: '2', + dependentFlows: [{ + id: '23f6cc59-0156-1000-06b4-2b0810089090' + }], + author: '2Hot', + comment: 'added Execute script', + created: new Date(date.setDate(date.getDate() - 1)), + updated: new Date() + }, { + id: '77fd6vv87-3549-0001-05g6-4d4567890765', + revision: '3', + dependentFlows: [{ + id: '23f6cc59-0156-1000-06b4-2b0810089090' + }], + author: 'Payne', + comment: 'removed Execute script', + created: new Date(date.setDate(date.getDate() - 1)), + updated: new Date() + }, { + id: '96fd6vv87-3549-0001-05g6-4d4567890765', + revision: '4', + dependentFlows: [{ + id: '23f6cc59-0156-1000-06b4-2b0810089090' + }], + author: 'G$', + comment: 'add Execute script', + created: new Date(date.setDate(date.getDate() - 1)), + updated: new Date() + }], + flows: [], + extensions: [], + assets: [], + actions: [{ + 'name': 'Delete', + 'icon': 'fa fa-close' + }] + }, { + id: '59f6cc23-0156-1000-09b4-2b0610089090', + name: "Cyber Security", + displayName: 'Cyber Security', + type: 'Data Flow', + sublabel: 'A sublabel', + updated: new Date(date.setDate(date.getDate() - 1)), + description: 'This is the most cyber secure flow ever!', + versions: [{ + id: '23f6cc59-0156-1000-06b4-2b0810089090', + revision: '1', + dependentFlows: [{ + id: '25fd6vv87-3549-0001-05g6-4d4567890765' + }], + author: 'G$', + comment: 'added funnel', + created: new Date(date.setDate(date.getDate() - 1)), + updated: new Date() + }], + flows: [], + extensions: [], + assets: [], + actions: [{ + 'name': 'Delete', + 'icon': 'fa fa-close', + 'tooltip': 'Delete User' + }] + }], + actions: [{ + 'name': 'permissions', + 'icon': 'fa fa-key', + 'tooltip': 'Manage Bucket Policies', + 'type': 'sidenav' + }, { + 'name': 'Delete', + 'icon': 'fa fa-trash', + 'tooltip': 'Delete Bucket' + }] + }] // some data model for the contents of a registry + }]) + }, 0); + } + ); + }, + + getRegistry: function (registryId) { + return this.getRegistries().then( + function (registries) { + return registries.find( + function (registry) { + if (registryId === registry.id) { + return registry; + } + }); + }); + }, + + getDroplet: function (registryId, bucketId, dropletId) { + return this.getDroplets(registryId, bucketId, dropletId).then( + function (droplets) { + return droplets[0]; + }); + }, + + getDroplets: function (registryIds, bucketIds, dropletIds) { + var self = this; + return this.getRegistries().then( + function (registries) { + var buckets = []; + + registries.find( + function (registry) { + if (registryIds === undefined || registryIds.indexOf(registry.id) >= 0) { + registry.buckets.find( + function (bucket) { + if (bucketIds === undefined || bucketIds.indexOf(bucket.id) >= 0) { + buckets.push(bucket); + } + }); + } + }); + + var droplets = []; + + buckets.find( + function (bucket) { + bucket.droplets.find( + function (droplet) { + if (dropletIds === undefined || dropletIds.indexOf(droplet.id) >= 0) { + droplets.push(droplet); + } + }); + }); + + return droplets; + }); + + }, + + isDropletFilterChecked: function (term) { + return (this.dropletsSearchTerms.indexOf(term) > -1); + }, + + getDropletTypeCount: function (type) { + return this.filteredDroplets.filter(function (droplet) { + return droplet.type === type; + }).length; + }, + + getDropletCertificationCount: function (certification) { + return this.filteredDroplets.filter(function (droplet) { + return Object.keys(droplet).find(function (key) { + if (key === certification && droplet[certification].type === 'certification') { + return droplet; + } + }); + }).length; + }, + + getSortByLabel: function () { + var sortByColumn; + var arrayLength = this.dropletColumns.length; + for (var i = 0; i < arrayLength; i++) { + if (this.dropletColumns[i].active === true) { + sortByColumn = this.dropletColumns[i]; + break; + } + } + + if (sortByColumn) { + var label = ''; + switch (sortByColumn.label) { + case 'Updated': + label = (sortByColumn.sortOrder === 'ASC') ? 'Newest (update)' : 'Oldest (update)'; + break; + case 'Name': + label = (sortByColumn.sortOrder === 'ASC') ? 'Name (a - z)' : 'Name (z - a)'; + break; + } + return label; + } + }, + + generateSortMenuLabels: function (col) { + var label = ''; + switch (col.label) { + case 'Updated': + label = (col.sortOrder !== 'ASC') ? 'Newest (update)' : 'Oldest (update)'; + break; + case 'Name': + label = (col.sortOrder !== 'ASC') ? 'Name (a - z)' : 'Name (z - a)'; + break; + } + return label; + }, + + sortDroplets: function (sortEvent, column) { + if (column.sortable === true) { + // toggle column sort order + var sortOrder = column.sortOrder = (column.sortOrder === 'ASC') ? 'DESC' : 'ASC'; + this.filterDroplets(column.name, sortOrder); + this.activeDropletColumn = column; + //only one column can be actively sorted so we reset all to inactive + this.dropletColumns.forEach(function (c) { + c.active = false; + }); + //and set this column as the actively sorted column + column.active = true; + } + }, + + dropletsSearchRemove: function (searchTerm) { + this.filterDroplets(this.activeDropletColumn.name, this.activeDropletColumn.sortOrder); + }, + + dropletsSearchAdd: function (searchTerm) { + this.filterDroplets(this.activeDropletColumn.name, this.activeDropletColumn.sortOrder); + }, + + toggleDropletsFilter: function (searchTerm) { + var applySearchTerm = true; + // check if the search term is already applied and remove it if true + if (this.dropletsSearchTerms.length > 0) { + var arrayLength = this.dropletsSearchTerms.length; + for (var i = 0; i < arrayLength; i++) { + var index = this.dropletsSearchTerms.indexOf(searchTerm); + if (index > -1) { + this.dropletsSearchTerms.splice(index, 1); + applySearchTerm = false; + } + } + } + + // if we just removed the search term do NOT apply it again + if (applySearchTerm) { + this.dropletsSearchTerms.push(searchTerm); + } + + this.filterDroplets(this.activeDropletColumn.name, this.activeDropletColumn.sortOrder); + }, + + filterDroplets: function (sortBy, sortOrder) { + // if `sortOrder` is `undefined` then use 'ASC' + if (sortOrder === undefined) { + sortOrder = 'ASC' + } + // if `sortBy` is `undefined` then find the first sortable column in this.dropletColumns + if (sortBy === undefined) { + var arrayLength = this.dropletColumns.length; + for (var i = 0; i < arrayLength; i++) { + if (this.dropletColumns[i].sortable === true) { + sortBy = this.dropletColumns[i].name; + this.activeDropletColumn = this.dropletColumns[i]; + //only one column can be actively sorted so we reset all to inactive + this.dropletColumns.forEach(function (c) { + c.active = false; + }); + //and set this column as the actively sorted column + this.dropletColumns[i].active = true; + this.dropletColumns[i].sortOrder = sortOrder; + break; + } + } + } + + var newData = this.droplets; + + for (var i = 0; i < this.dropletsSearchTerms.length; i++) { + newData = filterData(newData, this.dropletsSearchTerms[i], true, this.activeDropletColumn.name); + } + + newData = this.dataTableService.sortData(newData, sortBy, sortOrder); + this.filteredDroplets = newData; + this.getAutoCompleteDroplets(); + }, + + getAutoCompleteDroplets: function () { + var self = this; + this.autoCompleteDroplets = []; + this.dropletColumns.forEach(function (c) { + return self.filteredDroplets.forEach(function (r) { + return (r[c.name.toLowerCase()]) ? self.autoCompleteDroplets.push(r[c.name.toLowerCase()].toString()) : ''; + }) + }); + }, + + getBucket: function (registryId, bucketId) { + return this.getBuckets(registryId, bucketId).then( + function (buckets) { + return buckets[0]; + }); + }, + + getBuckets: function (registryIds, bucketIds) { + var self = this; + return this.getRegistries().then( + function (registries) { + var buckets = []; + + registries.find( + function (registry) { + if (registryIds === undefined || registryIds.indexOf(registry.id) >= 0) { + registry.buckets.find( + function (bucket) { + if (bucketIds === undefined || bucketIds.indexOf(bucket.id) >= 0) { + buckets.push(bucket); + } + }); + } + }); + + return buckets; + }); + + }, + + filterBuckets: function (sortBy, sortOrder) { + // if `sortOrder` is `undefined` then use 'ASC' + if (sortOrder === undefined) { + sortOrder = 'ASC' + } + + // if `sortBy` is `undefined` then find the first sortable column in this.bucketColumns + if (sortBy === undefined) { + var arrayLength = this.bucketColumns.length; + for (var i = 0; i < arrayLength; i++) { + if (this.bucketColumns[i].sortable === true) { + sortBy = this.bucketColumns[i].name; + this.activeBucketColumn = this.bucketColumns[i]; + //only one column can be actively sorted so we reset all to inactive + this.bucketColumns.forEach(function (c) { + c.active = false; + }); + //and set this column as the actively sorted column + this.bucketColumns[i].active = true; + this.bucketColumns[i].sortOrder = sortOrder; + break; + } + } + } + + var newData = this.buckets; + + for (var i = 0; i < this.bucketsSearchTerms.length; i++) { + newData = filterData(newData, this.bucketsSearchTerms[i], true, this.activeBucketColumn.name); + } + + newData = this.dataTableService.sortData(newData, sortBy, sortOrder); + this.filteredBuckets = newData; + this.getAutoCompleteBuckets(); + }, + + getAutoCompleteBuckets: function () { + var self = this; + this.autoCompleteBuckets = []; + this.bucketColumns.forEach(function (c) { + return self.filteredBuckets.forEach(function (r) { + return (r[c.name.toLowerCase()]) ? self.autoCompleteBuckets.push(r[c.name.toLowerCase()].toString()) : ''; + }); + }); + }, + + sortBuckets: function (sortEvent, column) { + if (column.sortable === true) { + // toggle column sort order + var sortOrder = column.sortOrder = (column.sortOrder === 'ASC') ? 'DESC' : 'ASC'; + this.filterBuckets(column.name, sortOrder); + this.activeBucketsColumn = column; + //only one column can be actively sorted so we reset all to inactive + this.bucketColumns.forEach(function (c) { + c.active = false; + }); + //and set this column as the actively sorted column + column.active = true; + } + }, + + bucketsSearchRemove: function (searchTerm) { + this.filterDroplets(this.activeBucketsColumn.name, this.activeBucketsColumn.sortOrder); + }, + + bucketsSearchAdd: function (searchTerm) { + this.filterDroplets(this.activeBucketsColumn.name, this.activeBucketsColumn.sortOrder); + }, + + allFilteredBucketsSelected: function () { + this.filteredBuckets.forEach(function (c) { + if (c.checked === undefined || c.checked === false) { + return false; + } + }); + + return true; + }, + + toggleBucketSelect: function (row) { + if (this.allFilteredBucketsSelected()) { + this.allBucketsSelected = true; + } else { + this.allBucketsSelected = false; + } + }, + + getCertification: function (registryId, certificatonId) { + return this.getCertifications(registryId, certificatonId).then( + function (certificatons) { + return certificatons[0]; + }); + }, + getCertifications: function (registryIds, certificatonIds) { + var self = this; + return this.getRegistries().then( + function (registries) { + var certificatons = []; + + registries.find( + function (registry) { + if (registryIds === undefined || registryIds.indexOf(registry.id) >= 0) { + registry.certifications.find( + function (certificaton) { + if (certificatonIds === undefined || certificatonIds.indexOf(certificaton.id) >= 0) { + certificatons.push(certificaton); + } + }); + } + }); + + return certificatons; + }); + + }, + + filterCertifications: function (sortBy, sortOrder) { + // if `sortOrder` is `undefined` then use 'ASC' + if (sortOrder === undefined) { + sortOrder = 'ASC' + } + + // if `sortBy` is `undefined` then find the first sortable column in this.bucketColumns + if (sortBy === undefined) { + var arrayLength = this.bucketColumns.length; + for (var i = 0; i < arrayLength; i++) { + if (this.bucketColumns[i].sortable === true) { + sortBy = this.bucketColumns[i].name; + this.activeBucketColumn = this.bucketColumns[i]; + //only one column can be actively sorted so we reset all to inactive + this.bucketColumns.forEach(function (c) { + c.active = false; + }); + //and set this column as the actively sorted column + this.bucketColumns[i].active = true; + this.bucketColumns[i].sortOrder = sortOrder; + break; + } + } + } + + var newData = this.certifications; + + for (var i = 0; i < this.certificationsSearchTerms.length; i++) { + newData = filterData(newData, this.certificationsSearchTerms[i], true, this.activeBucketColumn.name); + } + + newData = this.dataTableService.sortData(newData, sortBy, sortOrder); + this.filteredCertifications = newData; + this.getAutoCompleteCertifications(); + }, + + getAutoCompleteCertifications: function () { + var self = this; + this.autoCompleteCertifications = []; + this.bucketColumns.forEach(function (c) { + return self.filteredCertifications.forEach(function (r) { + return (r[c.name.toLowerCase()]) ? self.autoCompleteCertifications.push(r[c.name.toLowerCase()].toString()) : ''; + }); + }); + }, + + sortCertifications: function (sortEvent, column) { + if (column.sortable === true) { + // toggle column sort order + var sortOrder = column.sortOrder = (column.sortOrder === 'ASC') ? 'DESC' : 'ASC'; + this.filterCertifications(column.name, sortOrder); + this.activeCertificationsColumn = column; + //only one column can be actively sorted so we reset all to inactive + this.bucketColumns.forEach(function (c) { + c.active = false; + }); + //and set this column as the actively sorted column + column.active = true; + } + }, + + certificationsSearchRemove: function (searchTerm) { + this.filterDroplets(this.activeCertificationsColumn.name, this.activeCertificationsColumn.sortOrder); + }, + + certificationsSearchAdd: function (searchTerm) { + this.filterDroplets(this.activeCertificationsColumn.name, this.activeCertificationsColumn.sortOrder); + }, + + getUser: function (registryId, userId) { + return this.getUsers(registryId, userId).then( + function (users) { + return users[0]; + }); + }, + + getUsers: function (registryIds, userIds) { + var self = this; + return this.getRegistries().then( + function (registries) { + var users = []; + + registries.find( + function (registry) { + if (registryIds === undefined || registryIds.indexOf(registry.id) >= 0) { + registry.users.find( + function (user) { + if (userIds === undefined || userIds.indexOf(user.id) >= 0) { + users.push(user); + } + }); + } + }); + + return users; + }); + + }, + + sortUsers: function (sortEvent, column) { + if (column.sortable) { + var sortBy = column.name; + var sortOrder = column.sortOrder = (column.sortOrder === 'ASC') ? 'DESC' : 'ASC'; + this.filterUsers(sortBy, sortOrder); + + //only one column can be actively sorted so we reset all to inactive + this.userColumns.forEach(function (c) { + c.active = false; + }); + //and set this column as the actively sorted column + column.active = true; + } + }, + + usersSearchRemove: function (searchTerm) { + //only remove the first occurrence of the search term + var index = this.usersSearchTerms.indexOf(searchTerm); + if (index !== -1) { + this.usersSearchTerms.splice(index, 1); + } + this.usersCurrentPage = 1; + this.usersFromRow = 1; + this.usersPageSize = 1; + this.filterUsers(); + }, + + usersSearchAdd: function (searchTerm) { + this.usersSearchTerms.push(searchTerm); + this.usersCurrentPage = 1; + this.usersFromRow = 1; + this.usersPageSize = 1; + this.filterUsers(); + }, + + pageUsers: function (pagingEvent) { + this.usersFromRow = pagingEvent.fromRow; + this.usersCurrentPage = pagingEvent.page; + this.usersPageSize = pagingEvent.pageSize; + this.filterUsers(); + }, + + filterUsers: function (sortBy, sortOrder) { + if (this.allUsersSelected) { + this.toggleUsersSelectAll(); + } + this.deselectAllUsers(); + var newData = this.users; + + for (var i = 0; i < this.usersSearchTerms.length; i++) { + newData = filterData(newData, this.usersSearchTerms[i], true); + } + newData = this.dataTableService.sortData(newData, sortBy, sortOrder); + this.usersPageCount = newData.length; + newData = this.dataTableService.pageData(newData, this.usersFromRow, this.usersCurrentPage * this.usersPageSize); + this.filteredUsers = newData; + this.getAutoCompleteUsers(); + }, + + toggleUserSelect: function (row) { + if (this.allFilteredUsersSelected()) { + this.allUsersSelected = true; + } else { + this.allUsersSelected = false; + } + }, + + toggleUsersSelectAll: function () { + if (this.allUsersSelected) { + this.selectAllUsers(); + } else { + this.deselectAllUsers(); + } + }, + + selectAllUsers: function () { + this.filteredUsers.forEach(function (c) { + c.checked = true; + }); + }, + + deselectAllUsers: function () { + this.filteredUsers.forEach(function (c) { + c.checked = false; + }); + }, + allFilteredUsersSelected: function () { + var allFilteredUsersSelected = true; + this.filteredUsers.forEach(function (c) { + if (c.checked === undefined || c.checked === false) { + allFilteredUsersSelected = false; + } + }); + + return allFilteredUsersSelected; + }, + + getAutoCompleteUsers: function () { + var self = this; + this.autoCompleteUsers = []; + this.userColumns.forEach(function (c) { + self.filteredUsers.forEach(function (r) { + (r[c.name.toLowerCase()]) ? self.autoCompleteUsers.push(r[c.name.toLowerCase()].toString()) : ''; + }); + }); + }, + + // + + setBreadcrumbState: function (state) { + this.breadCrumbState = state; + } +}; + +NfRegistryService.parameters = [covalentCore.TdDataTableService]; + +module.exports = NfRegistryService; diff --git a/nifi-registry-web-ui/src/main/webapp/systemjs-angular-loader.js b/nifi-registry-web-ui/src/main/webapp/systemjs-angular-loader.js new file mode 100644 index 000000000..8e33bb5a6 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/systemjs-angular-loader.js @@ -0,0 +1,66 @@ +/* + * 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. + */ + +var templateUrlRegex = /templateUrl\s*:(\s*['"`](.*?)['"`]\s*)/gm; +var stylesRegex = /styleUrls *:(\s*\[[^\]]*?\])/g; +var stringRegex = /(['`"])((?:[^\\]\\\1|.)*?)\1/g; + +module.exports.translate = function (load) { + if (load.source.indexOf('moduleId') != -1) return load; + + var url = document.createElement('a'); + url.href = load.address; + + var basePathParts = url.pathname.split('/'); + + basePathParts.pop(); + var basePath = basePathParts.join('/'); + + var baseHref = document.createElement('a'); + baseHref.href = this.baseURL; + baseHref = baseHref.pathname; + + if (!baseHref.startsWith('/base/')) { // it is not karma + basePath = basePath.replace(baseHref, ''); + } + + load.source = load.source + .replace(templateUrlRegex, function (match, quote, url) { + var resolvedUrl = url; + + if (url.startsWith('.')) { + resolvedUrl = basePath + url.substr(1); + } + + return 'templateUrl: "' + resolvedUrl + '"'; + }) + .replace(stylesRegex, function (match, relativeUrls) { + var urls = []; + + while ((match = stringRegex.exec(relativeUrls)) !== null) { + if (match[2].startsWith('.')) { + urls.push('"' + basePath + match[2].substr(1) + '"'); + } else { + urls.push('"' + match[2] + '"'); + } + } + + return "styleUrls: [" + urls.join(', ') + "]"; + }); + + return load; +}; diff --git a/nifi-registry-web-ui/src/main/webapp/systemjs.builder.config.js b/nifi-registry-web-ui/src/main/webapp/systemjs.builder.config.js new file mode 100644 index 000000000..1d96854be --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/systemjs.builder.config.js @@ -0,0 +1,137 @@ +/* + * 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. + */ + +(function (global) { + System.config({ + baseURL: "./webapp/", + paths: { + // paths serve as alias + 'npm:': './node_modules/' + }, + // map tells the System loader where to look for things + map: { + 'text': 'npm:systemjs-plugin-text/text.js', + 'app': 'webapp/', + + // jquery + 'jquery': 'npm:jquery/dist/jquery.min.js', + + // Angular + '@angular/core': 'npm:@angular/core/bundles/core.umd.js', + '@angular/common': 'npm:@angular/common/bundles/common.umd.js', + '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js', + '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js', + '@angular/http': 'npm:@angular/http/bundles/http.umd.js', + '@angular/router': 'npm:@angular/router/bundles/router.umd.js', + '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js', + '@angular/flex-layout': 'npm:@angular/flex-layout/bundles/flex-layout.umd.js', + '@angular/material': 'npm:@angular/material/bundles/material.umd.js', + '@angular/platform-browser/animations': 'npm:@angular/platform-browser/bundles/platform-browser-animations.umd.js', + '@angular/cdk': 'npm:@angular/cdk/bundles/cdk.umd.js', + '@angular/cdk/a11y': 'npm:@angular/cdk/bundles/cdk-a11y.umd.js', + '@angular/cdk/collections': 'npm:@angular/cdk/bundles/cdk-collections.umd.js', + '@angular/cdk/observers': 'npm:@angular/cdk/bundles/cdk-observers.umd.js', + '@angular/cdk/overlay': 'npm:@angular/cdk/bundles/cdk-overlay.umd.js', + '@angular/cdk/platform': 'npm:@angular/cdk/bundles/cdk-platform.umd.js', + '@angular/cdk/portal': 'npm:@angular/cdk/bundles/cdk-portal.umd.js', + '@angular/cdk/keycodes': 'npm:@angular/cdk/bundles/cdk-keycodes.umd.js', + '@angular/cdk/bidi': 'npm:@angular/cdk/bundles/cdk-bidi.umd.js', + '@angular/cdk/coercion': 'npm:@angular/cdk/bundles/cdk-coercion.umd.js', + '@angular/cdk/table': 'npm:@angular/cdk/bundles/cdk-table.umd.js', + '@angular/cdk/rxjs': 'npm:@angular/cdk/bundles/cdk-rxjs.umd.js', + '@angular/cdk/scrolling': 'npm:@angular/cdk/bundles/cdk-scrolling.umd.js', + '@angular/animations': 'npm:@angular/animations/bundles/animations.umd.js', + '@angular/animations/browser': 'npm:@angular/animations/bundles/animations-browser.umd.js', + '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js', + + // needed to support gestures for angular material + 'hammerjs': 'npm:hammerjs/hammer.min.js', + + // Covalent + '@covalent/core': 'npm:@covalent/core/core.umd.js', + + // other libraries + 'rxjs': 'npm:rxjs', + 'moment': 'npm:moment', + 'angular2-moment': 'npm:angular2-moment', + 'switchMap': 'npm:rxjs/add/operator/switchMap', + 'zone.js': 'npm:zone.js/dist/zone.js', + 'core-js': 'npm:core-js/client/shim.min.js', + + // Fluid Design System + '@fluid-design-system/core': 'npm:@fluid-design-system/dist/platform/core/fluid-design-system.module.js', + '@fluid-design-system/dialogs': 'npm:@fluid-design-system/dist/platform/core/dialogs/fds-dialogs.module.js', + '@fluid-design-system/dialog-component': 'npm:@fluid-design-system/dist/platform/core/dialogs/fds-dialog.component.js', + '@fluid-design-system/dialog-service': 'npm:@fluid-design-system/dist/platform/core/dialogs/services/dialog.service.js', + '@fluid-design-system/confirm-dialog-component': 'npm:@fluid-design-system/dist/platform/core/dialogs/confirm-dialog/confirm-dialog.component.js', + + // Nifi Registry + 'nifi-registry/nf-registry.module.js': 'nf-registry.module.js', + 'nifi-registry/nf-registry.animations.js': 'nf-registry.animations.js', + 'nifi-registry/nf-registry.routes.js': 'nf-registry.routes.js', + 'nifi-registry/components/fluid-design-system/fds-demo.js': 'components/fluid-design-system/fds-demo.js', + 'nifi-registry/nf-registry.js': 'nf-registry.js', + 'nifi-registry/services/nf-registry.service.js': 'services/nf-registry.service.js', + 'nifi-registry/components/page-not-found/nf-registry-page-not-found.js': 'components/page-not-found/nf-registry-page-not-found.js', + 'nifi-registry/components/explorer/nf-registry-explorer.js': 'components/explorer/nf-registry-explorer.js', + 'nifi-registry/components/explorer/list/nf-registry-explorer-list-viewer.js': 'components/explorer/list/nf-registry-explorer-list-viewer.js', + 'nifi-registry/components/explorer/grid-list/nf-registry-explorer-grid-list-viewer.js': 'components/explorer/grid-list/nf-registry-explorer-grid-list-viewer.js', + 'nifi-registry/components/administration/nf-registry-administration.js': 'components/administration/nf-registry-administration.js', + 'nifi-registry/components/administration/general/nf-registry-general-administration.js': 'components/administration/general/nf-registry-general-administration.js', + 'nifi-registry/components/administration/users/nf-registry-users-administration.js': 'components/administration/users/nf-registry-users-administration.js', + 'nifi-registry/components/administration/users/add/nf-registry-add-user.js': 'components/administration/users/add/nf-registry-add-user.js', + 'nifi-registry/components/administration/users/details/nf-registry-user-details.js': 'components/administration/users/details/nf-registry-user-details.js', + 'nifi-registry/components/administration/users/permissions/nf-registry-user-permissions.js': 'components/administration/users/permissions/nf-registry-user-permissions.js', + 'nifi-registry/components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js': 'components/administration/workflow/buckets/permissions/nf-registry-bucket-permissions.js', + 'nifi-registry/components/administration/workflow/nf-registry-workflow-administration.js': 'components/administration/workflow/nf-registry-workflow-administration.js', + 'nifi-registry/components/explorer/list/registry/nf-registry-list-viewer.js': 'components/explorer/list/registry/nf-registry-list-viewer.js', + 'nifi-registry/components/explorer/grid-list/registry/nf-registry-grid-list-viewer.js': 'components/explorer/grid-list/registry/nf-registry-grid-list-viewer.js', + 'nifi-registry/components/explorer/list/registry/bucket/nf-registry-bucket-list-viewer.js': 'components/explorer/list/registry/bucket/nf-registry-bucket-list-viewer.js', + 'nifi-registry/components/explorer/grid-list/registry/bucket/nf-registry-bucket-grid-list-viewer.js': 'components/explorer/grid-list/registry/bucket/nf-registry-bucket-grid-list-viewer.js', + 'nifi-registry/components/explorer/list/registry/bucket/droplet/nf-registry-droplet-list-viewer.js': 'components/explorer/list/registry/bucket/droplet/nf-registry-droplet-list-viewer.js', + 'nifi-registry/components/explorer/grid-list/registry/bucket/droplet/nf-registry-droplet-grid-list-viewer.js': 'components/explorer/grid-list/registry/bucket/droplet/nf-registry-droplet-grid-list-viewer.js', + 'nifi-registry/components/explorer/list/registry/nf-registry-details-viewer.js': 'components/explorer/list/registry/nf-registry-details-viewer.js', + 'nifi-registry/components/explorer/list/registry/bucket/nf-registry-bucket-details-viewer.js': 'components/explorer/list/registry/bucket/nf-registry-bucket-details-viewer.js', + 'nifi-registry/components/explorer/list/registry/bucket/droplet/nf-registry-droplet-details-viewer.js': 'components/explorer/list/registry/bucket/droplet/nf-registry-droplet-details-viewer.js' + }, + // packages tells the System loader how to load when no filename and/or no extension + packages: { + 'app': { + defaultExtension: 'js', + meta: { + './*.js': { + loader: 'systemjs-angular-loader.js' + } + } + }, + 'systemjs-angular-loader.js': { + loader: false + }, + 'rxjs': { + defaultExtension: 'js' + }, + 'moment': { + main: './moment.js', + defaultExtension: 'js' + }, + 'angular2-moment': { + main: './index.js', + defaultExtension: 'js' + } + } + }); +})(this); diff --git a/nifi-registry-web-ui/src/main/webapp/systemjs.config.extras.js b/nifi-registry-web-ui/src/main/webapp/systemjs.config.extras.js new file mode 100644 index 000000000..e2a256afe --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/systemjs.config.extras.js @@ -0,0 +1,27 @@ +/* + * 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. + */ + +/** + * Add barrels and stuff + */ +(function (global) { + System.config({ + packages: { + // add packages here + } + }); +})(this); diff --git a/nifi-registry-web-ui/src/main/webapp/systemjs.spec.config.js b/nifi-registry-web-ui/src/main/webapp/systemjs.spec.config.js new file mode 100644 index 000000000..a9d72c63a --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/systemjs.spec.config.js @@ -0,0 +1,76 @@ +/* + * 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. + */ + +(function (global) { + System.config({ + paths: { + // paths serve as alias + 'npm:': 'nifi-registry/node_modules/' + }, + // map tells the System loader where to look for things + map: { + 'text': 'npm:systemjs-plugin-text/text.js', + 'app': './webapp', + + // jquery + 'jquery': 'npm:jquery/dist/jquery.min.js', + + // Angular + '@angular/core': 'npm:@angular/core/bundles/core.umd.min.js', + '@angular/common': 'npm:@angular/common/bundles/common.umd.min.js', + '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.min.js', + '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.min.js', + '@angular/http': 'npm:@angular/http/bundles/http.umd.min.js', + '@angular/router': 'npm:@angular/router/bundles/router.umd.min.js', + '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.min.js', + '@angular/flex-layout': 'npm:@angular/flex-layout/bundles/flex-layout.umd.js', + '@angular/material': 'npm:@angular/material/bundles/material.umd.min.js', + '@angular/platform-browser/animations': 'npm:@angular/platform-browser/bundles/platform-browser-animations.umd.min.js', + '@angular/cdk': 'npm:@angular/cdk/bundles/cdk.umd.min.js', + '@angular/animations': 'npm:@angular/animations/bundles/animations.umd.min.js', + '@angular/animations/browser': 'npm:@angular/animations/bundles/animations-browser.umd.min.js', + '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.min.js', + + // Covalent + '@covalent/core': 'npm:@covalent/core/core.umd.js', + + // other libraries + 'rxjs': 'npm:rxjs', + 'switchMap': 'npm:rxjs/add/operator/switchMap', + + // Fluid Design System + '@fluid-design-system/core': 'npm:@fluid-design-system/dist/platform/core/fluid-design-system.module.js', + }, + // packages tells the System loader how to load when no filename and/or no extension + packages: { + app: { + defaultExtension: 'js', + meta: { + './*.js': { + loader: 'nifi-registry/systemjs-angular-loader.js' + } + } + }, + 'nifi-registry/systemjs-angular-loader.js': { + loader: false + }, + rxjs: { + defaultExtension: 'js' + } + } + }); +})(this); diff --git a/nifi-registry-web-ui/src/main/webapp/theming/_helperClasses.scss b/nifi-registry-web-ui/src/main/webapp/theming/_helperClasses.scss new file mode 100644 index 000000000..a106f77db --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/theming/_helperClasses.scss @@ -0,0 +1,63 @@ +/* + * 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. + */ + +.fa-rotate-45 { + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -ms-transform: rotate(45deg); + -o-transform: rotate(45deg); + transform: rotate(45deg); +} + +.capitalize { + text-transform: capitalize; +} + +.uppercase { + text-transform: uppercase; +} + +.info { + color: $blue8; +} + +.authorized { + color: $red2; +} + +.suspended { + color: $green3; +} + +.nf-registry-button-container { + position: absolute; + bottom: 0px; + height: 64px; + left: 0px; + right: 0px; + border-top: 1px solid $grey4; +} + +.nf-registry-button-container .done-button { + float: right; + margin-right: 15px; + margin-top: 15px; +} + +.td-expansion-content { + background: $grey6; +} diff --git a/nifi-registry-web-ui/src/main/webapp/theming/_structureElements.scss b/nifi-registry-web-ui/src/main/webapp/theming/_structureElements.scss new file mode 100644 index 000000000..78c19d177 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/theming/_structureElements.scss @@ -0,0 +1,82 @@ +/* + * 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. + */ + +body { + background: $grey5; +} + +#nf-registry-app-container { + margin: 0; + width: 100%; + height: 100%; +} + +#nifi-registry-logo { + height: 44px; +} + +#nifi-registry-alerts-count { + border-radius: 50%; + background: $warnColor; + height: 14px; + width: 14px; + position: relative; + left: 9px; + color: #FFFFFF; + font-size: 9px; + text-align: center; + line-height: 14px; +} + +#nifi-registry-toolbar { + min-width: 1045px; + background-color: #FFFFFF; + position: absolute; + z-index: 1000; + background: $grey1; +} + +#nifi-registry-toolbar .mat-icon-button { + color: $grey5; + font-size: 20px; + margin: 0; +} + +#nifi-registry-toolbar .mat-select-value-text, #nifi-registry-toolbar .mat-select-arrow{ + color: white; +} + +#nifi-registry-toolbar span, #nifi-registry-toolbar .link{ + color: $grey5; +} + +#nf-registry-perspectives-container { + position: absolute; + top: 64px; + left: 0px; + right: 0px; + bottom: 0px; + background: $grey5; + min-height: 370px; + min-width: 1045px; + overflow: auto; +} + +md-sidenav { + width: 40%; + min-width: 418px; +} diff --git a/nifi-registry-web-ui/src/main/webapp/css/main.css b/nifi-registry-web-ui/src/main/webapp/theming/components/administration/_structureElements.scss similarity index 89% rename from nifi-registry-web-ui/src/main/webapp/css/main.css rename to nifi-registry-web-ui/src/main/webapp/theming/components/administration/_structureElements.scss index 6e9d02da8..aa591003b 100644 --- a/nifi-registry-web-ui/src/main/webapp/css/main.css +++ b/nifi-registry-web-ui/src/main/webapp/theming/components/administration/_structureElements.scss @@ -15,8 +15,8 @@ * limitations under the License. */ -/* general */ - -body { - font-family: Open Sans; +#nifi-registry-administration-perspective { + position: absolute; + top: 20px; + left: 50px; } diff --git a/nifi-registry-web-ui/src/main/webapp/theming/components/administration/general/_structureElements.scss b/nifi-registry-web-ui/src/main/webapp/theming/components/administration/general/_structureElements.scss new file mode 100644 index 000000000..ab3548dc7 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/theming/components/administration/general/_structureElements.scss @@ -0,0 +1,25 @@ +/* + * 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. + */ + +#nifi-registry-general-administration-perspective { + position: absolute; + top: 79px; + left: 50px; + right: calc(50% - 5px); + bottom: 20px; + background: white; +} diff --git a/nifi-registry-web-ui/src/main/webapp/theming/components/administration/users/_structureElements.scss b/nifi-registry-web-ui/src/main/webapp/theming/components/administration/users/_structureElements.scss new file mode 100644 index 000000000..650593f21 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/theming/components/administration/users/_structureElements.scss @@ -0,0 +1,61 @@ +/* + * 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. + */ + +#nifi-registry-users-administration-perspective { + position: absolute; + top: 79px; + left: 50px; + right: 20px; + bottom: 20px; + background: white; +} + +#nifi-registry-users-administration-list-container { + overflow-y: auto; + position: absolute; + bottom: 49px; + top: 124px; + left: 30px; + right: 30px; + overflow-x: hidden; +} + +#nifi-registry-users-administration-list-paging-bar { + position: absolute; + bottom: 0; + left: 0; + right: 0; +} + +#nf-registry-user-permissions-side-nav-container { + position: absolute; + bottom: 15px; + right: 10px; +} + +#nf-registry-add-user-side-nav-container { + position: absolute; + bottom: 15px; + right: 10px; +} + +#nf-registry-user-details-side-nav-container { + position: absolute; + bottom: 15px; + right: 10px; +} + diff --git a/nifi-registry-web-ui/src/main/webapp/theming/components/administration/workflow/_structureElements.scss b/nifi-registry-web-ui/src/main/webapp/theming/components/administration/workflow/_structureElements.scss new file mode 100644 index 000000000..038407974 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/theming/components/administration/workflow/_structureElements.scss @@ -0,0 +1,61 @@ +/* + * 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. + */ + +#nifi-registry-workflow-administration-perspective-buckets-container { + position: absolute; + top: 79px; + left: 50px; + right: calc(50% - 5px); + bottom: 20px; + background: white; +} + +//#nifi-registry-workflow-administration-perspective-certifications-container { +// position: absolute; +// top: 79px; +// left: calc(50% + 25px); +// right: 20px; +// bottom: 20px; +// background: white; +//} + +#nifi-registry-workflow-administration-buckets-list-container { + overflow-y: auto; + position: absolute; + bottom: 30px; + top: 171px; + left: 30px; + right: 30px; + overflow-x: hidden; +} + +//#nifi-registry-workflow-administration-certifications-list-container { +// overflow-y: auto; +// position: absolute; +// bottom: 30px; +// top: 171px; +// left: 30px; +// right: 30px; +// overflow-x: hidden; +//} + +#nf-registry-workflow-bucket-permissions-side-nav-container { + position: absolute; + bottom: 15px; + right: 10px; +} + diff --git a/nifi-registry-web-ui/src/main/webapp/theming/components/explorer/grid-list/_structureElements.scss b/nifi-registry-web-ui/src/main/webapp/theming/components/explorer/grid-list/_structureElements.scss new file mode 100644 index 000000000..0038782fb --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/theming/components/explorer/grid-list/_structureElements.scss @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#nf-registry-droplet-filter-clear-grouping-button-container { + height: 36px; + line-height: 36px; +} + +#nf-registry-droplet-filter-clear-grouping-button-container i{ + color: $red2; +} + +#droplet-sort-by-field { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + //width: 85px; + text-align: end; +} + +#nifi-registry-explorer-grid-list-viewer-droplet-container-details { + position: relative; +} + +#nifi-registry-explorer-grid-list-viewer-droplet-container-details-change-log { + position: relative; + left: 0px; + max-height: 230px; + overflow: auto; +} \ No newline at end of file diff --git a/nifi-registry-web-ui/src/main/webapp/theming/components/fluid-design-system/_structureElements.scss b/nifi-registry-web-ui/src/main/webapp/theming/components/fluid-design-system/_structureElements.scss new file mode 100644 index 000000000..75c5ebbc4 --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/theming/components/fluid-design-system/_structureElements.scss @@ -0,0 +1,25 @@ +/* + * 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. + */ + +#fds-demo { + position: absolute; + top: 0px; + bottom: 0px; + left: 0px; + right: 0px; + overflow: auto; +} diff --git a/nifi-registry-web-ui/src/main/webapp/theming/nf-registry.scss b/nifi-registry-web-ui/src/main/webapp/theming/nf-registry.scss new file mode 100644 index 000000000..8d9e8788c --- /dev/null +++ b/nifi-registry-web-ui/src/main/webapp/theming/nf-registry.scss @@ -0,0 +1,30 @@ +/* + * 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. + */ + +/* Welcome to Compass. + * In this file you should centralize your imports. After compilation simply import this file using the following HTML or equivalent: + * */ + +@import '../../platform/core/common/styles/globalVars'; +@import 'structureElements'; +@import 'helperClasses'; +@import 'components/administration/structureElements'; +@import 'components/administration/general/structureElements'; +@import 'components/administration/users/structureElements'; +@import 'components/administration/workflow/structureElements'; +@import 'components/explorer/grid-list/structureElements'; +@import 'components/fluid-design-system/structureElements'; diff --git a/pom.xml b/pom.xml index 47cf32706..91dbfaa3b 100644 --- a/pom.xml +++ b/pom.xml @@ -14,34 +14,37 @@ limitations under the License. --> - + 4.0.0 org.apache apache 17 - + org.apache.nifi.registry nifi-registry 0.0.1-SNAPSHOT pom - Provides a central location for storage and management of shared resources across one or more instances of NiFi and/or MiNiFi. + Provides a central location for storage and management of shared resources across one or more instances + of NiFi and/or MiNiFi. + nifi-registry-properties nifi-registry-utils - nifi-registry-data-model + nifi-registry-data-model nifi-registry-jetty nifi-registry-resources nifi-registry-runtime nifi-registry-security nifi-registry-framework - nifi-registry-provider-api - nifi-registry-provider-impl + nifi-registry-provider-api + nifi-registry-provider-impl nifi-registry-web-api nifi-registry-web-ui nifi-registry-bootstrap - nifi-registry-assembly + nifi-registry-assembly https://nifi.apache.org/registry.html @@ -98,8 +101,8 @@ UTF-8 UTF-8 2017 - 1.7.12 - 9.2.11.v20150529 + 1.7.12 + 9.4.3.v20170317 2.25.1 @@ -140,7 +143,7 @@ - + ch.qos.logback @@ -200,28 +203,28 @@ org.eclipse.jetty - jetty-jsp + jetty-annotations ${jetty.version} - javax.servlet - javax.servlet-api - 3.1.0 + org.eclipse.jetty + apache-jsp + ${jetty.version} - javax.servlet.jsp - javax.servlet.jsp-api - 2.3.1 + org.eclipse.jetty + apache-jstl + ${jetty.version} - javax.el - javax.el-api - 3.0.0 + org.apache.commons + commons-lang3 + 3.4 - javax.servlet.jsp.jstl - javax.servlet.jsp.jstl-api - 1.2.1 + javax.servlet + javax.servlet-api + 3.1.0 org.glassfish.jersey.core @@ -362,7 +365,9 @@ **/*Spec.class true - -Xmx1G -Djava.net.preferIPv4Stack=true ${maven.surefire.arguments} + -Xmx1G -Djava.net.preferIPv4Stack=true + ${maven.surefire.arguments} + @@ -551,78 +556,84 @@ - - + + - + - - + + - - + + - + - - + + - + - + - + - + - + - - + + - - + + - - + + - + - + - + - - + + - + - - + + - + - - - - - - + + + + + + - + @@ -637,8 +648,10 @@ nb-configuration.xml nbactions.xml - DEPENDENCIES - .github/PULL_REQUEST_TEMPLATE.md + DEPENDENCIES + + .github/PULL_REQUEST_TEMPLATE.md + @@ -658,7 +671,7 @@ - +