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/08/20 09:39:21 UTC
[01/12] brooklyn-ui git commit: add basic docs for the customizations
Repository: brooklyn-ui
Updated Branches:
refs/heads/master 0f1c87018 -> 57e9726d7
add basic docs for the customizations
and remove reference of tool
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/commit/f9d239ed
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/tree/f9d239ed
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/diff/f9d239ed
Branch: refs/heads/master
Commit: f9d239ed03d0f1b0b957c746603f4bfd09b53cf8
Parents: 44b38ea
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Aug 3 16:22:03 2018 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Aug 3 16:22:03 2018 +0100
----------------------------------------------------------------------
README.md | 2 +-
docs/customizations.md | 13 +++++++++++++
2 files changed, 14 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/f9d239ed/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index d522f56..2b5dc56 100644
--- a/README.md
+++ b/README.md
@@ -53,9 +53,9 @@ is to run `make` in the relevant module directory, with a Brooklyn REST server o
For developers, the following links may be useful:
* [Overview and architecture of the project](docs/overview.md)
-* [Creating a new UI module](tools/module-generator/README.md)
* [Building individual module / Dev environment](ui-modules/home/README.md)
* [Skinning the UI with custom themes](docs/skinning.md)
+* [Customizing and embedding the UI](docs/customizations.md)
## Troubleshooting
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/f9d239ed/docs/customizations.md
----------------------------------------------------------------------
diff --git a/docs/customizations.md b/docs/customizations.md
new file mode 100644
index 0000000..4458a88
--- /dev/null
+++ b/docs/customizations.md
@@ -0,0 +1,13 @@
+
+The UI is designed so modules can be used individually, or added as library modules in the usual NodeJS manner
+and widgets cherry-picked as needed.
+
+There are a number of points where UI default choices can be overridden:
+
+* Actions on Composer: by changing the config value for `'actionServiceProvider'` in `ui-modules/blueprint-composer/app/index.js`,
+ a different set of actions can be displayed on the composer screen
+
+* Composer - Virtual palette items and alternate catalog endpoints: by registering a different `blueprintServiceProvider`
+ items for the palette can come from Brooklyn and/or other sources, with other sources converted to "virtual items" that
+ can extend existing Brooklyn items
+
[09/12] brooklyn-ui git commit: allow ui modules to specify better
which should be preferred
Posted by he...@apache.org.
allow ui modules to specify better which should be preferred
otherwise it can be a little unpredictable which module is active
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/commit/4026a4b7
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/tree/4026a4b7
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/diff/4026a4b7
Branch: refs/heads/master
Commit: 4026a4b7bc3bef128fcbfaa4a17b89593105844b
Parents: 82d37c4
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Aug 9 00:24:48 2018 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Aug 9 02:56:42 2018 +0100
----------------------------------------------------------------------
modularity-server/README.md | 23 +++
modularity-server/module-api/pom.xml | 12 ++
.../ui/modularity/module/api/UiModule.java | 13 +-
.../modularity/module/api/UiModuleListener.java | 156 ++++++++++++++++++-
.../module/api/internal/UiModuleImpl.java | 39 ++++-
5 files changed, 232 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/4026a4b7/modularity-server/README.md
----------------------------------------------------------------------
diff --git a/modularity-server/README.md b/modularity-server/README.md
index c68563f..c228b72 100644
--- a/modularity-server/README.md
+++ b/modularity-server/README.md
@@ -9,6 +9,29 @@ This folder contains projects which help working with and extending the UI:
Note that UI modules themselves are in `../ui-modules`.
+# UI Module Config
+
+A Brooklyn UI module is a WAR being installed which includes a file `ui-module/config.yaml`
+defining at minimum:
+
+* a `name` (to be displayed in the UI)
+* a `slug` (used internally for reference; usually this is set to be `${project.artifactId}` and substituted during the build)
+* an `icon` CSS class set, usually Font Awesome based (e.g. `fa-home`).
+
+Optionally it can include:
+
+* a list of `type` tokens for arbitrary use (currently `home-ui-module` is used to indicate a module should
+ show up on the home page, and `library-ui-module` to indicate it should be excluded from the menu)
+* `actions` (not used currently, see code to understand)
+* `stopExisting` (boolean, whether to stop lower-numbered bundles listening on the same
+ context-path declared in `web.xml`, defaulting to `true`)
+* `supersedesBundles` (a list of `bundle-regex:version-regex` of bundles that should be stopped
+ when this UI module is installed; this is used for downstream projects that may override UI modules
+ and wish to ensure their modules are used without relying on bundle install order (but often bundle install order is sufficient))
+
+The Karaf command `web:list` is helpful in determining which module is actually active
+when there are conflicts for a given context path.
+
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/4026a4b7/modularity-server/module-api/pom.xml
----------------------------------------------------------------------
diff --git a/modularity-server/module-api/pom.xml b/modularity-server/module-api/pom.xml
index a68286a..c05c5a9 100644
--- a/modularity-server/module-api/pom.xml
+++ b/modularity-server/module-api/pom.xml
@@ -63,6 +63,18 @@
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.karaf.web</groupId>
+ <artifactId>org.apache.karaf.web.core</artifactId>
+ <version>${karaf.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.web</groupId>
+ <artifactId>pax-web-spi</artifactId>
+ <version>6.0.6</version> <!-- as it's provided we just need compile support; runtime is pulled in by karaf -->
+ <scope>provided</scope>
+ </dependency>
<!--TEST SCOPE-->
<dependency>
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/4026a4b7/modularity-server/module-api/src/main/java/org/apache/brooklyn/ui/modularity/module/api/UiModule.java
----------------------------------------------------------------------
diff --git a/modularity-server/module-api/src/main/java/org/apache/brooklyn/ui/modularity/module/api/UiModule.java b/modularity-server/module-api/src/main/java/org/apache/brooklyn/ui/modularity/module/api/UiModule.java
index 7fc26ef..43bdeb2 100644
--- a/modularity-server/module-api/src/main/java/org/apache/brooklyn/ui/modularity/module/api/UiModule.java
+++ b/modularity-server/module-api/src/main/java/org/apache/brooklyn/ui/modularity/module/api/UiModule.java
@@ -48,14 +48,25 @@ public interface UiModule {
* @return The module types eg single-page-app, external-ui
*/
Set<String> getTypes();
+
+ /**
+ * @return List of "bundle-regex" or "bundle-regex:version-regex" of bundles that should be stopped when this is installed.
+ * Useful if supplying a bundle to replace other bundles.
+ */
+ Set<String> getSupersedesBundles();
/**
+ * @return Whether to web-stop any bundles listening on the same endpoint.
+ */
+ boolean getStopExisting();
+
+ /**
* @return The module path
*/
String getPath();
/**
- * @return Registed module actions
+ * @return Registered module actions
*/
List<UiModuleAction> getActions();
}
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/4026a4b7/modularity-server/module-api/src/main/java/org/apache/brooklyn/ui/modularity/module/api/UiModuleListener.java
----------------------------------------------------------------------
diff --git a/modularity-server/module-api/src/main/java/org/apache/brooklyn/ui/modularity/module/api/UiModuleListener.java b/modularity-server/module-api/src/main/java/org/apache/brooklyn/ui/modularity/module/api/UiModuleListener.java
index 29f6cd9..8125e44 100644
--- a/modularity-server/module-api/src/main/java/org/apache/brooklyn/ui/modularity/module/api/UiModuleListener.java
+++ b/modularity-server/module-api/src/main/java/org/apache/brooklyn/ui/modularity/module/api/UiModuleListener.java
@@ -19,26 +19,33 @@
package org.apache.brooklyn.ui.modularity.module.api;
import java.io.InputStream;
+import java.net.URL;
import java.time.Duration;
+import java.util.Collection;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Map;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
+import org.apache.brooklyn.ui.modularity.module.api.internal.UiModuleImpl;
+import org.apache.karaf.web.WebBundle;
+import org.apache.karaf.web.WebContainerService;
+import org.ops4j.pax.web.service.spi.WebEvent;
+import org.ops4j.pax.web.service.spi.WebListener;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.Yaml;
-import org.apache.brooklyn.ui.modularity.module.api.internal.UiModuleImpl;
-
/** Invoked by modules in their web.xml to create and register the {@link UiModule} service for that UI module. */
public class UiModuleListener implements ServletContextListener {
@@ -47,6 +54,7 @@ public class UiModuleListener implements ServletContextListener {
public static final String CONFIG_PATH = "/WEB-INF/classes/ui-module/config.yaml";
private ServiceRegistration<UiModule> registration;
+ private AtomicReference<WebListener> listener = new AtomicReference<>();
public UiModuleListener() {
}
@@ -54,13 +62,15 @@ public class UiModuleListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent servletContextEvent) {
final UiModule uiModule = createUiModule(servletContextEvent.getServletContext());
Object moduleBundle = servletContextEvent.getServletContext().getAttribute("osgi-bundlecontext");
+ final Bundle bundle = moduleBundle instanceof BundleContext ? ((BundleContext)moduleBundle).getBundle() : FrameworkUtil.getBundle(this.getClass());
+
+ initWebListener(bundle);
// register service against the bundle where it came from if possible (it always is, from what I've seen)
// this prevents errors if this.getClass()'s bundle is not yet active and avoids needing to delay
// (it also means service would be unregistered on that bundle destroy without listening for servlet context
// destroy but servlet context destroy is useful for symmetry with this and in case it is destroyed without
// destroying the bundle; also we were already doing it)
- final Bundle bundle = moduleBundle instanceof BundleContext ? ((BundleContext)moduleBundle).getBundle() : FrameworkUtil.getBundle(this.getClass());
try {
if (bundle.getState() != Bundle.ACTIVE) {
@@ -69,13 +79,145 @@ public class UiModuleListener implements ServletContextListener {
bundle.getSymbolicName(), uiModule.getName(), bundle.getState(), TIMEOUT);
blockUntilBundleStarted(bundle, TIMEOUT);
}
- LOG.info("Registering new Brooklyn UI module [{}] to [{}] (bundle [{}:{}])", uiModule.getName(), uiModule.getPath(), bundle.getSymbolicName(), bundle.getVersion());
+ LOG.info("Registering new Brooklyn UI module {}:{} [{}] called '{}' on context-path '{}'",
+ bundle.getSymbolicName(), bundle.getVersion(), bundle.getVersion(), uiModule.getName(), uiModule.getPath() );
registration = bundle.getBundleContext().registerService(UiModule.class, uiModule, EMPTY_DICTIONARY);
+ LOG.trace("ServletContextListener on initializing UI module "+bundle.getSymbolicName()+" ["+bundle.getBundleId()+"] "
+ + "to "+uiModule.getPath()+", checking whether any bundles need stopping");
+ stopAnyExistingOrSuperseded(uiModule, bundle);
} catch (Exception e) {
LOG.error("Failed registration of Brooklyn UI module [" + uiModule.getName() + "] to [" + uiModule.getPath() + "]: "+e, e);
}
}
+
+ private void initWebListener(Bundle bundle) {
+ if (listener.compareAndSet(null, new UiModuleWebListener())) {
+ bundle.getBundleContext().registerService(WebListener.class, listener.get(), null);
+ }
+ }
+
+ public class UiModuleWebListener implements WebListener {
+ long lastId = -1;
+ @Override
+ public void webEvent(WebEvent event) {
+ try {
+ if (event.getType() == WebEvent.DEPLOYING && lastId != event.getBundleId()) {
+ // on deployment of new bundles check whether they are UI modules
+ // (this seems to be called about 10 times for any deployment; keep a note of the last bundle id to avoid duplication
+ lastId = event.getBundleId();
+ URL config = event.getBundle().getResource(CONFIG_PATH);
+ if (config!=null) {
+ LOG.trace("WebListener on deploying UI module "+event.getBundle().getSymbolicName()+" ["+event.getBundleId()+"] "
+ + "to "+event.getContextPath()+", checking whether any bundles need stopping");
+ stopAnyExistingOrSuperseded(createUiModule(config.openStream(), event.getContextPath()), event.getBundle());
+ }
+ }
+ } catch (Exception e) {
+ if (!isBundleStartingOrActive(event.getBundle())) {
+ LOG.debug("Error listening to UI module bundle "+event.getBundleName()+" in state "+event.getBundle().getState()+" (not starting/active, so not a serious problem, esp if we just stopped it): "+e);
+ } else {
+ LOG.warn("Error listening to UI module bundle "+event.getBundleName()+" start: "+e, e);
+ }
+ }
+ }
+ }
+
+ protected void stopAnyExistingOrSuperseded(final UiModule uiModule, final Bundle bundle) throws Exception {
+ if (uiModule.getStopExisting()) {
+ stopExistingModulesListeningOnOurEndpoint(bundle, uiModule);
+ }
+ if (!uiModule.getSupersedesBundles().isEmpty()) {
+ stopSupersededBundles(bundle, uiModule);
+ }
+ }
+ /** stop modules on the same endpoint that with a lower number ID;
+ * or if a module supersedes us, stop ourselves */
+ private void stopExistingModulesListeningOnOurEndpoint(Bundle bundle, UiModule uiModule) throws Exception {
+ ServiceReference<WebContainerService> webS = bundle.getBundleContext().getServiceReference(WebContainerService.class);
+ WebContainerService web = bundle.getBundleContext().getService(webS);
+
+ for (WebBundle bi: web.list()) {
+ if (bi.getBundleId()==bundle.getBundleId()) continue;
+ if (uiModule.getPath().equals(bi.getContextPath()) || (uiModule.getPath().equals("") && bi.getContextPath().equals("/"))) {
+ Bundle bb = bundle.getBundleContext().getBundle(bi.getBundleId());
+ Collection<ServiceReference<UiModule>> modules = bundle.getBundleContext().getServiceReferences(UiModule.class, null);
+ for (ServiceReference<UiModule> modS: modules) {
+ if (modS.getBundle()!=null && modS.getBundle().getBundleId()==bi.getBundleId()) {
+ // found UiModule for the potentially conflicting bundle
+ UiModule mod = bundle.getBundleContext().getService(modS);
+ if (isBundleSuperseded(mod, bundle)) {
+ // if that module supersedes us, don't stop them, stop us!
+ stopBundle(bundle, "context path "+bi.getContextPath()+" is in use by "+bb.getSymbolicName()+" ["+bb.getBundleId()+"]");
+ return;
+ }
+ }
+ }
+ if (bb.getBundleId() < bundle.getBundleId()) {
+ // in case of context-path conflict with no declared supersedes relationship, prefer the higher number (later installed)
+ stopBundle(bb, "context path "+bi.getContextPath()+" is needed for installation of "+bundle.getSymbolicName()+" ["+bundle.getBundleId()+"]");
+ }
+ }
+ }
+ }
+
+ /** stop modules superseded by us */
+ private void stopSupersededBundles(Bundle bundle, UiModule uiModule) {
+ LOG.trace("Calling stopSuperseded on install of "+bundle.getSymbolicName()+"; will stop any of "+uiModule.getSupersedesBundles());
+ for (Bundle b: bundle.getBundleContext().getBundles()) {
+ if (b.getBundleId()==bundle.getBundleId()) continue;
+ if (isBundleSuperseded(uiModule, b)) {
+ stopBundle(b, "it is superseded by "+bundle.getSymbolicName()+" ["+bundle.getBundleId()+"]");
+ }
+ }
+ }
+
+ private boolean isBundleSuperseded(UiModule module, Bundle bundle) {
+ if (module.getSupersedesBundles()!=null) {
+ for (String superseded: module.getSupersedesBundles()) {
+ String bn = superseded;
+ String version = null;
+ int split = bn.indexOf(':');
+ if (split>=0) {
+ version = bn.substring(split+1);
+ bn = bn.substring(0, split);
+ }
+ if (bundle.getSymbolicName().matches(bn) && (version==null || bundle.getVersion().toString().matches(version))) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ protected void stopBundle(Bundle bundleToStop, String reason) {
+ boolean isActive = isBundleStartingOrActive(bundleToStop);
+ String message = "stopping bundle "+bundleToStop.getSymbolicName()+" ["+bundleToStop.getBundleId()+"]; "+reason;
+ if (!isActive) {
+ LOG.trace("Not "+message+"; but that conflicting bundle is not starting or active");
+ // if it tries to start it should abort itself
+ return;
+ }
+ LOG.info("UiModules: " + message);
+ new Thread(() -> {
+ try {
+ bundleToStop.stop();
+ } catch (Exception e) {
+ LOG.warn("UiModules: error "+message+": "+e, e);
+ }
+ }).start();
+ }
+
+ protected boolean isBundleStartingOrActive(Bundle bundleToStop) {
+ switch (bundleToStop.getState()) {
+ case Bundle.START_TRANSIENT:
+ case Bundle.STARTING:
+ case Bundle.ACTIVE:
+ return true;
+ }
+ return false;
+ }
+
private void blockUntilBundleStarted(final Bundle bundle, Duration timeout) throws InterruptedException {
long endTime = System.currentTimeMillis() + timeout.toMillis();
do {
@@ -90,7 +232,7 @@ public class UiModuleListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
- LOG.info("Un-Registering Brooklyn UI module at [{}]", servletContextEvent.getServletContext().getContextPath());
+ LOG.info("Unregistering Brooklyn UI module at [{}]", servletContextEvent.getServletContext().getContextPath());
if (registration != null) {
try {
registration.unregister();
@@ -108,6 +250,10 @@ public class UiModuleListener implements ServletContextListener {
private UiModule createUiModule(ServletContext servletContext) {
final InputStream is = servletContext.getResourceAsStream(CONFIG_PATH);
final String path = servletContext.getContextPath();
+ return createUiModule(is, path);
+ }
+
+ protected UiModule createUiModule(final InputStream is, final String path) {
if (is == null) {
throw new RuntimeException(String.format("Module on path [%s] will not be registered as it does not have any configuration", path));
}
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/4026a4b7/modularity-server/module-api/src/main/java/org/apache/brooklyn/ui/modularity/module/api/internal/UiModuleImpl.java
----------------------------------------------------------------------
diff --git a/modularity-server/module-api/src/main/java/org/apache/brooklyn/ui/modularity/module/api/internal/UiModuleImpl.java b/modularity-server/module-api/src/main/java/org/apache/brooklyn/ui/modularity/module/api/internal/UiModuleImpl.java
index d3fa999..845cc8a 100644
--- a/modularity-server/module-api/src/main/java/org/apache/brooklyn/ui/modularity/module/api/internal/UiModuleImpl.java
+++ b/modularity-server/module-api/src/main/java/org/apache/brooklyn/ui/modularity/module/api/internal/UiModuleImpl.java
@@ -19,23 +19,25 @@
package org.apache.brooklyn.ui.modularity.module.api.internal;
import java.util.ArrayList;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
-import com.google.common.base.Optional;
-
import org.apache.brooklyn.ui.modularity.module.api.UiModule;
import org.apache.brooklyn.ui.modularity.module.api.UiModuleAction;
+import com.google.common.base.Optional;
+
public class UiModuleImpl implements UiModule {
private String id;
private String name;
private String slug;
private String icon;
- private Set<String> types = new HashSet<>();
+ private Set<String> types = new LinkedHashSet<>();
+ private Set<String> supersedesBundles = new LinkedHashSet<>();
+ private boolean stopExisting = true;
private String path;
private List<UiModuleAction> actions = new ArrayList<>();
@@ -49,7 +51,16 @@ public class UiModuleImpl implements UiModule {
if (types != null && types instanceof List) {
@SuppressWarnings("unchecked")
List<String> typesTyped = (List<String>) types;
- result.setTypes(new HashSet<String>(typesTyped));
+ result.setTypes(new LinkedHashSet<String>(typesTyped));
+ }
+ final Object supersedes = incomingMap.get("supersedes");
+ if (supersedes != null && supersedes instanceof List) {
+ @SuppressWarnings("unchecked")
+ List<String> supersedesTyped = (List<String>) supersedes;
+ result.setSupersedesBundles(new LinkedHashSet<String>(supersedesTyped));
+ }
+ if (incomingMap.containsKey("stopExisting")) {
+ result.setStopExisting(Boolean.getBoolean((String) incomingMap.get("stopExisting")));
}
final Object actions = incomingMap.get("actions");
if (actions != null && actions instanceof List) {
@@ -88,6 +99,16 @@ public class UiModuleImpl implements UiModule {
}
@Override
+ public Set<String> getSupersedesBundles() {
+ return supersedesBundles;
+ }
+
+ @Override
+ public boolean getStopExisting() {
+ return stopExisting;
+ }
+
+ @Override
public String getPath() {
return path;
}
@@ -117,6 +138,14 @@ public class UiModuleImpl implements UiModule {
this.types = types;
}
+ public void setSupersedesBundles(final Set<String> supersedesBundles) {
+ this.supersedesBundles = supersedesBundles;
+ }
+
+ public void setStopExisting(final boolean stopExisting) {
+ this.stopExisting = stopExisting;
+ }
+
public void setPath(String path) {
this.path = path;
}
[10/12] brooklyn-ui git commit: fix dependencies on changed classes
Posted by he...@apache.org.
fix dependencies on changed classes
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/commit/4d606727
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/tree/4d606727
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/diff/4d606727
Branch: refs/heads/master
Commit: 4d606727f15ebad753c3e6696dc55f65d85419f1
Parents: e6f7653
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Aug 9 10:41:15 2018 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Aug 9 10:41:15 2018 +0100
----------------------------------------------------------------------
.../ui/modularity/ExternalUiModule.java | 29 +++++++++++++++++---
.../BrooklynExternalUiModuleEnricher.java | 23 ++++++++++++----
2 files changed, 43 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/4d606727/modularity-server/external-modules/src/main/java/org/apache/brooklyn/ui/modularity/ExternalUiModule.java
----------------------------------------------------------------------
diff --git a/modularity-server/external-modules/src/main/java/org/apache/brooklyn/ui/modularity/ExternalUiModule.java b/modularity-server/external-modules/src/main/java/org/apache/brooklyn/ui/modularity/ExternalUiModule.java
index 4aaf969..7866efe 100644
--- a/modularity-server/external-modules/src/main/java/org/apache/brooklyn/ui/modularity/ExternalUiModule.java
+++ b/modularity-server/external-modules/src/main/java/org/apache/brooklyn/ui/modularity/ExternalUiModule.java
@@ -25,6 +25,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.apache.brooklyn.ui.modularity.module.api.UiModule;
+import org.apache.brooklyn.ui.modularity.module.api.UiModuleAction;
import org.apache.brooklyn.util.collections.MutableList;
import org.apache.brooklyn.util.collections.MutableSet;
import org.osgi.service.component.annotations.Activate;
@@ -36,9 +38,6 @@ import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableList;
-import org.apache.brooklyn.ui.modularity.module.api.UiModule;
-import org.apache.brooklyn.ui.modularity.module.api.UiModuleAction;
-
@Component(
name = ExternalUiModule.PID,
configurationPid = ExternalUiModule.PID,
@@ -59,12 +58,16 @@ public class ExternalUiModule implements UiModule {
private final String KEY_ICON = "icon";
private final String KEY_TYPES = "types";
private final String[] REQUIRED_KEYS = new String[] {KEY_ID, KEY_NAME, KEY_URL, KEY_ICON};
+ private final String KEY_SUPERSEDES = "supersedes";
+ private final String KEY_STOP_EXISTING = "stopExisting";
private String id;
private String name;
private String icon;
private String url;
private Set<String> types;
+ private Set<String> supersedes;
+ private boolean stopExisting;
@Activate
public void activate(final Map<String, String> properties) {
@@ -94,12 +97,20 @@ public class ExternalUiModule implements UiModule {
this.name = properties.get(KEY_NAME);
this.icon = properties.get(KEY_ICON);
this.url = properties.get(KEY_URL);
+
this.types = MutableSet.of(MODULE_TYPE);
-
final String userTypes = properties.get(KEY_TYPES);
if (userTypes != null) {
this.types.addAll(Arrays.asList(userTypes.split(",")));
}
+
+ this.supersedes = MutableSet.of(MODULE_TYPE);
+ final String userSupersedes = properties.get(KEY_SUPERSEDES);
+ if (userSupersedes != null) {
+ this.supersedes.addAll(Arrays.asList(userSupersedes.split(",")));
+ }
+
+ this.stopExisting = properties.get(KEY_STOP_EXISTING)!=null ? Boolean.parseBoolean(properties.get(KEY_STOP_EXISTING)) : true;
}
@Override
@@ -128,6 +139,16 @@ public class ExternalUiModule implements UiModule {
}
@Override
+ public Set<String> getSupersedesBundles() {
+ return supersedes;
+ }
+
+ @Override
+ public boolean getStopExisting() {
+ return stopExisting;
+ }
+
+ @Override
public String getPath() {
return this.url;
}
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/4d606727/modularity-server/external-modules/src/main/java/org/apache/brooklyn/ui/modularity/enricher/BrooklynExternalUiModuleEnricher.java
----------------------------------------------------------------------
diff --git a/modularity-server/external-modules/src/main/java/org/apache/brooklyn/ui/modularity/enricher/BrooklynExternalUiModuleEnricher.java b/modularity-server/external-modules/src/main/java/org/apache/brooklyn/ui/modularity/enricher/BrooklynExternalUiModuleEnricher.java
index 3d6fac2..9f19f37 100644
--- a/modularity-server/external-modules/src/main/java/org/apache/brooklyn/ui/modularity/enricher/BrooklynExternalUiModuleEnricher.java
+++ b/modularity-server/external-modules/src/main/java/org/apache/brooklyn/ui/modularity/enricher/BrooklynExternalUiModuleEnricher.java
@@ -18,6 +18,7 @@
*/
package org.apache.brooklyn.ui.modularity.enricher;
+import java.util.Collection;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
@@ -32,6 +33,8 @@ import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.core.enricher.AbstractEnricher;
import org.apache.brooklyn.core.entity.Attributes;
+import org.apache.brooklyn.ui.modularity.module.api.UiModule;
+import org.apache.brooklyn.ui.modularity.module.api.UiModuleAction;
import org.apache.brooklyn.util.collections.MutableSet;
import org.apache.brooklyn.util.core.flags.TypeCoercions;
import org.osgi.framework.Bundle;
@@ -41,11 +44,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
-import org.apache.brooklyn.ui.modularity.module.api.UiModule;
-import org.apache.brooklyn.ui.modularity.module.api.UiModuleAction;
-
public class BrooklynExternalUiModuleEnricher extends AbstractEnricher {
private static final Logger LOG = LoggerFactory.getLogger(BrooklynExternalUiModuleEnricher.class);
private static final Dictionary<String, ?> EMPTY_DICTIONARY = new Hashtable<>();
@@ -57,6 +58,8 @@ public class BrooklynExternalUiModuleEnricher extends AbstractEnricher {
public static final ConfigKey<String> MODULE_SLUG = ConfigKeys.newStringConfigKey(
"external.ui.module.slug", "Module slug");
public static final ConfigKey<List<String>> MODULE_TYPE = ConfigKeys.newConfigKey(new TypeToken<List<String>>() {}, "external.ui.module.types", "Module types", ImmutableList.<String>of());
+ public static final ConfigKey<List<String>> SUPERSEDES_BUNDLES = ConfigKeys.newConfigKey(new TypeToken<List<String>>() {}, "external.ui.module.supersedes", "Bundles supersedes", ImmutableList.<String>of());
+ public static final ConfigKey<Boolean> STOP_EXISTING = ConfigKeys.newConfigKey(new TypeToken<Boolean>() {}, "external.ui.module.stopExisting", "Module stops existing", true);
public static final ConfigKey<Sensor<?>> MODULE_URL_SENSOR_TO_MONITOR =
(ConfigKey) ConfigKeys.newConfigKey(Sensor.class, "external.ui.module.url.sensor", "Module URL Sensor", Attributes.MAIN_URI);
@@ -97,7 +100,7 @@ public class BrooklynExternalUiModuleEnricher extends AbstractEnricher {
LOG.debug("Could not register external UI module [{} :: {}] ... Could not load bundle context", getId(), getConfig(MODULE_NAME));
} else {
final Set<String> types = MutableSet.<String>builder().add("external-ui-module").addAll(getConfig(MODULE_TYPE)).build();
- final UiModule uiModule = newUiModule(getId(), getConfig(MODULE_NAME), getConfig(MODULE_SLUG), types, url, getConfig(MODULE_ICON));
+ final UiModule uiModule = newUiModule(getId(), getConfig(MODULE_NAME), getConfig(MODULE_SLUG), types, url, getConfig(MODULE_ICON), getConfig(SUPERSEDES_BUNDLES), getConfig(STOP_EXISTING));
registration = bundle.getBundleContext().registerService(
UiModule.class, uiModule, EMPTY_DICTIONARY);
LOG.debug("Registered external UI module [{} :: {}]", getId(), getConfig(MODULE_NAME));
@@ -119,7 +122,7 @@ public class BrooklynExternalUiModuleEnricher extends AbstractEnricher {
}
}
- private UiModule newUiModule(final String id, final String name, final String slug, final Set<String> types, final String url, final String icon) {
+ private UiModule newUiModule(final String id, final String name, final String slug, final Set<String> types, final String url, final String icon, final Collection<String> supersedes, final boolean stopExisting) {
return new UiModule() {
@Override
public String getId() {
@@ -155,6 +158,16 @@ public class BrooklynExternalUiModuleEnricher extends AbstractEnricher {
public List<UiModuleAction> getActions() {
return ImmutableList.of();
}
+
+ @Override
+ public Set<String> getSupersedesBundles() {
+ return ImmutableSet.copyOf(supersedes);
+ }
+
+ @Override
+ public boolean getStopExisting() {
+ return stopExisting;
+ }
};
}
}
[12/12] brooklyn-ui git commit: This closes #60
Posted by he...@apache.org.
This closes #60
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/commit/57e9726d
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/tree/57e9726d
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/diff/57e9726d
Branch: refs/heads/master
Commit: 57e9726d71824932a290b3688107af5e6d123851
Parents: f85263b 4d60672
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Aug 20 10:39:00 2018 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Aug 20 10:39:00 2018 +0100
----------------------------------------------------------------------
modularity-server/README.md | 23 +++
.../ui/modularity/ExternalUiModule.java | 29 +++-
.../BrooklynExternalUiModuleEnricher.java | 23 ++-
modularity-server/module-api/pom.xml | 12 ++
.../ui/modularity/module/api/UiModule.java | 13 +-
.../modularity/module/api/UiModuleListener.java | 156 ++++++++++++++++++-
.../module/api/internal/UiModuleImpl.java | 39 ++++-
.../home/app/views/main/main.controller.js | 4 +-
.../src/main/resources/ui-module/config.yaml | 20 +++
ui-modules/home/src/main/webapp/WEB-INF/web.xml | 4 +
.../module-links-drawer.template.html | 4 +-
.../module-links-navbar.template.html | 3 +-
ui-modules/utils/module-links/module-links.js | 4 +-
13 files changed, 306 insertions(+), 28 deletions(-)
----------------------------------------------------------------------
[11/12] brooklyn-ui git commit: This closes #59
Posted by he...@apache.org.
This closes #59
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/commit/f85263b8
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/tree/f85263b8
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/diff/f85263b8
Branch: refs/heads/master
Commit: f85263b8a3db6645a37d47f1f970b15cd2675852
Parents: 0f1c870 2945d14
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Aug 20 10:38:57 2018 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Aug 20 10:38:57 2018 +0100
----------------------------------------------------------------------
README.md | 2 +-
docs/customizations.md | 40 ++++++++++++
docs/vanilla-with-custom-widget.bom | 43 ++++++++++++
.../suggestion-dropdown.html | 67 +++++++++++++++++++
.../custom-config-widget/suggestion-dropdown.js | 58 ++++++++++++++++
.../suggestion-dropdown.less | 68 +++++++++++++++++++
.../providers/blueprint-service.provider.js | 16 +++++
.../spec-editor/spec-editor.directive.js | 69 ++++++++++++++++++--
.../app/components/spec-editor/spec-editor.less | 40 ++++++++++--
.../spec-editor/spec-editor.template.html | 56 +++++++++-------
ui-modules/blueprint-composer/app/index.js | 6 +-
ui-modules/blueprint-composer/app/index.less | 1 +
12 files changed, 431 insertions(+), 35 deletions(-)
----------------------------------------------------------------------
[04/12] brooklyn-ui git commit: show a nice dropdown for the values
supplied, including supporting description
Posted by he...@apache.org.
show a nice dropdown for the values supplied, including supporting description
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/commit/ee98bd40
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/tree/ee98bd40
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/diff/ee98bd40
Branch: refs/heads/master
Commit: ee98bd40f5c68b97b06343b061b674fad4332b22
Parents: 19de59d
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Aug 7 12:20:06 2018 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Aug 7 12:20:06 2018 +0100
----------------------------------------------------------------------
.../suggestion-dropdown.html | 29 ++++++++++++---
.../custom-config-widget/suggestion-dropdown.js | 15 +++++++-
.../suggestion-dropdown.less | 38 ++++++++++++++++++--
.../spec-editor/spec-editor.directive.js | 10 +-----
4 files changed, 75 insertions(+), 17 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/ee98bd40/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.html
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.html b/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.html
index 4ca05cc..82ecfea 100644
--- a/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.html
+++ b/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.html
@@ -36,13 +36,32 @@
</span>
<div class="control-value" ng-class="{ 'inline-control': item.widgetMode==='boolean', 'unset': !defined(config[item.name]), 'has-default': defined(item.defaultValue) && item.defaultValue!=null }">
- <div class="hide-when-collapsed">
+ <div class="hide-when-collapsed extra-label" ng-if="params['label-expanded']">
{{ params['label-expanded'] || "" }}
</div>
- <div>
- <span class="hide-when-expanded">{{ params['label-collapsed'] || "" }}</span>
- {{ config[item.name] }}
+ <div class="config-flex-row">
+ <span class="hide-when-expanded inline-label extra-label" ng-if="params['label-collapsed']">{{ params['label-collapsed'] || "" }}</span>
+ <div class="input-group">
+ <textarea ng-model="config[item.name]" class="form-control" name="{{item.name}}" id="{{item.name}}" auto-grow
+ placeholder="{{defined(config[item.name]) ? null : item.defaultValue=='' || item.defaultValue==null ? '(empty)' : item.defaultValue}}"
+ ng-focus="recordFocus(item)" on-enter="advanceOutToFormGroupInPanel"
+ uib-typeahead="suggestion.value for suggestion in getSuggestions() | filter:{value:$viewValue}"
+ typeahead-min-length=0
+ typeahead-template-url="SuggestionTemplate.html"></textarea>
+ <span class="input-group-btn dsl-wizard-button" ng-if="isDslWizardButtonAllowed(item.name)">
+ <a ui-sref="main.graphical.edit.dsl({entityId: model._id, for: item.name})" class="btn btn-default" title="Open in DSL editor"><i class="fa fa-bolt"></i></a>
+ </span>
+ </div>
</div>
</div>
-</div>
\ No newline at end of file
+</div>
+
+<!--TYPEAHEAD TEMPLATE :: START-->
+<script type="text/ng-template" id="SuggestionTemplate.html">
+ <div class="dropdown-item">
+ <span class="dropdown-item-value" ng-bind-html="match.model.value | uibTypeaheadHighlight:query"></span>
+ <p class="dropdown-item-description" ng-if="match.model.description">{{ match.model.description }}</p>
+ </div>
+</script>
+<!--TYPEAHEAD TEMPLATE :: END-->
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/ee98bd40/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.js
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.js b/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.js
index 7c23092..e64e3e8 100644
--- a/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.js
+++ b/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.js
@@ -40,7 +40,20 @@ export function suggestionDropdownDirective($rootScope) {
function link(scope) {
scope.$parent.copyScopeForCustomConfigWidget(scope);
- console.log("params for widget for "+scope.item.name, scope.params);
+
+ scope.getSuggestions = () => {
+ var result = [];
+ if (scope.params['suggestion-values']) {
+ scope.params['suggestion-values'].forEach( (v) => {
+ if (v["value"]) {
+ result.push(v);
+ } else {
+ result.push({value: v});
+ }
+ });
+ return result;
+ }
+ };
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/ee98bd40/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.less
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.less b/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.less
index c080a1b..91762e7 100644
--- a/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.less
+++ b/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.less
@@ -24,7 +24,41 @@ suggestion-dropdown {
.control-value {
// for widgets that are text, this aligns it with the label when collapsed and gives nice spacing when expanded.
// (for widgets that are dropdowns etc this should be omitted)
- padding-top: 2px;
+// padding-top: 2px;
+ }
+ .extra-label {
+ // this seems to work best here (instead of padding above) when combining a label with a textarea control
+ padding-top: 4px;
+ }
+ .inline-label {
+ margin-right: 5px;
+ white-space: nowrap;
+ }
+ spec-editor .spec-configuration .form-group & .control-value .config-flex-row {
+ flex-flow: nowrap;
+ }
+ .form-group:not(:focus-within):not(:focus) & .control-value .dropdown-menu {
+ // hide the dropdown menu when collapsed
+ display: none;
+ }
+ .dropdown-menu li a {
+ // quite a lot of padding in normal dropdown, in the ul and in the a
+ padding: 0;
+ }
+
+ .dropdown-item {
+ display: flex;
+ flex-flow: row wrap;
+ }
+ .dropdown-item-value {
+ }
+ .dropdown-item-description {
+ flex: 1 1 auto;
+ text-align: right;
+ font-style: italic;
+ font-size: 80%;
+ flex: 1 1 auto;
+ margin-bottom: 0;
+ margin-left: 6px;
}
-
}
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/ee98bd40/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js b/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js
index 17ab03a..b48366a 100644
--- a/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js
+++ b/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js
@@ -106,10 +106,7 @@ export function specEditorDirective($rootScope, $templateCache, $injector, $sani
codeModeActive: {},
codeModeForced: {},
codeModeError: {},
- customConfigWidgetMetadata: {
- "defaultDisplayName": { enabled: true, widget: "known-widget-missing" },
- "download.url": { enabled: true, widget: "suggestion-dropdown" },
- },
+ customConfigWidgetMetadata: {},
},
location: {
open: false
@@ -612,18 +609,13 @@ export function specEditorDirective($rootScope, $templateCache, $injector, $sani
}
function loadCustomConfigWidgetMetadata(model) {
- console.log("misc data", model.miscData, scope.model.miscData.get('ui-composer-hints'));
var customConfigWidgets = (scope.model.miscData.get('ui-composer-hints') || {})['config-widgets'] || [];
- console.log("customs", customConfigWidgets);
customConfigWidgets.forEach( (wd) => {
- console.log("looking at", wd);
var keys = wd.keys || [ wd.key ];
keys.forEach( (k) => {
- console.log("setting key", k);
scope.state.config.customConfigWidgetMetadata[k] = angular.extend({ enabled: true }, scope.state.config.customConfigWidgetMetadata[k], wd);
});
});
- console.log("custom config", scope.state.config.customConfigWidgetMetadata);
}
/* config state for each item is stored in multiple places:
[02/12] brooklyn-ui git commit: initial JS poc of custom config widget
Posted by he...@apache.org.
initial JS poc of custom config widget
all the hard angular stuff working, but hard-coded. now just need to wire it to real tags.
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/commit/29ba70e1
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/tree/29ba70e1
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/diff/29ba70e1
Branch: refs/heads/master
Commit: 29ba70e1936367a4e226823add0a4272252b0922
Parents: f9d239e
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Aug 6 22:59:11 2018 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Aug 6 22:59:11 2018 +0100
----------------------------------------------------------------------
docs/customizations.md | 8 +++
.../suggestion-dropdown.html | 48 +++++++++++++++
.../custom-config-widget/suggestion-dropdown.js | 44 ++++++++++++++
.../suggestion-dropdown.less | 30 +++++++++
.../spec-editor/spec-editor.directive.js | 64 +++++++++++++++++++-
.../app/components/spec-editor/spec-editor.less | 26 +++++++-
.../spec-editor/spec-editor.template.html | 22 +++++--
ui-modules/blueprint-composer/app/index.js | 6 +-
ui-modules/blueprint-composer/app/index.less | 1 +
9 files changed, 238 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29ba70e1/docs/customizations.md
----------------------------------------------------------------------
diff --git a/docs/customizations.md b/docs/customizations.md
index 4458a88..9912317 100644
--- a/docs/customizations.md
+++ b/docs/customizations.md
@@ -11,3 +11,11 @@ There are a number of points where UI default choices can be overridden:
items for the palette can come from Brooklyn and/or other sources, with other sources converted to "virtual items" that
can extend existing Brooklyn items
+* Composer - Custom Config Widgets: special widgets to use for config keys can be specified in a registered type's
+ definition as a map tag, for example for the demo widget `suggestion-dropout` included we might have:
+ '{ ui-composer-hints: { config-widgets: [ { key: start.timeout, suggestion-values: [ 30s, 2m, 5m, 30m, 2h ],
+ widget: suggestion-dropdown, label-collapsed: fail after, label-expanded: Fail if not successful within } ] } }`;
+ widgets should be registered as angular directives using the standard naming conventions (e.g. suggestionDropdownDirective),
+ as done for that directive in app/index.js and app/index.less.
+
+
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29ba70e1/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.html
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.html b/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.html
new file mode 100644
index 0000000..c511dfe
--- /dev/null
+++ b/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.html
@@ -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.
+-->
+<div class="custom-config-widget suggestion-dropdown config-flex-row">
+ <label class="control-label" for="{{item.name}}">
+ <span class="label-spec-configuration">{{item.label || item.name}}</span>
+ <span class="info-spec-configuration">
+ <i class="fa fa-fw fa-info-circle" popover-trigger="'mouseenter'"
+ popover-title="{{item.label || item.name}}"
+ uib-popover-template="'ConfigInfoTemplate.html'"
+ popover-class="spec-editor-popover" popover-placement="top-left" popover-append-to-body="true"></i>
+ </span>
+ </label>
+
+ <span class="label-rhs-buttons">
+ <span class="spacer"> </span>
+ <span class="custom-widget-enable-button custom-widget-active">
+ <i class="fa fa-fw fa-sun-o" ng-click="toggleCustomConfigWidgetMode(item, 'disabled')" aria-hidden="true" title="{{getCustomConfigWidgetModeTitle(item)}} [{{item.name}}]"></i>
+ <span class="sr-only">{{getCustomConfigWidgetModeTitle(item)}} [{{item.name}}]</span>
+ </span>
+ </span>
+
+ <div class="control-value" ng-class="{ 'inline-control': item.widgetMode==='boolean', 'unset': !defined(config[item.name]), 'has-default': defined(item.defaultValue) && item.defaultValue!=null }">
+ <div class="hide-when-collapsed">
+ <a ng-click="test()">Extra information</a>
+ </div>
+ <div>
+ <span class="hide-when-expanded">Custom widget: </span>
+ {{ config[item.name] }}
+ </div>
+ </div>
+
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29ba70e1/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.js
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.js b/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.js
new file mode 100644
index 0000000..d36c801
--- /dev/null
+++ b/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.js
@@ -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.
+ */
+
+import angular from 'angular';
+import template from './suggestion-dropdown.html';
+
+const MODULE_NAME = 'brooklyn.components.custom-config-widget.suggestion-dropdown';
+
+angular.module(MODULE_NAME, [])
+ .directive('suggestionDropdown', ['$rootScope', suggestionDropdownDirective]);
+
+export default MODULE_NAME;
+
+export function suggestionDropdownDirective($rootScope) {
+ return {
+ restrict: 'E',
+ scope: {
+ item: '='
+ },
+ template: template,
+ link: link,
+ };
+
+ function link(scope) {
+ scope.$parent.copyScopeForCustomConfigWidget(scope);
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29ba70e1/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.less
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.less b/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.less
new file mode 100644
index 0000000..c080a1b
--- /dev/null
+++ b/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.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.
+ */
+
+suggestion-dropdown {
+
+ width: 100%;
+
+ .control-value {
+ // for widgets that are text, this aligns it with the label when collapsed and gives nice spacing when expanded.
+ // (for widgets that are dropdowns etc this should be omitted)
+ padding-top: 2px;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29ba70e1/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js b/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js
index 7a581b7..a0eeba8 100644
--- a/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js
+++ b/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js
@@ -33,7 +33,7 @@ const ANY_MEMBERSPEC_REGEX = /(^.*[m,M]ember[s,S]pec$)/;
const REPLACED_DSL_ENTITYSPEC = '___brooklyn:entitySpec';
angular.module(MODULE_NAME, [onEnter, autoGrow, blurOnEnter, brooklynDslEditor, brooklynDslViewer])
- .directive('specEditor', ['$rootScope', '$filter', '$log', '$sce', '$timeout', '$document', 'blueprintService', specEditorDirective])
+ .directive('specEditor', ['$rootScope', '$templateCache', '$injector', '$sanitize', '$filter', '$log', '$sce', '$timeout', '$document', 'blueprintService', specEditorDirective])
.filter('specEditorConfig', specEditorConfigFilter)
.filter('specEditorType', specEditorTypeFilter);
@@ -70,7 +70,7 @@ export const CONFIG_FILTERS = [
}
];
-export function specEditorDirective($rootScope, $filter, $log, $sce, $timeout, $document, blueprintService) {
+export function specEditorDirective($rootScope, $templateCache, $injector, $sanitize, $filter, $log, $sce, $timeout, $document, blueprintService) {
return {
restrict: 'E',
scope: {
@@ -106,6 +106,10 @@ export function specEditorDirective($rootScope, $filter, $log, $sce, $timeout, $
codeModeActive: {},
codeModeForced: {},
codeModeError: {},
+ customWidget: {
+ "defaultDisplayName": { mode: "full", widget: "known-widget-missing" },
+ "download.url": { mode: "full", widget: "suggestion-dropdown" },
+ },
},
location: {
open: false
@@ -514,7 +518,7 @@ export function specEditorDirective($rootScope, $filter, $log, $sce, $timeout, $
// local config changed, make sure model is updated too
setModelFromLocalConfig();
}
- }
+ };
scope.getJsonModeTitle = (itemName) => {
if (!scope.state.config.codeModeActive[itemName]) {
return "Treat this value as a JSON-encoded object ["+itemName+"]";
@@ -525,6 +529,60 @@ export function specEditorDirective($rootScope, $filter, $log, $sce, $timeout, $
return "Edit in simple mode, unwrapping JSON if possible ["+itemName+"]";
}
}
+ scope.getCustomConfigWidgetMode = (item) => {
+ var mode = (scope.state.config.customWidget[item.name] || {})["mode"] || null;
+ if (mode) {
+ if ((scope.state.config.customWidget[item.name] || {})["error"]) return null;
+ }
+ return mode;
+ } ;
+ scope.toggleCustomConfigWidgetMode = (item, newval) => {
+ if (!scope.state.config.customWidget[item.name]) {
+ $log.error('Custom widget mode should not be toggled when not available: '+item.name);
+ return null;
+ }
+ if (newval) scope.state.config.customWidget[item.name].mode = newval;
+ else {
+ if (scope.state.config.customWidget[item.name].mode === "disabled") {
+ // TODO not always full
+ scope.state.config.customWidget[item.name].mode = "full"
+ } else {
+ scope.state.config.customWidget[item.name].mode = "full"
+ }
+ }
+ }
+ scope.getCustomConfigWidgetModeTitle = (item) => {
+ if (!scope.state.config.customWidget[item.name]) {
+ // shouldn't be visible
+ return "(custom widget not available)";
+ }
+ if (scope.state.config.customWidget[item.name].mode === "disabled") return "Enable custom widget";
+ else return "Disable custom widget";
+ };
+ scope.copyScopeForCustomConfigWidget = (descendantScope) => {
+ descendantScope.toggleCustomConfigWidgetMode = scope.toggleCustomConfigWidgetMode;
+ descendantScope.getCustomConfigWidgetModeTitle = scope.getCustomConfigWidgetModeTitle;
+ descendantScope.defined = scope.defined;
+ descendantScope.config = scope.config;
+ descendantScope.state = scope.state;
+ descendantScope.copyScopeForCustomConfigWidget = scope.copyScopeForCustomConfigWidget;
+ };
+ scope.getCustomConfigWidgetTemplate = (item) => {
+ var widgetName = $sanitize(scope.state.config.customWidget[item.name].widget);
+ var templateName = 'custom-config-widget-'+widgetName;
+ if (!$templateCache.get(templateName)) {
+ var widgetDirective = widgetName.replace(/(-[a-z])/g, function($1){return $1[1].toUpperCase();})+'Directive';
+ if ($injector.has(widgetDirective)) {
+ $templateCache.put(templateName, '<'+widgetName+' item="item">foo</'+widgetName+'>');
+ } else {
+ $log.error('Missing directive '+widgetDirective+' for custom widget for '+item.name+'; falling back to default widget');
+ scope.state.config.customWidget[item.name].error = "Missing directive";
+ templateName = "error-" + templateName;
+ $templateCache.put(templateName, '<i>Widget '+widgetName+' missing</i>');
+ }
+ }
+ return templateName;
+ };
scope.isDsl = (key, index) => {
let val = scope.model.config.get(key);
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29ba70e1/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.less
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.less b/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.less
index 1c14c92..233d937 100644
--- a/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.less
+++ b/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.less
@@ -272,12 +272,23 @@ spec-editor {
margin-right: 0.5em;
.remove-affordance();
}
+ span.rhs-buttons-subspan {
+ display: flex;
+ }
.json-config i {
margin-top: 2px; //nudge down to make aligned
}
- .dsl-open-wizard-from-toolbar, .dsl-manual-override-editor, .json-config {
+ .dsl-open-wizard-from-toolbar, .dsl-manual-override-editor, .json-config, .custom-widget-enable-button {
.toolbar-button-affordance()
}
+ .custom-widget-enable-button.custom-widget-active {
+ i {
+ color: @brand-primary;
+ }
+ &:hover i {
+ color: @gray-light;
+ }
+ }
.dsl-manual-override-editor.dsl-viewer-manual-override,
.json-config.code-mode-active {
i {
@@ -327,8 +338,11 @@ spec-editor {
}
}
.form-group {
- display: flex;
- flex-flow: row wrap;
+ &, .config-flex-row, .custom-widget-full {
+ display: flex;
+ flex-flow: row wrap;
+ width: 100%;
+ }
.control-label {
flex: 0 0 auto;
order: 10;
@@ -406,6 +420,9 @@ spec-editor {
}
}
&:not(:focus-within):not(:focus) {
+ .hide-when-collapsed {
+ display: none;
+ }
input {
// the RHS is square if DSL button hidden; simplest fix is to make LHS square too
border-radius: 0;
@@ -426,6 +443,9 @@ spec-editor {
}
}
.form-group:focus, .form-group:focus-within {
+ .hide-when-expanded {
+ display: none;
+ }
.control-value:not(.inline-control) {
flex-basis: 100%;
}
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29ba70e1/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.template.html
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.template.html b/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.template.html
index b305651..cc3e11e 100644
--- a/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.template.html
+++ b/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.template.html
@@ -131,12 +131,20 @@
<form name="formSpecConfig" novalidate class="lightweight">
<div ng-repeat="item in (filteredItems = (model.miscData.get('config') | specEditorConfig:state.config.filter.values:model.config | filter:{name:state.config.search} | orderBy:+priority)) track by item.name ">
- <div class="form-group" ng-class="{'has-error': (model.issues | filter:{ref: item.name}:true).length > 0, 'used': config[item.name] !== undefined}" ng-switch="getConfigWidgetMode(item)" tabindex="1"
+ <div class="form-group" ng-class="{'has-error': (model.issues | filter:{ref: item.name}:true).length > 0, 'used': config[item.name] !== undefined}"
+ ng-switch="getConfigWidgetMode(item)"
+ tabindex="1"
auto-focus="state.config.focus === item.name"
auto-focus-listen-to-window="true"
auto-focus-not-if-within="true"
ng-focus="recordFocus(item)"
on-enter="advanceControlInFormGroup">
+ <div ng-if="getCustomConfigWidgetMode(item) === 'full'" class="custom-widget-full">
+ <ng-include src="getCustomConfigWidgetTemplate(item)" class="custom-widget-full"/>
+ </div>
+
+ <!-- have to hide it; excluding it conditionally via if doesn't play nice with switch -->
+ <div ng-show="getCustomConfigWidgetMode(item) !== 'full'" class="config-flex-row">
<label class="control-label" for="{{item.name}}">
<span class="label-spec-configuration">{{item.label || item.name}}</span>
<span class="info-spec-configuration">
@@ -149,11 +157,15 @@
<span class="label-rhs-buttons">
<span class="spacer"> </span>
+ <span class="custom-widget-enable-button" ng-if="getCustomConfigWidgetMode(item) !== null">
+ <i class="fa fa-fw fa-sun-o" ng-click="toggleCustomConfigWidgetMode(item)" aria-hidden="true" title="{{getCustomConfigWidgetModeTitle(item)}} [{{item.name}}]"></i>
+ <span class="sr-only">{{getCustomConfigWidgetModeTitle(item)}} [{{item.name}}]</span>
+ </span>
<span class="json-config" ng-class="{'code-mode-active': state.config.codeModeActive[item.name], 'code-mode-forced': state.config.codeModeForced[item.name]}" ng-if="isCodeModeAvailable(item)">
- <i class="fa fa-fw fa-code" ng-click="codeModeClick(item)" aria-hidden="true" title="{{getJsonModeTitle(item.name)}}"></i>
- <span class="sr-only">{{getJsonModeTitle(item.name)}}</span>
+ <i class="fa fa-fw fa-code" ng-click="codeModeClick(item)" aria-hidden="true" title="{{getJsonModeTitle(item.name)}} [{{item.name}}]"></i>
+ <span class="sr-only">{{getJsonModeTitle(item.name)}} [{{item.name}}]</span>
</span>
- <span ng-if="isDsl(item.name)">
+ <span ng-if="isDsl(item.name)" class="rhs-buttons-subspan">
<span class="dsl-open-wizard-from-toolbar" ng-if="!state.config.dslViewerManualOverride[item.name]">
<i class="fa fa-fw fa-bolt" ui-sref="main.graphical.edit.dsl({entityId: model._id, for: item.name})" aria-hidden="true" title="Open in DSL editor [{{item.name}}]"></i>
<span class="sr-only">Open in DSL editor [{{item.name}}]</span>
@@ -309,6 +321,8 @@
</div>
<small ng-repeat="issue in model.issues | filter:{ref: item.name}:true" class="help-block issue" ng-bind-html="issue.message"></small>
+ </div>
+
</div>
</div>
</form>
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29ba70e1/ui-modules/blueprint-composer/app/index.js
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/index.js b/ui-modules/blueprint-composer/app/index.js
index f7a55b2..a970dc2 100755
--- a/ui-modules/blueprint-composer/app/index.js
+++ b/ui-modules/blueprint-composer/app/index.js
@@ -48,6 +48,7 @@ import {
catalogSelectorSortFilter
} from "components/catalog-selector/catalog-selector.directive";
import customActionDirective from "./components/custom-action/custom-action.directive";
+import customConfigSuggestionDropdown from "components/custom-config-widget/suggestion-dropdown";
import {onErrorDirective} from "components/catalog-selector/on-error.directive";
import {breadcrumbsDirective} from "components/breacrumbs/breadcrumbs.directive";
import {recursionHelperFactory} from "components/factories/recursion-helper.factory";
@@ -71,7 +72,10 @@ import {graphicalEditDslState, dslParamLabelFilter} from "views/main/graphical/e
import bottomSheet from "brooklyn-ui-utils/bottom-sheet/bottom-sheet";
import stackViewer from 'angular-java-stack-viewer';
-angular.module('app', [ngAnimate, ngResource, ngCookies, ngClipboard, uiRouter, 'ui.router.state.events', brCore, brServerStatus, brAutoFocus, brIconGenerator, brInterstitialSpinner, brooklynModuleLinks, brooklynUserManagement, brYamlEditor, brUtils, brSpecEditor, brooklynCatalogSaver, brooklynApi, bottomSheet, stackViewer, brDragndrop, customActionDirective, paletteApiProvider])
+angular.module('app', [ngAnimate, ngResource, ngCookies, ngClipboard, uiRouter, 'ui.router.state.events', brCore,
+ brServerStatus, brAutoFocus, brIconGenerator, brInterstitialSpinner, brooklynModuleLinks, brooklynUserManagement,
+ brYamlEditor, brUtils, brSpecEditor, brooklynCatalogSaver, brooklynApi, bottomSheet, stackViewer, brDragndrop,
+ customActionDirective, customConfigSuggestionDropdown, paletteApiProvider])
.directive('designer', ['$log', '$state', '$q', 'iconGenerator', 'catalogApi', 'blueprintService', 'brSnackbar', 'paletteDragAndDropService', designerDirective])
.directive('onError', onErrorDirective)
.directive('catalogSelector', catalogSelectorDirective)
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/29ba70e1/ui-modules/blueprint-composer/app/index.less
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/index.less b/ui-modules/blueprint-composer/app/index.less
index 5baf074..1562b40 100644
--- a/ui-modules/blueprint-composer/app/index.less
+++ b/ui-modules/blueprint-composer/app/index.less
@@ -31,6 +31,7 @@
@import "components/spec-editor/spec-editor";
@import "components/catalog-selector/catalog-selector";
@import "components/breacrumbs/breadcrumbs";
+@import "components/custom-config-widget/suggestion-dropdown";
@import "components/blueprint-data-manager/blueprint-data-manager.style.less";
@import "components/catalog-saver/catalog-saver.less";
@import "components/dsl-editor/dsl-editor";
[07/12] brooklyn-ui git commit: make Home a Brooklyn UI module
Posted by he...@apache.org.
make Home a Brooklyn UI module
previously it was just a WAR, not including it registry, which makes it hard for downstream projects to change
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/commit/82d37c47
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/tree/82d37c47
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/diff/82d37c47
Branch: refs/heads/master
Commit: 82d37c474b42b8dfc8afc2683d7723b7f201e1f7
Parents: 5d64b30
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Aug 9 00:20:37 2018 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Aug 9 00:20:37 2018 +0100
----------------------------------------------------------------------
.../src/main/resources/ui-module/config.yaml | 20 ++++++++++++++++++++
ui-modules/home/src/main/webapp/WEB-INF/web.xml | 4 ++++
.../module-links-drawer.template.html | 4 ++--
.../module-links-navbar.template.html | 3 ++-
4 files changed, 28 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/82d37c47/ui-modules/home/src/main/resources/ui-module/config.yaml
----------------------------------------------------------------------
diff --git a/ui-modules/home/src/main/resources/ui-module/config.yaml b/ui-modules/home/src/main/resources/ui-module/config.yaml
new file mode 100644
index 0000000..5bc77a6
--- /dev/null
+++ b/ui-modules/home/src/main/resources/ui-module/config.yaml
@@ -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.
+name: Home
+slug: ${project.artifactId}
+icon: fa-home
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/82d37c47/ui-modules/home/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/ui-modules/home/src/main/webapp/WEB-INF/web.xml b/ui-modules/home/src/main/webapp/WEB-INF/web.xml
index 992d1f3..4fa41b8 100644
--- a/ui-modules/home/src/main/webapp/WEB-INF/web.xml
+++ b/ui-modules/home/src/main/webapp/WEB-INF/web.xml
@@ -28,6 +28,10 @@
<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>
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/82d37c47/ui-modules/utils/module-links/module-links-drawer.template.html
----------------------------------------------------------------------
diff --git a/ui-modules/utils/module-links/module-links-drawer.template.html b/ui-modules/utils/module-links/module-links-drawer.template.html
index 6327b27..f547210 100644
--- a/ui-modules/utils/module-links/module-links-drawer.template.html
+++ b/ui-modules/utils/module-links/module-links-drawer.template.html
@@ -18,7 +18,7 @@
-->
<div class="ui-module-nav-drawer-container">
<div ng-repeat="module in modules track by id" ng-if="modules">
- <a ng-href="module.path">
+ <a ng-href="module.path" ng-if="module.path">
<i class="module-icon fa {{module.icon}}"></i>
<div class="module-name">{{module.name}}</div>
</a>
@@ -31,4 +31,4 @@
</li>
</ul>
</div>
-</div>
\ No newline at end of file
+</div>
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/82d37c47/ui-modules/utils/module-links/module-links-navbar.template.html
----------------------------------------------------------------------
diff --git a/ui-modules/utils/module-links/module-links-navbar.template.html b/ui-modules/utils/module-links/module-links-navbar.template.html
index 60e5f37..55b1019 100644
--- a/ui-modules/utils/module-links/module-links-navbar.template.html
+++ b/ui-modules/utils/module-links/module-links-navbar.template.html
@@ -33,12 +33,13 @@
</span>
</a>
<ul class="dropdown-menu ui-modules" uib-dropdown-menu>
+ <!-- put home first -->
<li role="menuitem"><a href="/" ng-class="{active: ctrl.isModuleActive('/')}">
<i class="ui-module-icon fa fa-fw fa-home"></i>
<span class="ui-module-name">Home</span>
</a></li>
<li role="menuitem" ng-repeat="module in ctrl.modules track by module.id">
- <a ng-href="{{module.path}}" class="module" ng-class="{active: ctrl.isModuleActive(module.path)}">
+ <a ng-href="{{module.path}}" class="module" ng-class="{active: ctrl.isModuleActive(module.path)}" ng-if="module.path">
<i class="ui-module-icon fa fa-fw {{module.icon}}"></i>
<span class="ui-module-name">{{module.name}}</span>
</a>
[08/12] brooklyn-ui git commit: fix filtering of ui modules for
display and add support for `library-ui-module`
Posted by he...@apache.org.
fix filtering of ui modules for display and add support for `library-ui-module`
previously there was a blank space for home as we filtered out the `<a>` but not the surrounding `<li>`;
now we filter the wrapping tag, and we also exclude for new `library` modules
(this allows ui modules to be registered for use in widgets etc but not included in the menu!)
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/commit/e6f7653a
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/tree/e6f7653a
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/diff/e6f7653a
Branch: refs/heads/master
Commit: e6f7653a15d44381ffe94160568728294a17749a
Parents: 4026a4b
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Aug 9 01:04:08 2018 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Aug 9 02:56:42 2018 +0100
----------------------------------------------------------------------
modularity-server/README.md | 2 +-
ui-modules/home/app/views/main/main.controller.js | 4 +---
ui-modules/utils/module-links/module-links-drawer.template.html | 4 ++--
ui-modules/utils/module-links/module-links-navbar.template.html | 4 ++--
ui-modules/utils/module-links/module-links.js | 4 ++--
5 files changed, 8 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/e6f7653a/modularity-server/README.md
----------------------------------------------------------------------
diff --git a/modularity-server/README.md b/modularity-server/README.md
index c228b72..f63b657 100644
--- a/modularity-server/README.md
+++ b/modularity-server/README.md
@@ -25,7 +25,7 @@ Optionally it can include:
* `actions` (not used currently, see code to understand)
* `stopExisting` (boolean, whether to stop lower-numbered bundles listening on the same
context-path declared in `web.xml`, defaulting to `true`)
-* `supersedesBundles` (a list of `bundle-regex:version-regex` of bundles that should be stopped
+* `supersedes` (a list of `bundle-regex:version-regex` of bundles that should be stopped
when this UI module is installed; this is used for downstream projects that may override UI modules
and wish to ensure their modules are used without relying on bundle install order (but often bundle install order is sufficient))
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/e6f7653a/ui-modules/home/app/views/main/main.controller.js
----------------------------------------------------------------------
diff --git a/ui-modules/home/app/views/main/main.controller.js b/ui-modules/home/app/views/main/main.controller.js
index b88c5e8..1c7360b 100644
--- a/ui-modules/home/app/views/main/main.controller.js
+++ b/ui-modules/home/app/views/main/main.controller.js
@@ -55,9 +55,7 @@ export function mainStateConfig($stateProvider) {
export function mainStateController($scope, $state, uiModules, catalogApps) {
$scope.$emit(HIDE_INTERSTITIAL_SPINNER_EVENT);
- this.uiModules = uiModules.filter((uiModule) => {
- return uiModule.types.indexOf('home-ui-module') > -1;
- });
+ this.uiModules = uiModules.filter( (uiModule) => uiModule.types.includes('home-ui-module') );
this.catalogApps = catalogApps;
this.pagination = {
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/e6f7653a/ui-modules/utils/module-links/module-links-drawer.template.html
----------------------------------------------------------------------
diff --git a/ui-modules/utils/module-links/module-links-drawer.template.html b/ui-modules/utils/module-links/module-links-drawer.template.html
index f547210..ec0fe7d 100644
--- a/ui-modules/utils/module-links/module-links-drawer.template.html
+++ b/ui-modules/utils/module-links/module-links-drawer.template.html
@@ -17,8 +17,8 @@
under the License.
-->
<div class="ui-module-nav-drawer-container">
- <div ng-repeat="module in modules track by id" ng-if="modules">
- <a ng-href="module.path" ng-if="module.path">
+ <div ng-repeat="module in modules track by id" ng-if="module.path && !module.type.includes('library-ui-module')">
+ <a ng-href="module.path">
<i class="module-icon fa {{module.icon}}"></i>
<div class="module-name">{{module.name}}</div>
</a>
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/e6f7653a/ui-modules/utils/module-links/module-links-navbar.template.html
----------------------------------------------------------------------
diff --git a/ui-modules/utils/module-links/module-links-navbar.template.html b/ui-modules/utils/module-links/module-links-navbar.template.html
index 55b1019..169f001 100644
--- a/ui-modules/utils/module-links/module-links-navbar.template.html
+++ b/ui-modules/utils/module-links/module-links-navbar.template.html
@@ -38,8 +38,8 @@
<i class="ui-module-icon fa fa-fw fa-home"></i>
<span class="ui-module-name">Home</span>
</a></li>
- <li role="menuitem" ng-repeat="module in ctrl.modules track by module.id">
- <a ng-href="{{module.path}}" class="module" ng-class="{active: ctrl.isModuleActive(module.path)}" ng-if="module.path">
+ <li role="menuitem" ng-repeat="module in ctrl.modules track by module.id" ng-if="module.path && !module.type.includes('library-ui-module')">
+ <a ng-href="{{module.path}}" class="module" ng-class="{active: ctrl.isModuleActive(module.path)}">
<i class="ui-module-icon fa fa-fw {{module.icon}}"></i>
<span class="ui-module-name">{{module.name}}</span>
</a>
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/e6f7653a/ui-modules/utils/module-links/module-links.js
----------------------------------------------------------------------
diff --git a/ui-modules/utils/module-links/module-links.js b/ui-modules/utils/module-links/module-links.js
index 94b239e..e983e79 100644
--- a/ui-modules/utils/module-links/module-links.js
+++ b/ui-modules/utils/module-links/module-links.js
@@ -53,8 +53,8 @@ export function moduleLinksMenuDirective($compile) {
function controller(brBrandInfo, brooklynUiModulesApi) {
this.modules = null;
this.isModuleActive = (path) => {
- if (path === '/') {
- return window.location.pathname === path;
+ if (path === '/' || path === '') {
+ return window.location.pathname === '/';
} else {
return window.location.pathname.startsWith(path);
}
[05/12] brooklyn-ui git commit: tidy of dropdown,
and also cleanup the "add config" dropdown
Posted by he...@apache.org.
tidy of dropdown, and also cleanup the "add config" dropdown
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/commit/6e030377
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/tree/6e030377
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/diff/6e030377
Branch: refs/heads/master
Commit: 6e030377cd5d0b32d585c7ffc597622c115f120f
Parents: ee98bd4
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Aug 7 16:31:51 2018 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Aug 7 16:36:40 2018 +0100
----------------------------------------------------------------------
docs/customizations.md | 12 ++++---
docs/vanilla-with-custom-widget.bom | 25 ++++++++++++++
.../custom-config-widget/suggestion-dropdown.js | 1 -
.../suggestion-dropdown.less | 12 ++++---
.../spec-editor/spec-editor.directive.js | 2 +-
.../app/components/spec-editor/spec-editor.less | 14 ++++++--
.../spec-editor/spec-editor.template.html | 34 +++++++++-----------
7 files changed, 67 insertions(+), 33 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/6e030377/docs/customizations.md
----------------------------------------------------------------------
diff --git a/docs/customizations.md b/docs/customizations.md
index 9912317..a27bc0e 100644
--- a/docs/customizations.md
+++ b/docs/customizations.md
@@ -12,10 +12,12 @@ There are a number of points where UI default choices can be overridden:
can extend existing Brooklyn items
* Composer - Custom Config Widgets: special widgets to use for config keys can be specified in a registered type's
- definition as a map tag, for example for the demo widget `suggestion-dropout` included we might have:
- '{ ui-composer-hints: { config-widgets: [ { key: start.timeout, suggestion-values: [ 30s, 2m, 5m, 30m, 2h ],
- widget: suggestion-dropdown, label-collapsed: fail after, label-expanded: Fail if not successful within } ] } }`;
- widgets should be registered as angular directives using the standard naming conventions (e.g. suggestionDropdownDirective),
- as done for that directive in app/index.js and app/index.less.
+ definition as a map tag, for example for the demo widget `suggestion-dropout` included we might have
+ '{ ui-composer-hints: { config-widgets: [ {
+ key: start.timeout, suggestion-values: [ 30s, 2m, 5m, 30m, 2h, { value: forever, description: 'No timeout' ],
+ widget: suggestion-dropdown, label-collapsed: fail after, label-expanded: Fail if not successful within } ] } }`
+ (as shown in the accompanying `vanillia-with-custom-widget.bom`);
+ widgets should be registered as angular directives using the standard Angular naming conventions
+ (e.g. suggestionDropdownDirective), as done for that directive in app/index.js and app/index.less.
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/6e030377/docs/vanilla-with-custom-widget.bom
----------------------------------------------------------------------
diff --git a/docs/vanilla-with-custom-widget.bom b/docs/vanilla-with-custom-widget.bom
new file mode 100644
index 0000000..313d3a6
--- /dev/null
+++ b/docs/vanilla-with-custom-widget.bom
@@ -0,0 +1,25 @@
+brooklyn.catalog:
+ id: vanilla-with-custom-widget
+ version: 1.0.0-SNAPSHOT
+ iconUrl: https://cdn.shopify.com/s/files/1/0709/1933/products/valilla_flower_1024x1024.png?v=1479432384
+ itemType: entity
+ tags:
+ - ui-composer-hints:
+ config-widgets:
+ - key: start.timeout
+ widget: suggestion-dropdown
+ suggestion-values:
+ - value: 30s
+ description: 30 seconds
+ - value: 2m
+ description: 2 minutes
+ - 5m
+ - 30m
+ - value: 2h
+ description: 2 hours
+ - value: forever
+ description: No timeout
+ label-collapsed: fail after
+ label-expanded: Fail if not successful within
+ item:
+ type: org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/6e030377/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.js
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.js b/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.js
index e64e3e8..3dfa860 100644
--- a/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.js
+++ b/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.js
@@ -40,7 +40,6 @@ export function suggestionDropdownDirective($rootScope) {
function link(scope) {
scope.$parent.copyScopeForCustomConfigWidget(scope);
-
scope.getSuggestions = () => {
var result = [];
if (scope.params['suggestion-values']) {
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/6e030377/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.less
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.less b/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.less
index 91762e7..fc2371e 100644
--- a/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.less
+++ b/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.less
@@ -41,24 +41,28 @@ suggestion-dropdown {
// hide the dropdown menu when collapsed
display: none;
}
+
.dropdown-menu li a {
// quite a lot of padding in normal dropdown, in the ul and in the a
padding: 0;
}
-
.dropdown-item {
display: flex;
flex-flow: row wrap;
+ width: 100%;
}
.dropdown-item-value {
+ flex: 1 0 auto;
}
.dropdown-item-description {
- flex: 1 1 auto;
+ flex: 10 1 auto;
text-align: right;
font-style: italic;
font-size: 80%;
- flex: 1 1 auto;
margin-bottom: 0;
- margin-left: 6px;
+ margin-left: 12px;
+ max-width: 70%;
+ margin-top: 2px;
+ line-height: 18px;
}
}
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/6e030377/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js b/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js
index b48366a..7a1ec92 100644
--- a/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js
+++ b/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js
@@ -303,7 +303,7 @@ export function specEditorDirective($rootScope, $templateCache, $injector, $sani
scope.state.config.add.open = false;
scope.state.config.focus = $item.name;
if ($item.isHidden) {
- scope.state.config.filter.values[ CONFIG_FILTERS[CONFIG_FILTERS.length - 1] ].id = true;
+ scope.state.config.filter.values.all = true;
}
};
scope.recordFocus = ($item)=> {
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/6e030377/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.less
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.less b/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.less
index da74f0f..29bb911 100644
--- a/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.less
+++ b/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.less
@@ -235,9 +235,6 @@ spec-editor {
}
}
- .spec-configuration-add {
- margin-bottom: 15px;
- }
.spec-configuration {
& > div {
margin-top: 30px;
@@ -771,6 +768,17 @@ spec-editor {
padding: 0.5em;
margin-top: -12px;
margin-bottom: 24px;
+ .dropdown-menu li a {
+ // quite a lot of padding in normal dropdown, in the ul and in the a
+ padding: 0;
+ }
+ .dropdown-item {
+ .config-name {
+ font-family: courier;
+ font-size: 95%;
+ margin-right: 1ex;
+ }
+ }
legend {
color: @gray;
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/6e030377/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.template.html
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.template.html b/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.template.html
index 740d295..8b466fe 100644
--- a/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.template.html
+++ b/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.template.html
@@ -79,13 +79,11 @@
</fieldset>
<fieldset uib-collapse="!state.config.add.open" class="spec-configuration-add">
- <legend>Add config key</legend>
-
<input auto-focus="state.config.add.open"
type="text"
autocomplete="off"
ng-model="state.config.add.value"
- placeholder="Add a new configuration key"
+ placeholder="Add a new configuration key or open existing"
class="form-control"
uib-typeahead="config.name for config in state.config.add.list | filter:{name:$viewValue}"
typeahead-template-url="ConfigItemTemplate.html"
@@ -99,14 +97,12 @@
<div ng-if="state.config.add.value.length > 0 && noResults" uib-dropdown uib-dropdown-toggle auto-close="disabled" is-open="true">
<ul class="dropdown-menu">
- <li><a ng-click="addConfigKey()">
- <div class="dropdown-item">
- <div class="details">
- <h4 class="dropdown-item-heading repo-name truncate">
- <span ng-bind-html="state.config.add.value | uibTypeaheadHighlight:state.config.add.value"></span>
- </h4>
- <p class="dropdown-item-subheading version truncate">Click to add the new config key</p>
- </div>
+ <!-- mimic real dropdown if nothing found -->
+ <li class="uib-typeahead-match"><a ng-click="addConfigKey()">
+ <div class="dropdown-item" ng-init="item = match.model">
+ <div class="dropdown-row">
+ <span ng-bind-html="state.config.add.value | uibTypeaheadHighlight:query" class="config-name"></span>
+ <i class="fa fa-fw fa-plus-square-o"></i>
</div>
</a></li>
</ul>
@@ -455,14 +451,14 @@
<!--TYPEAHEAD TEMPLATE :: START-->
<script type="text/ng-template" id="ConfigItemTemplate.html">
- <div class="dropdown-item">
- <div class="details">
- <h4 class="dropdown-item-heading repo-name truncate">
- <span ng-bind-html="match.model.label | uibTypeaheadHighlight:query"></span>
- <i class="fa fa-fw fa-asterisk" ng-if="match.model.constraints.required"></i>
- <i class="fa fa-fw fa-eye-slash" ng-if="match.model.isHidden"></i>
- </h4>
- <p class="dropdown-item-subheading version truncate">{{ match.model.description }}</p>
+ <div class="dropdown-item" ng-init="item = match.model">
+ <div class="dropdown-row">
+ <span ng-bind-html="match.model.name | uibTypeaheadHighlight:query" class="config-name"></span>
+ <i class="fa fa-fw fa-asterisk" ng-if="match.model.constraints.required"></i>
+ <i class="fa fa-fw fa-eye-slash" ng-if="match.model.isHidden"></i>
+ <!-- previously showed just the label; now show just the name as that's what is inserted.
+ ideally would show label and description as popover (reusing ConfigInfoTemplate), but due to bugs in popover
+ we can't easily get that to work. -->
</div>
</div>
</script>
[03/12] brooklyn-ui git commit: collect config-widget metadata from
ui-composer-hints tags on registered types
Posted by he...@apache.org.
collect config-widget metadata from ui-composer-hints tags on registered types
all that's left is to show the suggested dropdown values
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/commit/19de59de
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/tree/19de59de
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/diff/19de59de
Branch: refs/heads/master
Commit: 19de59de10894f8a3720c989d0e3be7fd68b260a
Parents: 29ba70e
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Aug 7 01:18:01 2018 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Aug 7 01:18:01 2018 +0100
----------------------------------------------------------------------
.../suggestion-dropdown.html | 6 +-
.../custom-config-widget/suggestion-dropdown.js | 4 +-
.../providers/blueprint-service.provider.js | 16 +++++
.../spec-editor/spec-editor.directive.js | 63 ++++++++++++--------
.../app/components/spec-editor/spec-editor.less | 2 +-
.../spec-editor/spec-editor.template.html | 6 +-
6 files changed, 63 insertions(+), 34 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/19de59de/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.html
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.html b/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.html
index c511dfe..4ca05cc 100644
--- a/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.html
+++ b/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.html
@@ -30,17 +30,17 @@
<span class="label-rhs-buttons">
<span class="spacer"> </span>
<span class="custom-widget-enable-button custom-widget-active">
- <i class="fa fa-fw fa-sun-o" ng-click="toggleCustomConfigWidgetMode(item, 'disabled')" aria-hidden="true" title="{{getCustomConfigWidgetModeTitle(item)}} [{{item.name}}]"></i>
+ <i class="fa fa-fw fa-sun-o" ng-click="toggleCustomConfigWidgetMode(item, false)" aria-hidden="true" title="{{getCustomConfigWidgetModeTitle(item)}} [{{item.name}}]"></i>
<span class="sr-only">{{getCustomConfigWidgetModeTitle(item)}} [{{item.name}}]</span>
</span>
</span>
<div class="control-value" ng-class="{ 'inline-control': item.widgetMode==='boolean', 'unset': !defined(config[item.name]), 'has-default': defined(item.defaultValue) && item.defaultValue!=null }">
<div class="hide-when-collapsed">
- <a ng-click="test()">Extra information</a>
+ {{ params['label-expanded'] || "" }}
</div>
<div>
- <span class="hide-when-expanded">Custom widget: </span>
+ <span class="hide-when-expanded">{{ params['label-collapsed'] || "" }}</span>
{{ config[item.name] }}
</div>
</div>
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/19de59de/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.js
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.js b/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.js
index d36c801..7c23092 100644
--- a/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.js
+++ b/ui-modules/blueprint-composer/app/components/custom-config-widget/suggestion-dropdown.js
@@ -31,7 +31,8 @@ export function suggestionDropdownDirective($rootScope) {
return {
restrict: 'E',
scope: {
- item: '='
+ item: '=',
+ params: '=',
},
template: template,
link: link,
@@ -39,6 +40,7 @@ export function suggestionDropdownDirective($rootScope) {
function link(scope) {
scope.$parent.copyScopeForCustomConfigWidget(scope);
+ console.log("params for widget for "+scope.item.name, scope.params);
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/19de59de/ui-modules/blueprint-composer/app/components/providers/blueprint-service.provider.js
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/providers/blueprint-service.provider.js b/ui-modules/blueprint-composer/app/components/providers/blueprint-service.provider.js
index 0e4b360..9f2491a 100644
--- a/ui-modules/blueprint-composer/app/components/providers/blueprint-service.provider.js
+++ b/ui-modules/blueprint-composer/app/components/providers/blueprint-service.provider.js
@@ -499,10 +499,26 @@ function BlueprintService($log, $q, $sce, paletteApi, iconGenerator, dslService)
}));
entity.miscData.set('sensors', data.sensors || []);
entity.miscData.set('traits', data.supertypes || []);
+ entity.miscData.set('tags', data.tags || []);
+ var uiHints = {};
+ data.tags.forEach( (t) => {
+ mergeAppendingLists(uiHints, t['ui-composer-hints']);
+ });
+ entity.miscData.set('ui-composer-hints', uiHints);
entity.miscData.set('virtual', data.virtual || null);
addUnlistedConfigKeysDefinitions(entity);
return entity;
}
+ function mergeAppendingLists(dst, src) {
+ for (let p in src) {
+ if (Array.isArray(dst[p]) || Array.isArray(src[p])) {
+ dst[p] = [].concat(dst[p] || [], src[p]);
+ } else {
+ dst[p] = Object.assign({}, dst[p], src[p]);
+ }
+ }
+ return dst;
+ }
function populateEntityFromApiError(entity) {
entity.clearIssues({group: 'type'});
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/19de59de/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js b/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js
index a0eeba8..17ab03a 100644
--- a/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js
+++ b/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js
@@ -106,9 +106,9 @@ export function specEditorDirective($rootScope, $templateCache, $injector, $sani
codeModeActive: {},
codeModeForced: {},
codeModeError: {},
- customWidget: {
- "defaultDisplayName": { mode: "full", widget: "known-widget-missing" },
- "download.url": { mode: "full", widget: "suggestion-dropdown" },
+ customConfigWidgetMetadata: {
+ "defaultDisplayName": { enabled: true, widget: "known-widget-missing" },
+ "download.url": { enabled: true, widget: "suggestion-dropdown" },
},
},
location: {
@@ -148,6 +148,8 @@ export function specEditorDirective($rootScope, $templateCache, $injector, $sani
scope.state.config.add.list = getAddListConfig();
});
+ loadCustomConfigWidgetMetadata(scope);
+
scope.config = {};
scope.$watch('model', (newVal, oldVal)=> {
if (newVal && !newVal.equals(oldVal)) {
@@ -528,36 +530,29 @@ export function specEditorDirective($rootScope, $templateCache, $injector, $sani
} else {
return "Edit in simple mode, unwrapping JSON if possible ["+itemName+"]";
}
- }
+ };
+ /** returns 'enabled' or 'disabled' if a widget is defined, or null if no special widget is defined */
scope.getCustomConfigWidgetMode = (item) => {
- var mode = (scope.state.config.customWidget[item.name] || {})["mode"] || null;
- if (mode) {
- if ((scope.state.config.customWidget[item.name] || {})["error"]) return null;
- }
- return mode;
- } ;
+ var widgetMetadata = scope.state.config.customConfigWidgetMetadata[item.name];
+ if (!widgetMetadata || widgetMetadata["error"]) return null;
+ return widgetMetadata["enabled"] ? 'enabled' : 'disabled';
+ };
scope.toggleCustomConfigWidgetMode = (item, newval) => {
- if (!scope.state.config.customWidget[item.name]) {
+ var widgetMetadata = scope.state.config.customConfigWidgetMetadata[item.name];
+ if (!widgetMetadata) {
$log.error('Custom widget mode should not be toggled when not available: '+item.name);
return null;
}
- if (newval) scope.state.config.customWidget[item.name].mode = newval;
- else {
- if (scope.state.config.customWidget[item.name].mode === "disabled") {
- // TODO not always full
- scope.state.config.customWidget[item.name].mode = "full"
- } else {
- scope.state.config.customWidget[item.name].mode = "full"
- }
- }
+ if (!scope.defined(newval)) newval = !widgetMetadata.enabled;
+ widgetMetadata.enabled = newval;
}
scope.getCustomConfigWidgetModeTitle = (item) => {
- if (!scope.state.config.customWidget[item.name]) {
+ var widgetMetadata = scope.state.config.customConfigWidgetMetadata[item.name];
+ if (!widgetMetadata) {
// shouldn't be visible
return "(custom widget not available)";
}
- if (scope.state.config.customWidget[item.name].mode === "disabled") return "Enable custom widget";
- else return "Disable custom widget";
+ return widgetMetadata.enabled ? "Use standard widget" : "Use custom widget";
};
scope.copyScopeForCustomConfigWidget = (descendantScope) => {
descendantScope.toggleCustomConfigWidgetMode = scope.toggleCustomConfigWidgetMode;
@@ -568,15 +563,16 @@ export function specEditorDirective($rootScope, $templateCache, $injector, $sani
descendantScope.copyScopeForCustomConfigWidget = scope.copyScopeForCustomConfigWidget;
};
scope.getCustomConfigWidgetTemplate = (item) => {
- var widgetName = $sanitize(scope.state.config.customWidget[item.name].widget);
+ var widgetMetadata = scope.state.config.customConfigWidgetMetadata[item.name];
+ var widgetName = $sanitize(widgetMetadata.widget || '--no-widget--');
var templateName = 'custom-config-widget-'+widgetName;
if (!$templateCache.get(templateName)) {
var widgetDirective = widgetName.replace(/(-[a-z])/g, function($1){return $1[1].toUpperCase();})+'Directive';
if ($injector.has(widgetDirective)) {
- $templateCache.put(templateName, '<'+widgetName+' item="item">foo</'+widgetName+'>');
+ $templateCache.put(templateName, '<'+widgetName+' item="item" params="state.config.customConfigWidgetMetadata[item.name]"/>');
} else {
$log.error('Missing directive '+widgetDirective+' for custom widget for '+item.name+'; falling back to default widget');
- scope.state.config.customWidget[item.name].error = "Missing directive";
+ scope.state.config.customConfigWidgetMetadata[item.name].error = "Missing directive";
templateName = "error-" + templateName;
$templateCache.put(templateName, '<i>Widget '+widgetName+' missing</i>');
}
@@ -615,6 +611,21 @@ export function specEditorDirective($rootScope, $templateCache, $injector, $sani
});
}
+ function loadCustomConfigWidgetMetadata(model) {
+ console.log("misc data", model.miscData, scope.model.miscData.get('ui-composer-hints'));
+ var customConfigWidgets = (scope.model.miscData.get('ui-composer-hints') || {})['config-widgets'] || [];
+ console.log("customs", customConfigWidgets);
+ customConfigWidgets.forEach( (wd) => {
+ console.log("looking at", wd);
+ var keys = wd.keys || [ wd.key ];
+ keys.forEach( (k) => {
+ console.log("setting key", k);
+ scope.state.config.customConfigWidgetMetadata[k] = angular.extend({ enabled: true }, scope.state.config.customConfigWidgetMetadata[k], wd);
+ });
+ });
+ console.log("custom config", scope.state.config.customConfigWidgetMetadata);
+ }
+
/* config state for each item is stored in multiple places:
* * scope.config = map of values used/set by editor (strings, map of strings, json code if using code mode, etc);
* this should be suitable for ng-model to work with, so e.g. if using code mode we need to put JSON.stringify value in here,
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/19de59de/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.less
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.less b/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.less
index 233d937..da74f0f 100644
--- a/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.less
+++ b/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.less
@@ -338,7 +338,7 @@ spec-editor {
}
}
.form-group {
- &, .config-flex-row, .custom-widget-full {
+ &, .config-flex-row, .custom-config-widget {
display: flex;
flex-flow: row wrap;
width: 100%;
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/19de59de/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.template.html
----------------------------------------------------------------------
diff --git a/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.template.html b/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.template.html
index cc3e11e..740d295 100644
--- a/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.template.html
+++ b/ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.template.html
@@ -139,12 +139,12 @@
auto-focus-not-if-within="true"
ng-focus="recordFocus(item)"
on-enter="advanceControlInFormGroup">
- <div ng-if="getCustomConfigWidgetMode(item) === 'full'" class="custom-widget-full">
- <ng-include src="getCustomConfigWidgetTemplate(item)" class="custom-widget-full"/>
+ <div ng-if="getCustomConfigWidgetMode(item) === 'enabled'" class="custom-config-widget">
+ <ng-include src="getCustomConfigWidgetTemplate(item)" class="custom-config-widget"/>
</div>
<!-- have to hide it; excluding it conditionally via if doesn't play nice with switch -->
- <div ng-show="getCustomConfigWidgetMode(item) !== 'full'" class="config-flex-row">
+ <div ng-show="getCustomConfigWidgetMode(item) !== 'enabled'" class="config-flex-row">
<label class="control-label" for="{{item.name}}">
<span class="label-spec-configuration">{{item.label || item.name}}</span>
<span class="info-spec-configuration">
[06/12] brooklyn-ui git commit: add license info so files just added
don't break RAT
Posted by he...@apache.org.
add license info so files just added don't break RAT
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/commit/2945d14f
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/tree/2945d14f
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/diff/2945d14f
Branch: refs/heads/master
Commit: 2945d14f48d1cb54fac1712306ddd13d548c7ec8
Parents: 6e03037
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed Aug 8 11:02:27 2018 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Wed Aug 8 11:02:27 2018 +0100
----------------------------------------------------------------------
docs/customizations.md | 17 +++++++++++++++++
docs/vanilla-with-custom-widget.bom | 18 ++++++++++++++++++
2 files changed, 35 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/2945d14f/docs/customizations.md
----------------------------------------------------------------------
diff --git a/docs/customizations.md b/docs/customizations.md
index a27bc0e..24f0a47 100644
--- a/docs/customizations.md
+++ b/docs/customizations.md
@@ -20,4 +20,21 @@ There are a number of points where UI default choices can be overridden:
widgets should be registered as angular directives using the standard Angular naming conventions
(e.g. suggestionDropdownDirective), as done for that directive in app/index.js and app/index.less.
+<!--
+ 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.
+-->
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/2945d14f/docs/vanilla-with-custom-widget.bom
----------------------------------------------------------------------
diff --git a/docs/vanilla-with-custom-widget.bom b/docs/vanilla-with-custom-widget.bom
index 313d3a6..ceb2ecb 100644
--- a/docs/vanilla-with-custom-widget.bom
+++ b/docs/vanilla-with-custom-widget.bom
@@ -1,3 +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.
+
brooklyn.catalog:
id: vanilla-with-custom-widget
version: 1.0.0-SNAPSHOT