You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2018/07/26 10:50:37 UTC
[20/28] brooklyn-ui git commit: This adds the contributed
brooklyn-ui-angular code in the folder new/.
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/app-inspector/app/views/main/main.controller.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/app-inspector/app/views/main/main.controller.js b/new/ui-modules/app-inspector/app/views/main/main.controller.js
new file mode 100644
index 0000000..07280f8
--- /dev/null
+++ b/new/ui-modules/app-inspector/app/views/main/main.controller.js
@@ -0,0 +1,69 @@
+/*
+ * 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 {HIDE_INTERSTITIAL_SPINNER_EVENT} from 'brooklyn-ui-utils/interstitial-spinner/interstitial-spinner';
+import template from "./main.template.html";
+
+export const mainState = {
+ name: 'main',
+ url: '/',
+ template: template,
+ controller: ['$scope', '$q', 'brWebNotifications', mainController],
+ controllerAs: 'ctrl'
+};
+
+export function mainController($scope, $q, brWebNotifications) {
+ $scope.$emit(HIDE_INTERSTITIAL_SPINNER_EVENT);
+
+ let ctrl = this;
+
+ brWebNotifications.supported.then(() => {
+ ctrl.isNotificationsSupported = true;
+ }).catch(() => {
+ ctrl.isNotificationsSupported = false;
+ });
+
+ brWebNotifications.isEnabled().then(() => {
+ ctrl.isNotificationsEnabled = true;
+ }).catch(() => {
+ ctrl.isNotificationsEnabled = false;
+ });
+
+ brWebNotifications.getPermission().then(permission => {
+ ctrl.isNotificationsBlocked = permission === 'denied';
+ });
+
+ ctrl.toggleNotifications = () => {
+ brWebNotifications.isEnabled().then(() => {
+ return brWebNotifications.setEnable(false);
+ }).then(enable => {
+ ctrl.isNotificationsEnabled = enable;
+ }).catch(() => {
+ brWebNotifications.requestPermission().then(permission => {
+ ctrl.isNotificationsBlocked = permission === 'denied';
+
+ if (ctrl.isNotificationsBlocked) {
+ return $q.reject();
+ }
+ return brWebNotifications.setEnable(permission === 'granted');
+ }).then(enable => {
+ ctrl.isNotificationsEnabled = enable;
+ });
+ });
+ };
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/app-inspector/app/views/main/main.less
----------------------------------------------------------------------
diff --git a/new/ui-modules/app-inspector/app/views/main/main.less b/new/ui-modules/app-inspector/app/views/main/main.less
new file mode 100644
index 0000000..d14fed7
--- /dev/null
+++ b/new/ui-modules/app-inspector/app/views/main/main.less
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+.entity-tree {
+
+ .entity-tree-header {
+ display: flex;
+
+ .entity-tree-title {
+ flex-grow: 1;
+ }
+ .entity-tree-action {
+ flex-shrink: 1;
+ vertical-align: middle;
+ margin-left: 0.5em;
+ display: inline-table;
+ }
+ .notifications {
+ color: @gray-light;
+ transform: rotate(0);
+ transition: 0.3s all ease;
+ &.active {
+ color: @brand-primary;
+ transform: rotate(30deg);
+ }
+ }
+ }
+
+ //.entity-tree-heading {
+ // .clearfix()
+ //}
+
+ .entity-tree-title {
+ font-size: 1.8rem;
+ font-weight: bold;
+ color: @brand-primary;
+ }
+
+ .entity-tree-action-bar {
+ margin-right: -0.5rem;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/app-inspector/app/views/main/main.template.html
----------------------------------------------------------------------
diff --git a/new/ui-modules/app-inspector/app/views/main/main.template.html b/new/ui-modules/app-inspector/app/views/main/main.template.html
new file mode 100644
index 0000000..0911647
--- /dev/null
+++ b/new/ui-modules/app-inspector/app/views/main/main.template.html
@@ -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.
+-->
+<div class="container-fluid">
+ <div class="row">
+ <div class="col-md-4">
+ <br-card>
+ <br-card-content class="entity-tree">
+ <div class="entity-tree-header">
+ <h2 class="entity-tree-title">Applications</h2>
+
+ <button class="btn btn-link entity-tree-action"
+ ng-class="{'btn-sm': !ctrl.isNotificationsBlocked, 'btn-xs': ctrl.isNotificationsBlocked}"
+ ng-if="ctrl.isNotificationsSupported"
+ ng-disabled="ctrl.isNotificationsBlocked"
+ ng-click="ctrl.toggleNotifications()">
+ <i class="fa fa-bell notifications" ng-if="!ctrl.isNotificationsBlocked"
+ ng-class="{'active': ctrl.isNotificationsEnabled}"></i>
+ <span class="fa-stack" ng-if="ctrl.isNotificationsBlocked"
+ uib-tooltip="Notifications are currently blocked. You can allow them in your browser settings"
+ tooltip-placement="left">
+ <i class="fa fa-bell fa-stack-1x"></i>
+ <i class="fa fa-ban fa-stack-2x text-danger"></i>
+ </span>
+ </button>
+
+ <a href="/brooklyn-ui-blueprint-composer" class="btn btn-sm btn-default entity-tree-action">
+ <i class="fa fa-plus"></i>
+ </a>
+ </div>
+
+ <entity-tree></entity-tree>
+ </br-card-content>
+ </br-card>
+
+ </div>
+
+ <div class="col-md-8">
+ <ui-view>
+ <h3 class="text-center text-muted">Select an entity on the left</h3>
+ </ui-view>
+ </div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/app-inspector/config/build/webpack.config.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/app-inspector/config/build/webpack.config.js b/new/ui-modules/app-inspector/config/build/webpack.config.js
new file mode 100644
index 0000000..a050fa9
--- /dev/null
+++ b/new/ui-modules/app-inspector/config/build/webpack.config.js
@@ -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.
+ */
+eval(require('fs').readFileSync('../shared/config/build/webpack.config.js')+'');
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/app-inspector/config/server.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/app-inspector/config/server.js b/new/ui-modules/app-inspector/config/server.js
new file mode 100644
index 0000000..dfba7dc
--- /dev/null
+++ b/new/ui-modules/app-inspector/config/server.js
@@ -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.
+ */
+eval(require('fs').readFileSync('../shared/config/server.js')+'');
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/app-inspector/config/test/karma.config.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/app-inspector/config/test/karma.config.js b/new/ui-modules/app-inspector/config/test/karma.config.js
new file mode 100644
index 0000000..6fc6558
--- /dev/null
+++ b/new/ui-modules/app-inspector/config/test/karma.config.js
@@ -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.
+ */
+const PRODUCTION_BUILD = process.env.NODE_ENV === 'production';
+const webpackConfig = require('./../build/webpack.config.js');
+
+module.exports = function (config) {
+ const conf = {
+ basePath: '',
+ frameworks: ['jasmine'],
+ files: [
+ {pattern: './karma.test.shim.js', watched: false}
+ ],
+ preprocessors: {
+ './karma.test.shim.js': ['webpack', 'sourcemap']
+ },
+ webpack: Object.assign({}, webpackConfig, {entry: undefined, plugins: undefined}),
+ webpackMiddleware: {
+ stats: 'errors-only'
+ },
+ webpackServer: {
+ noInfo: true
+ },
+ exclude: [],
+ colors: !PRODUCTION_BUILD,
+ logLevel: config.LOG_INFO,
+ autoWatch: !PRODUCTION_BUILD,
+ singleRun: PRODUCTION_BUILD,
+ reporters: ['progress'],
+ browsers: ['PhantomJS'],
+ plugins: [
+ require('karma-webpack'),
+ require('karma-sourcemap-loader'),
+ 'karma-jasmine',
+ 'karma-phantomjs-launcher'
+ ],
+ failOnEmptyTestSuite: false
+ };
+ config.set(conf);
+};
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/app-inspector/config/test/karma.test.shim.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/app-inspector/config/test/karma.test.shim.js b/new/ui-modules/app-inspector/config/test/karma.test.shim.js
new file mode 100644
index 0000000..3d926c0
--- /dev/null
+++ b/new/ui-modules/app-inspector/config/test/karma.test.shim.js
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+Error.stackTraceLimit = Infinity;
+
+require('angular');
+require('angular-mocks');
+require('babel-polyfill');
+
+var testsContext = require.context('./../../app', true, /\.spec\.js$/);
+testsContext.keys().forEach(testsContext);
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/app-inspector/config/test/protractor.config.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/app-inspector/config/test/protractor.config.js b/new/ui-modules/app-inspector/config/test/protractor.config.js
new file mode 100644
index 0000000..5274c81
--- /dev/null
+++ b/new/ui-modules/app-inspector/config/test/protractor.config.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.
+ */
+exports.config = {
+ framework: 'jasmine2',
+ seleniumAddress: 'http://localhost:4444/wd/hub',
+ specs: ['../../app/**/*.e2e-spec.js'],
+ baseUrl: 'http://admin:password@localhost:8080',
+ capabilities: {
+ 'browserName': 'chrome',
+ 'chromeOptions': {
+ 'args': ['--window-size=1440,1000']
+ }
+ },
+ onPrepare: function () {
+ require('babel-register');
+ },
+ jasmineNodeOpts: {
+ // If true, print colors to the terminal.
+ showColors: true,
+ // Default time to wait in ms before a test fails.
+ defaultTimeoutInterval: 30000
+ }
+};
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/app-inspector/package.json
----------------------------------------------------------------------
diff --git a/new/ui-modules/app-inspector/package.json b/new/ui-modules/app-inspector/package.json
new file mode 100644
index 0000000..fd0cfa2
--- /dev/null
+++ b/new/ui-modules/app-inspector/package.json
@@ -0,0 +1,109 @@
+{
+ "__license__": [
+ "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."
+ ],
+ "name": "brooklyn-ui-app-inspector",
+ "versionBuildNote": "BROOKLYN_VERSION_BELOW this exists so scripts update this automatically",
+ "version": "1.0.0-SNAPSHOT",
+ "description": "Brooklyn UI :: Modules - App inspector",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/apache/brooklyn-ui.git"
+ },
+ "author": "Apache Software Foundation",
+ "license": "Apache-2.0",
+ "scripts": {
+ "build": "rimraf dist && webpack --config ./config/build/webpack.config.js --bail",
+ "start": "node ./config/server.js",
+ "test": "karma start ./config/test/karma.config.js",
+ "lint": "./node_modules/.bin/eslint app/**/*.js",
+ "e2e": "protractor ./config/test/protractor.config.js"
+ },
+ "engines": {
+ "node": ">=8.0.0",
+ "npm": ">=5.0.0"
+ },
+ "brooklyn": {
+ "appname": "App inspector"
+ },
+ "dependencies": {
+ "brooklyn-ui-utils": "file:../utils",
+ "angular": "^1.6.1",
+ "angular-animate": "^1.6.1",
+ "angular-cookies": "^1.6.1",
+ "angular-resource": "^1.6.1",
+ "angular-sanitize": "^1.6.1",
+ "angular-ui-bootstrap": "^2.5.0",
+ "angular-ui-router": "^0.3.1",
+ "angular-xeditable": "^0.4.0",
+ "bootstrap": "^3.3.7",
+ "d3": "4.10.0",
+ "es6-promise": "^4.0.5",
+ "font-awesome": "^4.6.3",
+ "isomorphic-fetch": "^2.2.1",
+ "lodash": "^4.16.4",
+ "moment": "^2.15.1",
+ "ngclipboard": "^1.1.1",
+ "normalizr": "^2.2.1"
+ },
+ "devDependencies": {
+ "angular-elastic": "^2.5.1",
+ "angular-mocks": "^1.6.1",
+ "autoprefixer": "^6.5.1",
+ "babel-core": "^6.17.0",
+ "babel-loader": "^6.2.5",
+ "babel-polyfill": "^6.20.0",
+ "babel-preset-env": "^1.6.0",
+ "babel-preset-stage-0": "^6.16.0",
+ "css-loader": "^0.25.0",
+ "dotenv": "^2.0.0",
+ "ejs": "^2.5.2",
+ "ejs-html-loader": "^2.0.2",
+ "ejs-loader": "^0.3.0",
+ "eslint": "^3.8.1",
+ "exports-loader": "^0.6.3",
+ "expose-loader": "^0.7.1",
+ "express": "^4.14.0",
+ "extract-text-webpack-plugin": "^1.0.1",
+ "file-loader": "^0.9.0",
+ "html-loader": "^0.4.4",
+ "html-webpack-plugin": "^2.22.0",
+ "image-webpack-loader": "^3.0.0",
+ "imports-loader": "^0.6.5",
+ "jasmine-core": "^2.5.2",
+ "karma": "^1.3.0",
+ "karma-jasmine": "^1.0.2",
+ "karma-phantomjs-launcher": "^1.0.2",
+ "karma-sourcemap-loader": "^0.3.7",
+ "karma-webpack": "^1.8.0",
+ "less": "^2.7.1",
+ "less-loader": "^2.2.3",
+ "less-vars-to-js": "^1.1.2",
+ "phantomjs-prebuilt": "^2.1.13",
+ "postcss-loader": "^1.0.0",
+ "properties-reader": "0.0.15",
+ "proxy-middleware": "^0.15.0",
+ "raw-loader": "^0.5.1",
+ "resolve-url-loader": "^1.6.0",
+ "rimraf": "^2.5.4",
+ "style-loader": "^0.13.1",
+ "url": "^0.11.0",
+ "url-loader": "^0.5.7",
+ "webpack": "^1.13.2",
+ "webpack-dev-middleware": "^1.8.4",
+ "webpack-hot-middleware": "^2.13.0"
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/app-inspector/pom.xml
----------------------------------------------------------------------
diff --git a/new/ui-modules/app-inspector/pom.xml b/new/ui-modules/app-inspector/pom.xml
new file mode 100644
index 0000000..251b79e
--- /dev/null
+++ b/new/ui-modules/app-inspector/pom.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <artifactId>brooklyn-ui-modules-parent</artifactId>
+ <groupId>org.apache.brooklyn.ui.modules</groupId>
+ <version>${revision}</version>
+ </parent>
+
+ <artifactId>brooklyn-ui-app-inspector</artifactId>
+ <packaging>war</packaging>
+ <name>Brooklyn UI :: Modules - App inspector</name>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>dist</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>com.github.eirslett</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-resources</id>
+ <!-- here the phase you need -->
+ <phase>compile</phase>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>
+ ${project.build.directory}/${project.artifactId}-${project.version}
+ </outputDirectory>
+ <resources>
+ <resource>
+ <directory>${project.basedir}/dist</directory>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-war-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <!-- configure plugin to generate MANIFEST.MF
+ adapted from http://blog.knowhowlab.org/2010/06/osgi-tutorial-from-project-structure-to.html -->
+ <executions>
+ <execution>
+ <id>bundle-manifest</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>manifest</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <supportedProjectTypes>
+ <supportedProjectType>war</supportedProjectType>
+ <supportedProjectType>jar</supportedProjectType>
+ <supportedProjectType>bundle</supportedProjectType>
+ </supportedProjectTypes>
+ <instructions>
+ <Bundle-ManifestVersion>${project.version}</Bundle-ManifestVersion>
+ <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+ <Import-Package>
+ org.apache.brooklyn.ui.modularity.module.api,
+ org.eclipse.jetty.servlets,
+ *
+ </Import-Package>
+ <Export-Package>
+ !*
+ </Export-Package>
+ <Web-ContextPath>/${project.artifactId}</Web-ContextPath>
+ <_wab>app</_wab>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/app-inspector/src/main/resources/ui-module/config.yaml
----------------------------------------------------------------------
diff --git a/new/ui-modules/app-inspector/src/main/resources/ui-module/config.yaml b/new/ui-modules/app-inspector/src/main/resources/ui-module/config.yaml
new file mode 100644
index 0000000..133da49
--- /dev/null
+++ b/new/ui-modules/app-inspector/src/main/resources/ui-module/config.yaml
@@ -0,0 +1,22 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+name: App inspector
+slug: ${project.artifactId}
+icon: fa-search
+types:
+- home-ui-module
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/app-inspector/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/new/ui-modules/app-inspector/src/main/webapp/WEB-INF/web.xml b/new/ui-modules/app-inspector/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..9e99c5f
--- /dev/null
+++ b/new/ui-modules/app-inspector/src/main/webapp/WEB-INF/web.xml
@@ -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.
+-->
+<web-app version="2.4"
+ xmlns="http://java.sun.com/xml/ns/j2ee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
+ http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+
+ <description>Brooklyn App inspector</description>
+ <display-name>Brooklyn App inspector</display-name>
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+ <listener>
+ <listener-class>org.apache.brooklyn.ui.modularity.module.api.UiModuleListener</listener-class>
+ </listener>
+
+ <!--FILTERS :: START-->
+ <filter>
+ <filter-name>ui-module-filter</filter-name>
+ <filter-class>org.apache.brooklyn.ui.modularity.module.api.UiModuleFilter</filter-class>
+ <init-param>
+ <param-name>Cache-Control</param-name>
+ <param-value>public, max-age=604800</param-value><!--Cache static content for 1 week-->
+ </init-param>
+ </filter>
+ <filter>
+ <filter-name>GzipFilter</filter-name>
+ <filter-class>org.eclipse.jetty.servlets.GzipFilter</filter-class>
+ <init-param>
+ <param-name>mimeTypes</param-name>
+ <param-value>text/html,text/plain,text/xml,application/xhtml+xml,text/css,application/javascript,image/svg+xml</param-value>
+ </init-param>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>ui-module-filter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+ <filter-mapping>
+ <filter-name>GzipFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+ <!--FILTERS :: END-->
+
+
+</web-app>
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/blueprint-composer/.babelrc
----------------------------------------------------------------------
diff --git a/new/ui-modules/blueprint-composer/.babelrc b/new/ui-modules/blueprint-composer/.babelrc
new file mode 100644
index 0000000..222c2ba
--- /dev/null
+++ b/new/ui-modules/blueprint-composer/.babelrc
@@ -0,0 +1,6 @@
+{
+ "presets": [
+ "env",
+ "stage-0"
+ ]
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/blueprint-composer/.eslintrc.json
----------------------------------------------------------------------
diff --git a/new/ui-modules/blueprint-composer/.eslintrc.json b/new/ui-modules/blueprint-composer/.eslintrc.json
new file mode 100644
index 0000000..c4fe470
--- /dev/null
+++ b/new/ui-modules/blueprint-composer/.eslintrc.json
@@ -0,0 +1,52 @@
+{
+ "__license__": [
+ "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."
+ ],
+ "extends": "google",
+ "rules": {
+ "indent": [
+ "error",
+ 4
+ ],
+ "max-len": [
+ "warn",
+ 120
+ ],
+ "space-before-function-paren": [
+ "error",
+ "always"
+ ],
+ "sort-imports": [
+ "error",
+ {
+ "ignoreCase": false,
+ "ignoreMemberSort": false,
+ "memberSyntaxSortOrder": [
+ "none",
+ "all",
+ "multiple",
+ "single"
+ ]
+ }
+ ],
+ "quotes": [
+ "error",
+ "single"
+ ]
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/blueprint-composer/.npmrc
----------------------------------------------------------------------
diff --git a/new/ui-modules/blueprint-composer/.npmrc b/new/ui-modules/blueprint-composer/.npmrc
new file mode 100644
index 0000000..c595d19
--- /dev/null
+++ b/new/ui-modules/blueprint-composer/.npmrc
@@ -0,0 +1,18 @@
+#
+# 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.
+package-lock=false
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/blueprint-composer/Makefile
----------------------------------------------------------------------
diff --git a/new/ui-modules/blueprint-composer/Makefile b/new/ui-modules/blueprint-composer/Makefile
new file mode 100644
index 0000000..c7cb424
--- /dev/null
+++ b/new/ui-modules/blueprint-composer/Makefile
@@ -0,0 +1,49 @@
+#
+# 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.
+default: dev
+
+build:
+ @echo "Building production bundle..."
+ NODE_ENV="production" npm run build
+
+clean:
+ @echo "Cleaning modules..."
+ @rm -rf ./node_modules
+
+dev:
+ @echo "Starting dev web server..."
+ @npm start
+
+server: build
+ @echo "Starting api proxy server..."
+ NODE_ENV="production" npm start
+
+install:
+ @echo "Installing npm modules..."
+ @npm install
+
+test:
+ @echo "Running tests..."
+ @npm test
+
+setup: clean install
+
+war:
+ @mvn clean install
+
+.PHONY: build clean deploy dev install server setup test war
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/blueprint-composer/app/components/blueprint-data-manager/blueprint-data-manager.directive.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/blueprint-composer/app/components/blueprint-data-manager/blueprint-data-manager.directive.js b/new/ui-modules/blueprint-composer/app/components/blueprint-data-manager/blueprint-data-manager.directive.js
new file mode 100644
index 0000000..b3e0eac
--- /dev/null
+++ b/new/ui-modules/blueprint-composer/app/components/blueprint-data-manager/blueprint-data-manager.directive.js
@@ -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.
+ */
+import template from "./blueprint-data-manager.template.html";
+import {saveAs} from "file-saver/FileSaver";
+const VALID_FILENAME_REGEX = /^.*\.ya?ml$/
+const FILETYPE_TOKEN_REGEX = /^.*\.(.*)$/
+
+export function blueprintDataManagerDirective() {
+ return {
+ restrict: 'E',
+ template: template,
+ controller: ['$rootScope', '$scope', '$element', '$document', 'blueprintService', 'brSnackbar', controller]
+ };
+
+ function controller($rootScope, $scope, $element, $document, blueprintService, brSnackbar) {
+ var fileInputElement = null;
+ $scope.fileInputId = 'hidden-load-file-input-' + Math.random().toString(36).slice(2);
+ $scope.dragging = false;
+ $scope.targetActive = false;
+ $scope.openFileDialog = openFileDialog;
+ $scope.saveBlueprint = saveBlueprint;
+
+ $document.bind('drag dragstart dragend dragover dragenter dragleave drop', (event)=> {
+ event.preventDefault();
+ event.stopPropagation();
+ }).bind('drag dragstart dragover dragenter', (event)=> {
+ $element.addClass('drag-active');
+ }).bind('mouseout dragend drop', (event)=> {
+ $element.removeClass('drag-active');
+ $element.removeClass('drag-target-active');
+ });
+
+ $element.bind('drag dragstart dragend dragover dragenter dragleave drop', (event)=> {
+ event.preventDefault();
+ event.stopPropagation();
+ }).bind('dragstart dragover dragenter', (event)=> {
+ event.dataTransfer.dropEffect = 'copy';
+ $element.addClass('drag-active');
+ $element.addClass('drag-target-active');
+ }).bind('dragleave dragend drop', (event)=> {
+ $element.removeClass('drag-active');
+ $element.removeClass('drag-target-active');
+ }).bind('drop', (event)=> {
+ readFile(event.dataTransfer.files[0]);
+ });
+
+ $document.bind('keydown', (event)=> {
+ if (event.keyCode === 83 && (event.ctrlKey || event.metaKey)) {
+ event.preventDefault();
+ saveBlueprint();
+ }
+ });
+
+ function notify(message) {
+ $rootScope.$apply(brSnackbar.create(message));
+ }
+
+ function saveBlueprint() {
+ try {
+ var yaml = blueprintService.getAsYaml();
+ if (yaml.length > 0) {
+ var blob = new Blob([yaml], {type: 'text/plain;charset=' + document.inputEncoding || 'UTF-8'});
+ saveAs(blob, 'blueprint-' + Date.now() + '.yaml');
+ } else {
+ notify('Blueprint not saved ... empty');
+ }
+ } catch (error) {
+ notify('Blueprint saved');
+ }
+ }
+
+ function readFile(file) {
+ if (VALID_FILENAME_REGEX.test(file.name)) {
+ var reader = new FileReader();
+ reader.addEventListener("load", function () {
+ try {
+ var yaml = reader.result;
+ blueprintService.setFromYaml(yaml, true);
+ $rootScope.$broadcast('d3.redraw', true);
+ notify('Blueprint loaded successfully');
+ } catch (error) {
+ notify('Failed to load blueprint ' + error.message);
+ }
+ }, false);
+ reader.readAsText(file);
+ } else {
+ var match = file.name.match(FILETYPE_TOKEN_REGEX);
+ notify('Incorrect file type [' +
+ ((match.length === 2) ? match[1] : match[0] ) + '] ... supported file types [yml, yaml]');
+ }
+ }
+
+ function openFileDialog() {
+ fileInputElement.click();
+ }
+
+ setTimeout(()=> {
+ fileInputElement = document.getElementById($scope.fileInputId);
+ fileInputElement.addEventListener('change', (e)=> {
+ readFile(e.target.files[0]);
+ }, false);
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/blueprint-composer/app/components/blueprint-data-manager/blueprint-data-manager.style.less
----------------------------------------------------------------------
diff --git a/new/ui-modules/blueprint-composer/app/components/blueprint-data-manager/blueprint-data-manager.style.less b/new/ui-modules/blueprint-composer/app/components/blueprint-data-manager/blueprint-data-manager.style.less
new file mode 100644
index 0000000..f7c4ec9
--- /dev/null
+++ b/new/ui-modules/blueprint-composer/app/components/blueprint-data-manager/blueprint-data-manager.style.less
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+blueprint-data-manager {
+ .file-drop-container {
+ display: none;
+ transition: all linear 0.3s;
+ position: fixed;
+ top: 30vh;
+ left: 30vw;
+ width: 40vw;
+ height: 40vh;
+ border: 10px dashed @gray-lighter;
+ color: @gray-lighter;
+ .file-drop-text {
+ font-size: 50px;
+ text-align: center;
+ margin-top: 15vh;
+ }
+
+ }
+ .file-drop-container.blur {
+ backdrop-filter: blur(10px);
+ -webkit-backdrop-filter: blur(10px);
+ }
+}
+
+blueprint-data-manager.drag-active {
+ .file-drop-container {
+ display: block;
+ opacity: 1;
+ }
+}
+
+blueprint-data-manager.drag-target-active {
+ .file-drop-container {
+ border-color: @gray-light;
+ color: @gray-light;
+ .file-drag-icon {
+ color: #5cb85c;
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/blueprint-composer/app/components/blueprint-data-manager/blueprint-data-manager.template.html
----------------------------------------------------------------------
diff --git a/new/ui-modules/blueprint-composer/app/components/blueprint-data-manager/blueprint-data-manager.template.html b/new/ui-modules/blueprint-composer/app/components/blueprint-data-manager/blueprint-data-manager.template.html
new file mode 100644
index 0000000..6a962d4
--- /dev/null
+++ b/new/ui-modules/blueprint-composer/app/components/blueprint-data-manager/blueprint-data-manager.template.html
@@ -0,0 +1,32 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<div class="file-drop-container blur">
+ <div class="file-drop-text">
+ <h1>Drop file to load blueprint</h1>
+ <i class="file-drag-icon fa fa-plus-square" aria-hidden="true"></i>
+ </div>
+</div>
+<div class="file-drop-container"></div><!--2nd file-drop-container intentional (due to how JS events propogate)-->
+<button class="btn btn-primary" ng-click="saveBlueprint()">
+ <i class="fa fa-download" aria-hidden="true" title="Download the blueprint"></i>
+</button>
+<button class="btn btn-primary" ng-click="openFileDialog()">
+ <i class="fa fa-folder-open-o" aria-hidden="true" title="Import a blueprint"></i>
+</button>
+<input id="{{fileInputId}}" type="file" style="display:none">
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/blueprint-composer/app/components/breacrumbs/breadcrumbs.directive.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/blueprint-composer/app/components/breacrumbs/breadcrumbs.directive.js b/new/ui-modules/blueprint-composer/app/components/breacrumbs/breadcrumbs.directive.js
new file mode 100644
index 0000000..72b6ea8
--- /dev/null
+++ b/new/ui-modules/blueprint-composer/app/components/breacrumbs/breadcrumbs.directive.js
@@ -0,0 +1,48 @@
+/*
+ * 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 template from './breadcrumbs.template.html';
+
+export function breadcrumbsDirective() {
+ return {
+ restrict: 'E',
+ scope: {
+ entity: '<',
+ current: '<'
+ },
+ template: template,
+ link: link
+ }
+}
+
+function link(scope) {
+ if (scope.entity) {
+ scope.breadcrumbs = [];
+ if (scope.current) {
+ scope.breadcrumbs.push(scope.current);
+ }
+
+ let currentEntity = scope.entity;
+ while (currentEntity.hasParent()) {
+ scope.breadcrumbs.push(currentEntity);
+ currentEntity = currentEntity.parent;
+ }
+ scope.breadcrumbs.push(currentEntity);
+ scope.breadcrumbs.reverse();
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/blueprint-composer/app/components/breacrumbs/breadcrumbs.less
----------------------------------------------------------------------
diff --git a/new/ui-modules/blueprint-composer/app/components/breacrumbs/breadcrumbs.less b/new/ui-modules/blueprint-composer/app/components/breacrumbs/breadcrumbs.less
new file mode 100644
index 0000000..d910198
--- /dev/null
+++ b/new/ui-modules/blueprint-composer/app/components/breacrumbs/breadcrumbs.less
@@ -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.
+ */
+breadcrumbs {
+ display: block;
+
+ li:nth-child(2):before {
+ content: '\f061';
+ font-family: FontAwesome;
+ }
+
+ .active.attached:before {
+ content: '::';
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/blueprint-composer/app/components/breacrumbs/breadcrumbs.template.html
----------------------------------------------------------------------
diff --git a/new/ui-modules/blueprint-composer/app/components/breacrumbs/breadcrumbs.template.html b/new/ui-modules/blueprint-composer/app/components/breacrumbs/breadcrumbs.template.html
new file mode 100644
index 0000000..4047bd4
--- /dev/null
+++ b/new/ui-modules/blueprint-composer/app/components/breacrumbs/breadcrumbs.template.html
@@ -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.
+-->
+<ol class="breadcrumb" ng-if="breadcrumbs">
+ <li>You are editing</li>
+ <li ng-repeat="breadcrumb in breadcrumbs track by $index" ng-switch="breadcrumb" ng-class="{'active': $index === breadcrumbs.length - 1, 'attached': breadcrumb.family.id !== 'ENTITY'}">
+ <a ng-if="$index < breadcrumbs.length - 1" ui-sref="main.graphical.edit.node.entity({entityId: breadcrumb._id})">{{breadcrumb.name || 'Unnamed entity'}}</a>
+ <span ng-if="$index === breadcrumbs.length - 1">
+ {{breadcrumb.name || 'Unnamed ' + breadcrumb.family.displayName}}
+ </span>
+ </li>
+</ol>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.directive.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.directive.js b/new/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.directive.js
new file mode 100644
index 0000000..33bda2e
--- /dev/null
+++ b/new/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.directive.js
@@ -0,0 +1,181 @@
+/*
+ * 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 angular from 'angular';
+import angularAnimate from 'angular-animate';
+import uibModal from 'angular-ui-bootstrap/src/modal/index-nocss';
+import template from './catalog-saver.template.html';
+import modalTemplate from './catalog-saver.modal.template.html';
+import jsYaml from 'js-yaml';
+import brUtils from 'brooklyn-ui-utils/utils/general';
+
+const MODULE_NAME = 'brooklyn.components.catalog-saver';
+const REASONS = {
+ new: 0,
+ deploy: 1
+};
+const VIEWS = {
+ form: 0,
+ saved: 1
+};
+const TYPES = [
+ {id: 'template', label: 'Application'},
+ {id: 'entity', label: 'Entity'}
+];
+
+angular.module(MODULE_NAME, [angularAnimate, uibModal, brUtils])
+ .directive('catalogSaver', ['$rootScope', '$uibModal', saveToCatalogModalDirective])
+ .directive('catalogVersion', ['$parse', catalogVersionDirective]);
+
+export default MODULE_NAME;
+
+export function saveToCatalogModalDirective($rootScope, $uibModal) {
+ return {
+ restrict: 'E',
+ template: template,
+ scope: {
+ config: '='
+ },
+ link: link
+ };
+
+ function link($scope) {
+ $scope.buttonText = Object.keys($scope.config).length > 0 ? `Update ${$scope.config.name || $scope.config.symbolicName}` : 'Add to catalog';
+ $scope.activateModal = () => {
+ let modalInstance = $uibModal.open({
+ template: modalTemplate,
+ size: 'save',
+ controller: ['$scope', 'blueprintService', 'paletteApi', 'brUtilsGeneral', CatalogItemModalController],
+ scope: $scope,
+ });
+
+ // Promise is resolved when the modal is closed. We expect the modal to pass back the action to perform thereafter
+ modalInstance.result.then(reason => {
+ switch (reason) {
+ case REASONS.new:
+ $rootScope.$broadcast('blueprint.reset');
+ break;
+ case REASONS.deploy:
+ $rootScope.$broadcast('blueprint.deploy');
+ break;
+ }
+ });
+ };
+ }
+}
+
+export function CatalogItemModalController($scope, blueprintService, paletteApi, brUtilsGeneral) {
+ $scope.REASONS = REASONS;
+ $scope.VIEWS = VIEWS;
+ $scope.TYPES = TYPES;
+ $scope.state = {
+ pattern: '[\\w\\.\\-\\_]+',
+ view: VIEWS.form,
+ saving: false,
+ force: false,
+ isUpdate: Object.keys($scope.config).length > 0
+ };
+
+ $scope.getTitle = () => {
+ switch ($scope.state.view) {
+ case VIEWS.form:
+ return $scope.state.isUpdate ? `Update ${$scope.config.name || $scope.config.symbolicName}` : 'Add to catalog';
+ case VIEWS.saved:
+ return `${$scope.config.name || $scope.config.symbolicName} ${$scope.state.isUpdate ? 'updated' : 'saved'}`;
+ }
+ };
+
+ $scope.save = () => {
+ $scope.state.saving = true;
+ $scope.state.error = undefined;
+
+ let bom = createBom();
+ paletteApi.create(bom, {forceUpdate: $scope.state.force}).then((savedItem) => {
+ if (!angular.isArray($scope.config.versions)) {
+ $scope.config.versions = [];
+ }
+ $scope.config.versions.push($scope.config.version);
+ $scope.state.view = VIEWS.saved;
+ }).catch(error => {
+ $scope.state.error = error.error.message;
+ }).finally(() => {
+ $scope.state.saving = false;
+ });
+ };
+
+ function createBom() {
+ let blueprint = blueprintService.getAsJson();
+
+ let bomItem = {
+ id: $scope.config.symbolicName,
+ itemType: $scope.config.itemType,
+ item: blueprint
+ };
+ if (brUtilsGeneral.isNonEmpty($scope.config.name)) {
+ bomItem.name = $scope.config.name;
+ }
+ if (brUtilsGeneral.isNonEmpty($scope.config.description)) {
+ bomItem.description = $scope.config.description;
+ }
+ if (brUtilsGeneral.isNonEmpty($scope.config.iconUrl)) {
+ bomItem.iconUrl = $scope.config.iconUrl;
+ }
+
+ return jsYaml.dump({
+ 'brooklyn.catalog': {
+ bundle: `catalog-bom-${$scope.config.bundle}`,
+ version: $scope.config.version,
+ items: [bomItem]
+ }
+ });
+ }
+}
+
+export function catalogVersionDirective($parse) {
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ link: link
+ };
+
+ function link (scope, elm, attr, ctrl) {
+ if (!ctrl) {
+ return;
+ }
+
+ let matches;
+ let force;
+
+ scope.$watch(attr.catalogVersion, value => {
+ if (matches !== value) {
+ matches = value;
+ ctrl.$validate();
+ }
+ });
+ scope.$watch(attr.catalogVersionForce, value => {
+ if (force !== value) {
+ force = value;
+ ctrl.$validate();
+ }
+ });
+
+ ctrl.$validators.exist = (modelValue, viewValue) => {
+ return !angular.isDefined(matches) || ctrl.$isEmpty(viewValue) || viewValue.endsWith('SNAPSHOT') || force === true || matches.indexOf(viewValue) === -1;
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.less
----------------------------------------------------------------------
diff --git a/new/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.less b/new/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.less
new file mode 100644
index 0000000..a7faa18
--- /dev/null
+++ b/new/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.less
@@ -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.
+ */
+.next-actions {
+ margin-top: 2em;
+}
+
+@media (min-width: 768px) {
+ .modal-save {
+ width: 400px;
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.modal.template.html
----------------------------------------------------------------------
diff --git a/new/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.modal.template.html b/new/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.modal.template.html
new file mode 100644
index 0000000..39b203a
--- /dev/null
+++ b/new/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.modal.template.html
@@ -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.
+-->
+<div class="modal-header">
+ <br-svg type="close" class="pull-right" ng-click="$dismiss('Close modal')"></br-svg>
+ <h3 class="modal-title">{{getTitle()}}</h3>
+</div>
+
+<div class="modal-body add-to-catalog-modal">
+ <form ng-show="state.view === VIEWS.form" name="form" novalidate>
+ <div class="form-group" ng-class="{'has-error': form.bundle.$invalid}">
+ <label class="control-label">Bundle ID</label>
+ <div class="input-group">
+ <span class="input-group-addon">catalog-bom-</span>
+ <input ng-model="config.bundle" ng-disabled="state.saving" class="form-control" placeholder="E.g my-bundle" name="bundle" required ng-pattern="state.pattern" autofocus />
+ </div>
+ <p class="help-block" ng-show="form.bundle.$invalid">
+ <span ng-if="form.bundle.$error.required">You must specify a bundle ID</span>
+ <span ng-if="form.bundle.$error.pattern">The bundle ID can contains only letters, numbers as well a the following characters: <code>.</code>, <code>-</code> and <code>_</code></span>
+ </p>
+ </div>
+ <div class="form-group" ng-class="{'has-error': form.version.$invalid}">
+ <label class="control-label">Version</label>
+ <div class="input-group">
+ <input ng-model="config.version" ng-disabled="state.saving" class="form-control" placeholder="E.g. 1.0.0-SNAPSHOT" name="version" type="text" required catalog-version="config.versions" catalog-version-force="state.force" ng-pattern="state.pattern" />
+ <span class="input-group-btn">
+ <button class="btn btn-default" ng-class="{'btn-primary active': state.force}" ng-click="state.force = !state.force"
+ uib-tooltip="Force override of existing bundle at this version." tooltip-placement="top-right">
+ <i class="fa fa-fire"></i>
+ </button>
+ </span>
+ </div>
+ <p class="help-block">
+ <span ng-if="form.version.$error.required">You must specify a version</span>
+ <span ng-if="form.version.$error.pattern">The version can contains only letters, numbers as well a the following characters: <code>.</code>, <code>-</code> and <code>_</code></span>
+ <span ng-if="form.version.$error.exist">This version has already been used</span>
+ </p>
+ </div>
+ <div class="form-group" ng-class="{'has-error': form.symbolicName.$invalid}">
+ <label class="control-label">Blueprint symbolic name</label>
+ <input ng-model="config.symbolicName" ng-disabled="state.saving" class="form-control" placeholder="E.g my-catalog-id" name="symbolicName" required ng-pattern="state.pattern" autofocus />
+ <p class="help-block" ng-show="form.symbolicName.$invalid">
+ <span ng-if="form.symbolicName.$error.required">You must specify a blueprint symbolic name</span>
+ <span ng-if="form.symbolicName.$error.pattern">The blueprint symbolic name can contains only letters, numbers as well a the following characters: <code>.</code>, <code>-</code> and <code>_</code></span>
+ </p>
+ </div>
+
+ <div class="form-group" ng-class="{'has-error': form.itemType.$invalid}">
+ <label class="control-label">Blueprint type</label>
+ <select class="form-control" name="itemType" ng-options="type.id as type.label for type in TYPES" ng-model="config.itemType" ng-disabled="state.saving" required >
+ </select>
+ <p class="help-block" ng-show="form.itemType.$invalid">
+ <span ng-if="form.itemType.$error.required">You must specify a blueprint type</span>
+ </p>
+ </div>
+ <div class="form-group">
+ <label class="control-label">Blueprint display name</label>
+ <input ng-model="config.name" ng-disabled="state.saving" class="form-control" name="name" type="text" />
+ </div>
+ <div class="form-group">
+ <label class="control-label">Blueprint description</label>
+ <textarea ng-model="config.description" ng-disabled="state.saving" class="form-control" name="description" rows="3"></textarea>
+ </div>
+ <div class="form-group">
+ <label class="control-label">Blueprint icon url</label>
+ <input ng-model="config.iconUrl" ng-disabled="state.saving" class="form-control" name="iconUrl" type="text" />
+ </div>
+ </form>
+
+ <div class="text-center" ng-show="state.view === VIEWS.saved">
+ <div class="fa-stack fa-3x text-success">
+ <i class="fa fa-circle-thin fa-stack-2x"></i>
+ <i class="fa fa-check fa-stack-1x"></i>
+ </div>
+
+ <h3>You're all set!</h3>
+
+ <div class="next-actions">
+ <p>What would you like to do next?</p>
+ <button class="btn btn-default btn-block" ng-click="$dismiss('Continue editing')">Continue to edit this blueprint</button>
+ <button class="btn btn-info btn-block" ng-click="$close(REASONS.new)">Create a new blueprint</button>
+ <a class="btn btn-primary btn-block" ng-href="/brooklyn-ui-catalog/#!/bundles/catalog-bom-{{config.bundle}}/{{config.version}}/types/{{config.symbolicName}}/{{config.version}}">View in catalog</a>
+ <button ng-if="['template', 'entity'].indexOf(config.itemType) > -1" class="btn btn-link btn-block" ng-click="$close(REASONS.deploy)">Or deploy</button>
+ </div>
+ </div>
+
+ <div uib-alert class="alert-danger" ng-if="state.error" dismiss-on-timeout="10000" close="state.error = undefined">
+ <h4>Failed to save</h4>
+ <p>{{state.error}}</p>
+ </div>
+</div>
+
+<div class="modal-footer" ng-if="state.view === VIEWS.form">
+ <button class="btn btn-success" ng-disabled="form.$invalid || state.saving" ng-click="save()">
+ <span ng-if="!state.saving">Save</span>
+ <i ng-if="state.saving" class="fa fa-spinner fa-spin"></i>
+ </button>
+</div>
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.template.html
----------------------------------------------------------------------
diff --git a/new/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.template.html b/new/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.template.html
new file mode 100644
index 0000000..4a216af
--- /dev/null
+++ b/new/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.template.html
@@ -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.
+-->
+<button class="btn btn-info" ng-click="activateModal()">{{buttonText}}</button>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/blueprint-composer/app/components/catalog-selector/catalog-selector.directive.js
----------------------------------------------------------------------
diff --git a/new/ui-modules/blueprint-composer/app/components/catalog-selector/catalog-selector.directive.js b/new/ui-modules/blueprint-composer/app/components/catalog-selector/catalog-selector.directive.js
new file mode 100644
index 0000000..e19b1a2
--- /dev/null
+++ b/new/ui-modules/blueprint-composer/app/components/catalog-selector/catalog-selector.directive.js
@@ -0,0 +1,226 @@
+/*
+ * 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 angular from 'angular';
+import {EntityFamily} from '../util/model/entity.model';
+import template from './catalog-selector.template.html';
+
+const ITEMS_PER_PAGE = 30;
+// fields in either bundle or type record:
+const FIELDS_TO_SEARCH = ['name', 'displayName', 'symbolicName', 'version', 'type', 'supertypes', 'containingBundle', 'description', 'displayTags'];
+
+export function catalogSelectorDirective() {
+ return {
+ restrict: 'E',
+ scope: {
+ family: '<',
+ onSelect: '&',
+ itemsPerPage: '<',
+ reservedKeys: '<?'
+ },
+ template: template,
+ controller: ['$scope', '$q', '$uibModal', '$log', 'paletteApi', 'paletteDragAndDropService', 'iconGenerator', controller]
+ };
+}
+
+export function catalogSelectorSearchFilter() {
+ return function (items, search) {
+ if (search) {
+ return items.filter(function (item) {
+ return search.toLowerCase().split(' ').reduce( (found, part) =>
+ found &&
+ FIELDS_TO_SEARCH
+ .filter(field => item.hasOwnProperty(field) && item[field])
+ .reduce((match, field) => {
+ if (match) return true;
+ let text = item[field];
+ if (!text.toLowerCase) {
+ text = JSON.stringify(text).toLowerCase();
+ } else {
+ text = text.toLowerCase();
+ }
+ return match || text.indexOf(part) > -1;
+ }, false)
+ , true);
+ });
+ } else {
+ return items;
+ }
+ }
+}
+
+export function catalogSelectorSortFilter($filter) {
+ return function (items, family) {
+ return items.sort(function (left, right) {
+ let nameLeft;
+ let nameRight;
+ if (family) {
+ switch (family) {
+ case EntityFamily.ENTITY:
+ case EntityFamily.SPEC:
+ case EntityFamily.POLICY:
+ case EntityFamily.ENRICHER:
+ case EntityFamily.LOCATION:
+ nameLeft = $filter('entityName')(left);
+ nameRight = $filter('entityName')(right);
+ break;
+ }
+ }
+
+ if (!nameLeft || !nameRight) {
+ return 0;
+ }
+ let nameCompare = nameLeft.localeCompare(nameRight);
+ if (nameCompare !== 0) {
+ return nameCompare;
+ }
+ let versionCompare = right.version.localeCompare(left.version);
+ if (versionCompare !== 0) {
+ return versionCompare
+ }
+ // TODO should symbolic name be the sorted field?
+ let symNameCompare = left.symbolicName.localeCompare(right.symbolicName);
+ if (symNameCompare !== 0) {
+ return symNameCompare
+ }
+ let containingBundleCompare = right.containingBundle.localeCompare(left.containingBundle);
+ if (containingBundleCompare !== 0) {
+ return containingBundleCompare
+ }
+ return 0;
+ });
+ }
+}
+
+function controller($scope, $q, $uibModal, $log, paletteApi, paletteDragAndDropService, iconGenerator) {
+ $scope.pagination = {
+ page: 1,
+ itemsPerPage: $scope.itemsPerPage || ITEMS_PER_PAGE
+ };
+ $scope.state = {
+ orders: ['name', 'type', 'id'],
+ currentOrder: 'name'
+ };
+
+ $scope.getPlaceHolder = function () {
+ return 'Search';
+ };
+
+ $scope.isLoading = true;
+
+ $scope.$watch('search', () => {
+ $scope.freeFormTile = {
+ symbolicName: $scope.search,
+ name: $scope.search,
+ displayName: $scope.search,
+ supertypes: [$scope.family.superType]
+ };
+ });
+
+ $scope.getItems = function (search) {
+ let defer = $q.resolve([]);
+
+ switch ($scope.family) {
+ case EntityFamily.ENTITY:
+ case EntityFamily.SPEC:
+ defer = paletteApi.getTypes({params: {supertype: 'entity', fragment: search}});
+ break;
+ case EntityFamily.POLICY:
+ defer = paletteApi.getTypes({params: {supertype: 'policy', fragment: search}});
+ break;
+ case EntityFamily.ENRICHER:
+ defer = paletteApi.getTypes({params: {supertype: 'enricher', fragment: search}});
+ break;
+ case EntityFamily.LOCATION:
+ defer = paletteApi.getLocations();
+ break;
+ }
+
+ return defer.then(data => {
+ return data;
+ }).catch(error => {
+ return [];
+ }).finally(() => {
+ $scope.isLoading = false;
+ });
+ };
+ $scope.onSelectItem = function (item) {
+ if (angular.isFunction($scope.onSelect)) {
+ $scope.onSelect({item: item});
+ }
+ $scope.search = '';
+ };
+ $scope.onDragItem = function (item, event) {
+ let frame = document.createElement('div');
+ frame.classList.add('drag-frame');
+ event.target.appendChild(frame);
+ setTimeout(function() {
+ // can remove at end of this cycle, browser will have grabbed its drag image
+ frame.parentNode.removeChild(frame);
+ }, 0);
+ /* have tried many other ways to get a nice drag image;
+ this seems to work best, adding an empty div which forces the size to be larger,
+ so when grabbing the image it grabs the drop-shadow.
+ things that _didn't_ work include:
+ - styling event.target now then unstyling (normally this would work, in posts on the web, but it doesn't here; angular?)
+ - make a restyled cloned copy offscreen (this comes so close but remote img srcs aren't loaded
+ */
+
+ paletteDragAndDropService.dragStart(item);
+ };
+ $scope.onDragEnd = function (item, event) {
+ paletteDragAndDropService.dragEnd();
+ };
+ $scope.allowFreeForm = function () {
+ return [
+ EntityFamily.LOCATION
+ ].indexOf($scope.family) > -1;
+ };
+ $scope.isReserved = function () {
+ if (!$scope.reservedKeys || !angular.isArray($scope.reservedKeys)) {
+ return false;
+ }
+ return $scope.reservedKeys.indexOf($scope.search) > -1;
+ };
+ $scope.onImageError = (scope, el, attrs) => {
+ $log.warn("Icon for "+attrs.itemId+" at "+angular.element(el).attr("src")+" could not be loaded; generating icon");
+ angular.element(el).attr("src", iconGenerator(attrs.itemId));
+ };
+
+ // Init
+ $scope.items = [];
+ function getDisplayTags(tags) {
+ if (!tags || !tags.length || !tags.reduce) return tags;
+ return tags.reduce((result, tag) => {
+ if (!(/[=:\[\]()]/.exec(tag))) {
+ result.push(tag);
+ }
+ return result;
+ }, []);
+ }
+ $scope.getItems().then((items)=> {
+ // add displayTags, as any tag that doesn't contain = : or ( ) [ ]
+ // any tag that is an object will be eliminated as it is toStringed to make [ object object ]
+ items.forEach(item => {
+ if (item.tags) {
+ item.displayTags = getDisplayTags(item.tags);
+ }
+ });
+ $scope.items = items;
+ });
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29927b73/new/ui-modules/blueprint-composer/app/components/catalog-selector/catalog-selector.less
----------------------------------------------------------------------
diff --git a/new/ui-modules/blueprint-composer/app/components/catalog-selector/catalog-selector.less b/new/ui-modules/blueprint-composer/app/components/catalog-selector/catalog-selector.less
new file mode 100644
index 0000000..e0bdb73
--- /dev/null
+++ b/new/ui-modules/blueprint-composer/app/components/catalog-selector/catalog-selector.less
@@ -0,0 +1,213 @@
+/*
+ * 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.
+ */
+catalog-selector {
+ @duration: 0.3s;
+ @duration-item: 0.1s;
+
+ display: block;
+ margin-top: 15px;
+
+ .grid {
+ margin-bottom: 15px;
+ }
+ .pagination {
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+
+ .catalog-palette {
+ padding-left: 10px;
+ padding-right: 10px;
+ }
+ .catalog-palette-item {
+ padding-left: 5px;
+ padding-right: 5px;
+ }
+
+ .item {
+ margin-top: 9px;
+ padding: 3px;
+ cursor: copy;
+ transition: all @duration-item ease;
+ position: relative;
+ background: white; //useful when dragging
+ box-shadow: 0 0 rgba(0, 0, 0, 0.1), 0 1px 2px 1px rgba(0, 0, 0, 0.2);
+ &:hover {
+ box-shadow: 0 0 rgba(0, 0, 0, 0.2), 0 2px 4px 1px rgba(0, 0, 0, 0.2);
+ transform: scale(1.1);
+
+ .fa-info-circle {
+ opacity: 1;
+ }
+ }
+ .drag-frame {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ transform: scale(1.15);
+ }
+
+ .fa-info-circle {
+ position: absolute;
+ top: 2px;
+ right: 2px;
+ padding: 3px 3px 3px 4px; // this seems to center it better than 3px all around
+ opacity: 0;
+ transition: opacity @duration ease, color @duration ease;
+ cursor: pointer;
+ color: mix(@gray-light, @gray-lighter, 50%);
+ background-color: rgba(255, 255, 255, 0.75);
+ border-radius: 10px;
+ &:hover {
+ color: @gray;
+ }
+ }
+
+ .item-logo {
+ position: relative;
+ width: 100%;
+ height: 60px;
+ overflow: hidden;
+
+ & > img {
+ -webkit-user-drag: none;
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ margin: auto;
+ max-width: 90%;
+ max-height: 100%;
+ }
+ }
+
+ .item-content {
+ &.deprecated {
+ color: @gray-light;
+ }
+ padding-left: 2px;
+ padding-right: 2px;
+ padding-top: 2px;
+ padding-bottom: 4px;
+ overflow: hidden;
+
+ h3 {
+ font-size: 0.75em;
+ text-align: center;
+ margin: 0;
+ .text-overflow();
+ }
+ }
+ }
+ .form-group {
+ margin-top: 3px;
+ margin-bottom: 3px;
+ }
+
+ .spinner-area {
+ height: 300px;
+ position: relative;
+
+ .spinner {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%,-50%);
+
+ .svg-container {
+ width: 50px;
+ height: 50px;
+ transform-origin: 50% 50%;
+ animation: interstitial-spinner-animation 1.0s infinite linear;
+
+ circle {
+ fill: none;
+ stroke-width: 7;
+ &.foreground {
+ stroke: @brand-primary;
+ stroke-dasharray: 105 360;
+ }
+ &.background {
+ stroke: rgba(0, 0, 0, 0.05);
+ }
+ }
+
+ @keyframes interstitial-spinner-animation {
+ 100% {
+ transform: rotate(360deg);
+ }
+ }
+ }
+ }
+ }
+}
+
+.catalog-selector-popover {
+ // these numbers are extremely brittle, for instance -5px or -8px causes it to shift up 100px or so
+ // old discussion in history
+ margin-top: -6px;
+ max-width: 400px;
+
+ .palette-item-quick-info {
+ word-wrap: break-word;
+ word-break: break-word;
+ .quick-info-metadata {
+ .text-muted();
+ .text-overflow();
+ white-space: normal;
+ word-break: break-all;
+ p {
+ margin-bottom: 0;
+ margin-left: 1.5em;
+ font-size: 90%;
+ .type-symbolic-name {
+ font-weight: bold;
+ }
+ }
+ .mini-icon {
+ width: 1.5em;
+ overflow-x: visible;
+ margin-left: -1.5em;
+ text-align: center;
+ }
+ }
+ .deprecated-marker {
+ float: right;
+ color: @brand-warning;
+ }
+ .quick-info-description {
+ border-top: 1px solid @popover-border-color;
+ border-bottom: 1px solid @popover-border-color;
+ padding-top: 10px;
+ padding-bottom: 10px;
+ margin-top: 10px;
+ margin-bottom: 10px;
+ }
+ .palette-item-tag {
+ margin-right: 4px;
+ }
+ }
+
+ p:last-child {
+ margin-bottom: 0;
+ }
+}