http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8e792605/modules/web-control-center/nodejs/public/form-models/clusters.json ---------------------------------------------------------------------- diff --git a/modules/web-control-center/nodejs/public/form-models/clusters.json b/modules/web-control-center/nodejs/public/form-models/clusters.json new file mode 100644 index 0000000..3258cc8 --- /dev/null +++ b/modules/web-control-center/nodejs/public/form-models/clusters.json @@ -0,0 +1,849 @@ +{ + "templateTip": [ + "Use following template for add cluster:", + "<ul>", + " <li>blank - Empty configuration.</li>", + " <li>local - Configuration with static ips discovery and pre-configured list of IP addresses.</li>", + " <li>multicast - Configuration with multicast discovery.</li>", + "</ul>" + ], + "general": [ + { + "label": "Name", + "type": "text", + "model": "name", + "required": true, + "placeholder": "Input name" + }, + { + "label": "Caches", + "type": "dropdown-multiple", + "model": "caches", + "placeholder": "Choose caches", + "items": "caches", + "tip": [ + "Select caches to start in cluster." + ], + "addLink": { + "label": "Add cache(s)", + "ref": "/caches" + } + }, + { + "label": "Discovery", + "type": "dropdown-details", + "path": "discovery", + "model": "kind", + "required": true, + "placeholder": "Choose discovery", + "items": "discoveries", + "tip": [ + "Discovery allows to discover remote nodes in grid." + ], + "details": { + "Vm": { + "expanded": true, + "fields": [ + { + "tableLabel": "Addresses", + "label": "address", + "type": "table-simple", + "path": "discovery.Vm", + "model": "addresses", + "editIdx": -1, + "reordering": true, + "placeholder": "IP address:port", + "tip": [ + "Addresses may be represented as follows:", + "<ul>", + " <li>IP address (e.g. 127.0.0.1, 9.9.9.9, etc);</li>", + " <li>IP address and port (e.g. 127.0.0.1:47500, 9.9.9.9:47501, etc);</li>", + " <li>IP address and port range (e.g. 127.0.0.1:47500..47510, 9.9.9.9:47501..47504, etc);</li>", + " <li>Hostname (e.g. host1.com, host2, etc);</li>", + " <li>Hostname and port (e.g. host1.com:47500, host2:47502, etc).</li>", + " <li>Hostname and port range (e.g. host1.com:47500..47510, host2:47502..47508, etc).</li>", + "</ul>", + "If port is 0 or not provided then default port will be used (depends on discovery SPI configuration).", + "If port range is provided (e.g. host:port1..port2) the following should be considered:", + "<ul>", + " <li>port1 < port2 should be true;</li>", + " <li>Both port1 and port2 should be greater than 0.</li>", + "</ul>" + ] + } + ] + }, + "Multicast": { + "expanded": false, + "fields": [ + { + "label": "IP address", + "type": "text", + "path": "discovery.Multicast", + "model": "multicastGroup", + "placeholder": "228.1.2.4", + "tip": [ + "IP address of multicast group." + ] + }, + { + "label": "Port number", + "type": "number", + "path": "discovery.Multicast", + "model": "multicastPort", + "max": 65535, + "placeholder": "47400", + "tip": [ + "Port number which multicast messages are sent to." + ] + }, + { + "label": "Waits for reply", + "type": "number", + "path": "discovery.Multicast", + "model": "responseWaitTime", + "placeholder": "500", + "tip": [ + "Time in milliseconds IP finder waits for reply to multicast address request." + ] + }, + { + "label": "Attempts count", + "type": "number", + "path": "discovery.Multicast", + "model": "addressRequestAttempts", + "placeholder": "2", + "tip": [ + "Number of attempts to send multicast address request.", + "IP finder re-sends request only in case if no reply for previous request is received." + ] + }, + { + "label": "Local address", + "type": "text", + "path": "discovery.Multicast", + "model": "localAddress", + "tip": [ + "Local host address used by this IP finder.", + "If provided address is non-loopback then multicast socket is bound to this interface.", + "If local address is not set or is any local address then IP finder creates multicast sockets for all found non-loopback addresses." + ] + } + ] + }, + "S3": { + "expanded": true, + "fields": [ + { + "label": "Bucket name", + "type": "text", + "path": "discovery.S3", + "model": "bucketName", + "placeholder": "" + } + ] + }, + "Cloud": { + "expanded": true, + "fields": [ + { + "label": "Credential", + "type": "text", + "path": "discovery.Cloud", + "model": "credential", + "placeholder": "", + "tip": [ + "Credential that is used during authentication on the cloud.", + "Depending on a cloud platform it can be a password or access key." + ] + }, + { + "label": "Path to credential", + "type": "text", + "path": "discovery.Cloud", + "model": "credentialPath", + "placeholder": "", + "tip": [ + "Path to a credential that is used during authentication on the cloud.", + "Access key or private key should be stored in a plain or PEM file without a passphrase." + ] + }, + { + "label": "Identity", + "type": "text", + "path": "discovery.Cloud", + "model": "identity", + "placeholder": "", + "tip": [ + "Identity that is used as a user name during a connection to the cloud.", + "Depending on a cloud platform it can be an email address, user name, etc." + ] + }, + { + "label": "Provider", + "type": "text", + "model": "discovery.Cloud.provider", + "placeholder": "", + "tip": [ + "Cloud provider to use." + ] + } + ] + }, + "GoogleStorage": { + "expanded": true, + "fields": [ + { + "label": "Project name", + "type": "text", + "path": "discovery.GoogleStorage", + "model": "projectName", + "placeholder": "", + "tip": [ + "Google Cloud Platforms project name.", + "Usually this is an auto generated project number (ex. 208709979073) that can be found in 'Overview' section of Google Developer Console." + ] + }, + { + "label": "Bucket name", + "type": "text", + "path": "discovery.GoogleStorage", + "model": "bucketName", + "placeholder": "", + "tip": [ + "Google Cloud Storage bucket name.", + "If the bucket doesn't exist Ignite will automatically create it.", + "However the name must be unique across whole Google Cloud Storage and Service Account Id must be authorized to perform this operation." + ] + }, + { + "label": "Private key path", + "type": "text", + "path": "discovery.GoogleStorage", + "model": "serviceAccountP12FilePath", + "placeholder": "", + "tip": [ + "Full path to the private key in PKCS12 format of the Service Account." + ] + }, + { + "label": "Account id", + "type": "text", + "path": "discovery.GoogleStorage", + "model": "accountId", + "placeholder": "", + "tip": [ + "Service account ID (typically an e-mail address)." + ] + } + ] + }, + "Jdbc": { + "expanded": true, + "fields": [ + { + "label": "DB schema should be initialized by Ignite", + "type": "check", + "path": "discovery.Jdbc", + "model": "initSchema", + "tip": [ + "Flag indicating whether DB schema should be initialized by Ignite or was explicitly created by user." + ] + } + ] + }, + "SharedFs": { + "expanded": false, + "fields": [ + { + "label": "File path", + "type": "text", + "path": "discovery.SharedFs", + "model": "path", + "placeholder": "disco/tcp" + } + ] + } + } + } + ], + "advanced": [ + { + "label": "Atomic configuration", + "tip": [ + "Configuration for atomic data structures.", + "Atomics are distributed across the cluster, essentially enabling performing atomic operations (such as increment-and-get or compare-and-set) with the same globally-visible value." + ], + "fields": [ + { + "label": "Backups", + "type": "number", + "path": "atomicConfiguration", + "model": "backups", + "placeholder": "0", + "tip": [ + "Number of backup nodes." + ] + }, + { + "label": "Cache mode", + "type": "dropdown", + "path": "atomicConfiguration", + "model": "cacheMode", + "placeholder": "PARTITIONED", + "items": "cacheModes", + "tip": [ + "Cache modes:", + "<ul>", + " <li>Partitioned - in this mode the overall key set will be divided into partitions and all partitions will be split equally between participating nodes.</li>", + " <li>Replicated - in this mode all the keys are distributed to all participating nodes.</li>", + " <li>Local - in this mode caches residing on different grid nodes will not know about each other.</li>", + "</ul>" + ] + }, + { + "label": "Sequence reserve", + "type": "number", + "path": "atomicConfiguration", + "model": "atomicSequenceReserveSize", + "placeholder": "1,000", + "tip": [ + "Default number of sequence values reserved for IgniteAtomicSequence instances.", + "After a certain number has been reserved, consequent increments of sequence will happen locally, without communication with other nodes, until the next reservation has to be made." + ] + } + ] + }, + { + "label": "Communication", + "tip": [ + "Cluster communication network properties." + ], + "fields": [ + { + "label": "Timeout", + "type": "number", + "model": "networkTimeout", + "placeholder": "5,000", + "tip": [ + "Maximum timeout in milliseconds for network requests." + ] + }, + { + "label": "Send retry delay", + "type": "number", + "model": "networkSendRetryDelay", + "placeholder": "1,000", + "tip": [ + "Interval in milliseconds between message send retries." + ] + }, + { + "label": "Send retry count", + "type": "number", + "model": "networkSendRetryCount", + "placeholder": "3", + "tip": [ + "Message send retries count." + ] + }, + { + "label": "Segment check frequency", + "type": "number", + "model": "segmentCheckFrequency", + "placeholder": "10,000", + "tip": [ + "Network segment check frequency in milliseconds.", + "If 0, periodic segment check is disabled and segment is checked only on topology changes (if segmentation resolvers are configured)." + ] + }, + { + "label": "Wait for segment on start", + "type": "check", + "model": "waitForSegmentOnStart", + "tip": [ + "Wait for segment on start flag.", + "<ul>", + " <li>If enabled, node should wait for correct segment on start.</li>", + " <li>If node detects that segment is incorrect on startup and enabled, node waits until segment becomes correct.</li>", + " <li>If segment is incorrect on startup and disabled, exception is thrown.</li>", + "</ul>" + ] + }, + { + "label": "Discovery startup delay", + "type": "number", + "model": "discoveryStartupDelay", + "placeholder": "600,000", + "tip": [ + "This value is used to expire messages from waiting list whenever node discovery discrepancies happen." + ] + } + ] + }, + { + "label": "Deployment", + "tip": [ + "Task and resources deployment in cluster." + ], + "fields": [ + { + "label": "Mode", + "type": "dropdown", + "model": "deploymentMode", + "placeholder": "SHARED", + "items": "deploymentModes", + "tip": [ + "Task classes and resources sharing mode." + ] + } + ] + }, + { + "label": "Events", + "tip": [ + " Grid events are used for notification about what happens within the grid." + ], + "fields": [ + { + "label": "Include type", + "type": "dropdown-multiple", + "model": "includeEventTypes", + "placeholder": "Choose recorded event types", + "items": "events", + "tip": [ + "Array of event types, which will be recorded by GridEventStorageManager#record(Event).", + "Note, that either the include event types or the exclude event types can be established." + ] + } + ] + }, + { + "label": "Marshaller", + "tip": [ + "Marshaller allows to marshal or unmarshal objects in grid.", + "It provides serialization/deserialization mechanism for all instances that are sent across networks or are otherwise serialized." + ], + "fields": [ + { + "label": "Marshaller", + "type": "dropdown-details", + "path": "marshaller", + "model": "kind", + "placeholder": "Choose marshaller", + "items": "marshallers", + "tip": [ + "Instance of marshaller to use in grid. If not provided, OptimizedMarshaller will be used on Java HotSpot VM, and JdkMarshaller will be used on other VMs." + ], + "details": { + "OptimizedMarshaller": { + "expanded": false, + "fields": [ + { + "label": "Streams pool size", + "type": "number", + "path": "marshaller.OptimizedMarshaller", + "model": "poolSize", + "placeholder": "0", + "tip": [ + "Specifies size of cached object streams used by marshaller.", + "Object streams are cached for performance reason to avoid costly recreation for every serialization routine.", + "If 0 (default), pool is not used and each thread has its own cached object stream which it keeps reusing.", + "Since each stream has an internal buffer, creating a stream for each thread can lead to high memory consumption if many large messages are marshalled or unmarshalled concurrently.", + "Consider using pool in this case. This will limit number of streams that can be created and, therefore, decrease memory consumption.", + "NOTE: Using streams pool can decrease performance since streams will be shared between different threads which will lead to more frequent context switching." + ] + }, + { + "label": "Require serializable", + "type": "check", + "path": "marshaller.OptimizedMarshaller", + "model": "requireSerializable", + "tip": [ + "Whether marshaller should require Serializable interface or not." + ] + } + ] + } + } + }, + { + "label": "Marshal local jobs", + "type": "check", + "model": "marshalLocalJobs", + "placeholder": "false", + "tip": [ + "If this flag is enabled, jobs mapped to local node will be marshalled as if it was remote node." + ] + }, + { + "label": "Keep alive time", + "type": "number", + "model": "marshallerCacheKeepAliveTime", + "placeholder": "10,000", + "tip": [ + "Keep alive time of thread pool that is in charge of processing marshaller messages." + ] + }, + { + "label": "Pool size", + "type": "number", + "model": "marshallerCacheThreadPoolSize", + "placeholder": "max(8, availableProcessors) * 2", + "tip": [ + "Default size of thread pool that is in charge of processing marshaller messages." + ] + } + ] + }, + { + "label": "Metrics", + "tip": ["Cluster runtime metrics settings."], + "fields": [ + { + "label": "Elapsed time", + "type": "number", + "model": "metricsExpireTime", + "placeholder": "Long.MAX_VALUE", + "min": 1, + "tip": [ + "Time in milliseconds after which a certain metric value is considered expired." + ] + }, + { + "label": "History size", + "type": "number", + "model": "metricsHistorySize", + "placeholder": "10,000", + "min": 1, + "tip": [ + "Number of metrics kept in history to compute totals and averages." + ] + }, + { + "label": "Log frequency", + "type": "number", + "model": "metricsLogFrequency", + "placeholder": "60,000", + "tip": [ + "Frequency of metrics log print out. To disable set to 0" + ] + }, + { + "label": "Update frequency", + "type": "number", + "model": "metricsUpdateFrequency", + "placeholder": "60,000", + "tip": [ + "Job metrics update frequency in milliseconds.", + "<ul>", + " <li>If set to -1 job metrics are never updated.</li>", + " <li>If set to 0 job metrics are updated on each job start and finish.</li>", + " <li>Positive value defines the actual update frequency.</li>", + "</ul>" + ] + } + ] + }, + { + "label": "Peer Class Loading", + "tip": ["Cluster peer class loading settings."], + "fields": [ + { + "label": "Enable peer class loading", + "type": "check", + "model": "peerClassLoadingEnabled", + "tip": [ + "Enables/disables peer class loading." + ] + }, + { + "label": "Local class path exclude", + "type": "text", + "model": "peerClassLoadingLocalClassPathExclude", + "placeholder": "[]", + "tip": [ + "List of packages separated by comma from the system classpath that need to be peer-to-peer loaded from task originating node.", + "'*' is supported at the end of the package name which means that all sub-packages and their classes are included like in Java package import clause." + ] + }, + { + "label": "Missed resources cache size", + "type": "number", + "model": "peerClassLoadingMissedResourcesCacheSize", + "placeholder": "100", + "tip": [ + "If size greater than 0, missed resources will be cached and next resource request ignored.", + "If size is 0, then request for the resource will be sent to the remote node every time this resource is requested." + ] + }, + { + "label": "Pool size", + "type": "number", + "model": "peerClassLoadingThreadPoolSize", + "placeholder": "availableProcessors", + "tip": [ + "Thread pool size to use for peer class loading." + ] + } + ] + }, + { + "label": "Swap", + "tip": ["Settings for overflow data to disk if it cannot fit in memory."], + "fields": [ + { + "label": "Swap space SPI", + "type": "dropdown-details", + "path": "swapSpaceSpi", + "model": "kind", + "items": "swapSpaceSpis", + "placeholder": "Choose swap SPI", + "tip": [ + "Provides a mechanism in grid for storing data on disk.", + "Ignite cache uses swap space to overflow data to disk if it cannot fit in memory." + ], + "details": { + "FileSwapSpaceSpi": { + "fields": [ + { + "label": "Base directory", + "type": "text", + "path": "swapSpaceSpi.FileSwapSpaceSpi", + "model": "baseDirectory", + "placeholder": "swapspace", + "tip": [ + "Base directory where to write files." + ] + }, + { + "label": "Read stripe size", + "type": "number", + "path": "swapSpaceSpi.FileSwapSpaceSpi", + "model": "readStripesNumber", + "placeholder": "available CPU cores", + "tip": [ + "Read stripe size defines number of file channels to be used concurrently." + ] + }, + { + "label": "Maximum sparsity", + "type": "number", + "path": "swapSpaceSpi.FileSwapSpaceSpi", + "model": "maximumSparsity", + "placeholder": "0.5", + "tip": [ + "This property defines maximum acceptable wasted file space to whole file size ratio.", + "When this ratio becomes higher than specified number compacting thread starts working." + ] + }, + { + "label": "Max write queue size", + "type": "number", + "path": "swapSpaceSpi.FileSwapSpaceSpi", + "model": "maxWriteQueueSize", + "placeholder": "1024 * 1024", + "tip": [ + "Max write queue size in bytes.", + "If there are more values are waiting for being written to disk then specified size, SPI will block on store operation." + ] + }, + { + "label": "Write buffer size", + "type": "number", + "path": "swapSpaceSpi.FileSwapSpaceSpi", + "model": "writeBufferSize", + "placeholder": "Available CPU cores", + "tip": [ + "Write buffer size in bytes.", + "Write to disk occurs only when this buffer is full." + ] + } + ] + } + } + } + ] + }, + { + "label": "Time configuration", + "tip": ["Time settings for CLOCK write ordering mode."], + "fields": [ + { + "label": "Samples size", + "type": "number", + "model": "clockSyncSamples", + "placeholder": "8", + "tip": [ + "Number of samples used to synchronize clocks between different nodes.", + "Clock synchronization is used for cache version assignment in CLOCK order mode." + ] + }, + { + "label": "Frequency", + "type": "number", + "model": "clockSyncFrequency", + "placeholder": "120,000", + "tip": [ + "Frequency at which clock is synchronized between nodes, in milliseconds.", + "Clock synchronization is used for cache version assignment in CLOCK order mode." + ] + }, + { + "label": "Port base", + "type": "number", + "model": "timeServerPortBase", + "max": 65535, + "placeholder": "31100", + "tip": [ + "Time server provides clock synchronization between nodes.", + "Base UPD port number for grid time server. Time server will be started on one of free ports in range." + ] + }, + { + "label": "Port range", + "type": "number", + "model": "timeServerPortRange", + "placeholder": "100", + "tip": [ + "Time server port range." + ] + } + ] + }, + { + "label": "Thread pools size", + "tip": ["Settings for node thread pools."], + "fields": [ + { + "label": "Public", + "type": "number", + "model": "publicThreadPoolSize", + "placeholder": "max(8, availableProcessors) * 2", + "tip": [ + "Thread pool that is in charge of processing ComputeJob, GridJobs and user messages sent to node." + ] + }, + { + "label": "System", + "type": "number", + "model": "systemThreadPoolSize", + "placeholder": "max(8, availableProcessors) * 2", + "tip": [ + "Thread pool that is in charge of processing internal system messages." + ] + }, + { + "label": "Management", + "type": "number", + "model": "managementThreadPoolSize", + "placeholder": "4", + "tip": [ + "Thread pool that is in charge of processing internal and Visor ComputeJob, GridJobs." + ] + }, + { + "label": "IGFS", + "type": "number", + "model": "igfsThreadPoolSize", + "placeholder": "availableProcessors", + "tip": [ + "Thread pool that is in charge of processing outgoing IGFS messages." + ] + } + ] + }, + { + "label": "Transactions", + "tip": ["Settings for transactions."], + "fields": [ + { + "label": "Cache concurrency", + "type": "dropdown", + "path": "transactionConfiguration", + "model": "defaultTxConcurrency", + "placeholder": "PESSIMISTIC", + "items": "transactionConcurrency", + "tip": [ + "Cache transaction concurrency to use when one is not explicitly specified." + ] + }, + { + "label": "Isolation", + "type": "dropdown", + "path": "transactionConfiguration", + "model": "transactionIsolation", + "placeholder": "REPEATABLE_READ", + "items": "transactionIsolation", + "tip": [ + "Default transaction isolation." + ] + }, + { + "label": "Default timeout", + "type": "number", + "path": "transactionConfiguration", + "model": "defaultTxTimeout", + "placeholder": "0", + "tip": [ + "Default transaction timeout." + ] + }, + { + "label": "Pessimistic log cleanup delay", + "type": "number", + "path": "transactionConfiguration", + "model": "pessimisticTxLogLinger", + "placeholder": "10,000", + "tip": [ + "Delay, in milliseconds, after which pessimistic recovery entries will be cleaned up for failed node." + ] + }, + { + "label": "Pessimistic log size", + "type": "number", + "path": "transactionConfiguration", + "model": "pessimisticTxLogSize", + "placeholder": "0", + "tip": [ + "Size of pessimistic transactions log stored on node in order to recover transaction commit if originating node has left grid before it has sent all messages to transaction nodes." + ] + }, + { + "label": "Enable serializable cache transactions", + "type": "check", + "path": "transactionConfiguration", + "model": "txSerializableEnabled", + "tip": [ + "Flag to enable/disable isolation level for cache transactions.", + "Serializable level does carry certain overhead and if not used, should be disabled." + ] + } + ] + }, + { + "label": "Utility", + "tip": ["Settings for utility messages processing."], + "fields": [ + { + "label": "Keep alive time", + "type": "number", + "model": "utilityCacheKeepAliveTime", + "placeholder": "10,000", + "tip": [ + "Keep alive time of thread pool that is in charge of processing utility cache messages." + ] + }, + { + "label": "Pool size", + "type": "number", + "model": "utilityCachePoolSize", + "placeholder": "max(8, availableProcessors) * 2", + "tip": [ + "Thread pool that is in charge of processing utility cache messages." + ] + } + ] + } + ] +}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8e792605/modules/web-control-center/nodejs/public/form-models/persistence.json ---------------------------------------------------------------------- diff --git a/modules/web-control-center/nodejs/public/form-models/persistence.json b/modules/web-control-center/nodejs/public/form-models/persistence.json new file mode 100644 index 0000000..edf5344 --- /dev/null +++ b/modules/web-control-center/nodejs/public/form-models/persistence.json @@ -0,0 +1,66 @@ +{ + "connection": [ + { + "label": "Name", + "type": "text", + "model": "name", + "required": true + }, + { + "label": "Database type", + "type": "dropdown", + "model": "dbType", + "placeholder": "Choose database", + "items": "databases", + "tip": [ + "Select database type to connect for loading tables metadata." + ] + }, + { + "label": "Database name", + "type": "text", + "model": "dbName", + "tip": [ + "Database name to connect for loading tables metadata." + ] + }, + { + "label": "Host", + "type": "text", + "model": "host", + "placeholder": "IP address or host", + "tip": [ + "IP address or host name where database server deployed." + ] + }, + { + "label": "Port", + "type": "number", + "model": "port", + "max": 65535, + "placeholder": "", + "tip": [ + "Port number for connecting to database." + ] + }, + { + "label": "User", + "type": "text", + "model": "user", + "placeholder": "", + "tip": [ + "User name for connecting to database." + ] + }, + { + "label": "Password", + "type": "password", + "model": "password", + "placeholder": "", + "tip": [ + "Password for connecting to database.", + "Note, password would not be saved." + ] + } + ] +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8e792605/modules/web-control-center/nodejs/public/images/docker.png ---------------------------------------------------------------------- diff --git a/modules/web-control-center/nodejs/public/images/docker.png b/modules/web-control-center/nodejs/public/images/docker.png new file mode 100644 index 0000000..7ec3aef Binary files /dev/null and b/modules/web-control-center/nodejs/public/images/docker.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8e792605/modules/web-control-center/nodejs/public/images/java.png ---------------------------------------------------------------------- diff --git a/modules/web-control-center/nodejs/public/images/java.png b/modules/web-control-center/nodejs/public/images/java.png new file mode 100644 index 0000000..ddb3b8e Binary files /dev/null and b/modules/web-control-center/nodejs/public/images/java.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8e792605/modules/web-control-center/nodejs/public/images/logo.png ---------------------------------------------------------------------- diff --git a/modules/web-control-center/nodejs/public/images/logo.png b/modules/web-control-center/nodejs/public/images/logo.png new file mode 100644 index 0000000..c3577c5 Binary files /dev/null and b/modules/web-control-center/nodejs/public/images/logo.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8e792605/modules/web-control-center/nodejs/public/images/xml.png ---------------------------------------------------------------------- diff --git a/modules/web-control-center/nodejs/public/images/xml.png b/modules/web-control-center/nodejs/public/images/xml.png new file mode 100644 index 0000000..029065e Binary files /dev/null and b/modules/web-control-center/nodejs/public/images/xml.png differ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8e792605/modules/web-control-center/nodejs/public/javascripts/bundle.js ---------------------------------------------------------------------- diff --git a/modules/web-control-center/nodejs/public/javascripts/bundle.js b/modules/web-control-center/nodejs/public/javascripts/bundle.js new file mode 100644 index 0000000..840da56 --- /dev/null +++ b/modules/web-control-center/nodejs/public/javascripts/bundle.js @@ -0,0 +1,18 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Place here all common utility functions that will be available on each page. \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8e792605/modules/web-control-center/nodejs/public/javascripts/controllers/caches.js ---------------------------------------------------------------------- diff --git a/modules/web-control-center/nodejs/public/javascripts/controllers/caches.js b/modules/web-control-center/nodejs/public/javascripts/controllers/caches.js new file mode 100644 index 0000000..006f065 --- /dev/null +++ b/modules/web-control-center/nodejs/public/javascripts/controllers/caches.js @@ -0,0 +1,237 @@ +/* + * 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. + */ + +configuratorModule.controller('cachesController', ['$scope', '$alert', '$http', 'commonFunctions', function ($scope, $alert, $http, commonFunctions) { + $scope.swapSimpleItems = commonFunctions.swapSimpleItems; + $scope.joinTip = commonFunctions.joinTip; + $scope.getModel = commonFunctions.getModel; + + $scope.atomicities = [ + {value: 'ATOMIC', label: 'ATOMIC'}, + {value: 'TRANSACTIONAL', label: 'TRANSACTIONAL'} + ]; + + $scope.modes = [ + {value: 'PARTITIONED', label: 'PARTITIONED'}, + {value: 'REPLICATED', label: 'REPLICATED'}, + {value: 'LOCAL', label: 'LOCAL'} + ]; + + $scope.atomicWriteOrderModes = [ + {value: 'CLOCK', label: 'CLOCK'}, + {value: 'PRIMARY', label: 'PRIMARY'} + ]; + + $scope.memoryModes = [ + {value: 'ONHEAP_TIERED', label: 'ONHEAP_TIERED'}, + {value: 'OFFHEAP_TIERED', label: 'OFFHEAP_TIERED'}, + {value: 'OFFHEAP_VALUES', label: 'OFFHEAP_VALUES'} + ]; + + $scope.evictionPolicies = [ + {value: 'LRU', label: 'Least Recently Used'}, + {value: 'RND', label: 'Random'}, + {value: 'FIFO', label: 'FIFO'}, + {value: 'SORTED', label: 'Sorted'}, + {value: undefined, label: 'Not set'} + ]; + + $scope.rebalanceModes = [ + {value: 'SYNC', label: 'SYNC'}, + {value: 'ASYNC', label: 'ASYNC'}, + {value: 'NONE', label: 'NONE'} + ]; + + $scope.cacheStoreFactories = [ + {value: 'CacheJdbcPojoStoreFactory', label: 'JDBC POJO store factory'}, + {value: 'CacheJdbcBlobStoreFactory', label: 'JDBC BLOB store factory'}, + {value: 'CacheHibernateBlobStoreFactory', label: 'Hibernate BLOB store factory'}, + {value: undefined, label: 'Not set'} + ]; + + $scope.cacheStoreJdbcDialects = [ + {value: 'BasicJdbcDialect', label: 'Generic JDBC dialect'}, + {value: 'OracleDialect', label: 'Oracle'}, + {value: 'DB2Dialect', label: 'IBM DB2'}, + {value: 'SQLServerDialect', label: 'Microsoft SQL Server'}, + {value: 'MySQLDialect', label: 'My SQL'}, + {value: 'H2Dialect', label: 'H2 database'} + ]; + + $scope.general = []; + $scope.advanced = []; + + $http.get('/form-models/caches.json') + .success(function (data) { + $scope.general = data.general; + $scope.advanced = data.advanced; + }); + + $scope.caches = []; + + // When landing on the page, get caches and show them. + $http.get('/rest/caches') + .success(function (data) { + $scope.spaces = data.spaces; + $scope.caches = data.caches; + + var restoredItem = angular.fromJson(sessionStorage.cacheBackupItem); + + if (restoredItem) { + var idx = _.findIndex($scope.caches, function (cache) { + return cache._id == restoredItem._id; + }); + + if (idx >= 0) + $scope.selectedItem = $scope.caches[idx]; + + $scope.backupItem = restoredItem; + } + + $scope.$watch('backupItem', function (val) { + if (val) + sessionStorage.cacheBackupItem = angular.toJson(val); + }, true); + }); + + $scope.selectItem = function (item) { + $scope.selectedItem = item; + + $scope.backupItem = angular.copy(item); + }; + + // Add new cache. + $scope.createItem = function () { + $scope.backupItem = {mode: 'PARTITIONED', atomicityMode: 'ATOMIC'}; + $scope.backupItem.space = $scope.spaces[0]._id; + }; + + // Save cache in db. + $scope.saveItem = function () { + var item = $scope.backupItem; + + console.log(item); + + if (item.cacheStoreFactory && !item.readThrough && !item.writeThrough) { + $alert({position: 'top', title: 'Store is configured but read/write through are not enabled!'}); + + return; + } + + if ((item.readThrough || item.writeThrough) && (!item.cacheStoreFactory || !item.cacheStoreFactory.kind)) { + $alert({position: 'top', title: 'Read / write through are enabled but strore is not configured!'}); + + return; + } + + $http.post('/rest/caches/save', item) + .success(function (_id) { + var idx = _.findIndex($scope.caches, function (cache) { + return cache._id == _id; + }); + + if (idx >= 0) + angular.extend($scope.caches[idx], item); + else { + item._id = _id; + + $scope.caches.push(item); + } + + $scope.selectItem(item); + + $alert({ + type: 'success', + title: 'Cache "' + item.name + '" saved.', + duration: 2, + container: '#save-btn' + }); + }) + .error(function (errorMessage) { + $alert({title: errorMessage}); + }); + }; + + $scope.removeItem = function () { + var _id = $scope.selectedItem._id; + + $http.post('/rest/caches/remove', {_id: _id}) + .success(function () { + var i = _.findIndex($scope.caches, function (cache) { + return cache._id == _id; + }); + + if (i >= 0) { + $scope.caches.splice(i, 1); + + $scope.selectedItem = undefined; + $scope.backupItem = undefined; + } + }) + .error(function (errorMessage) { + $alert({title: errorMessage}); + }); + }; + + $scope.addIndexedTypes = function (keyCls, valCls) { + var idxTypes = $scope.backupItem.indexedTypes; + + var newItem = {keyClass: keyCls, valueClass: valCls}; + + if (idxTypes) + idxTypes.push(newItem); + else + $scope.backupItem.indexedTypes = [newItem]; + }; + + $scope.editIndexedTypes = function (idx) { + $scope.indexedTypeIdx = idx; + + if (idx < 0) { + $scope.currKeyCls = ''; + $scope.currValCls = ''; + } + else { + var idxType = $scope.backupItem.indexedTypes[idx]; + + $scope.currKeyCls = idxType.keyClass; + $scope.currValCls = idxType.valueClass; + } + }; + + $scope.saveIndexedType = function (k, v) { + var idxTypes = $scope.backupItem.indexedTypes; + + var idx = $scope.indexedTypeIdx; + + if (idx < 0) { + var newItem = {keyClass: k, valueClass: v}; + + if (idxTypes) + idxTypes.push(newItem); + else + $scope.backupItem.indexedTypes = [newItem]; + } + else { + var idxType = idxTypes[idx]; + + idxType.keyClass = k; + idxType.valueClass = v; + } + }; + }] +); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8e792605/modules/web-control-center/nodejs/public/javascripts/controllers/clusters.js ---------------------------------------------------------------------- diff --git a/modules/web-control-center/nodejs/public/javascripts/controllers/clusters.js b/modules/web-control-center/nodejs/public/javascripts/controllers/clusters.js new file mode 100644 index 0000000..ce38381 --- /dev/null +++ b/modules/web-control-center/nodejs/public/javascripts/controllers/clusters.js @@ -0,0 +1,207 @@ +/* + * 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. + */ + +configuratorModule.controller('clustersController', ['$scope', '$alert', '$http', 'commonFunctions', function ($scope, $alert, $http, commonFunctions) { + $scope.swapSimpleItems = commonFunctions.swapSimpleItems; + $scope.joinTip = commonFunctions.joinTip; + $scope.getModel = commonFunctions.getModel; + + $scope.templates = [ + {value: {}, label: 'blank'}, + {value: {discovery: {kind: 'Vm', Vm: {addresses: ['127.0.0.1:47500..47510']}}}, label: 'local'}, + {value: {discovery: {kind: 'Multicast', Multicast: {}}}, label: 'multicast'} + ]; + + $scope.discoveries = [ + {value: 'Vm', label: 'static IPs'}, + {value: 'Multicast', label: 'multicast'}, + {value: 'S3', label: 'AWS S3'}, + {value: 'Cloud', label: 'apache jclouds'}, + {value: 'GoogleStorage', label: 'google cloud storage'}, + {value: 'Jdbc', label: 'JDBC'}, + {value: 'SharedFs', label: 'shared filesystem'} + ]; + + $scope.swapSpaceSpis = [ + {value: 'FileSwapSpaceSpi', label: 'File-based swap'}, + {value: undefined, label: 'Not set'} + ]; + + $scope.events = []; + + for (var eventGroupName in eventGroups) { + if (eventGroups.hasOwnProperty(eventGroupName)) { + $scope.events.push({value: eventGroupName, label: eventGroupName}); + } + } + + $scope.cacheModes = [ + {value: 'LOCAL', label: 'LOCAL'}, + {value: 'REPLICATED', label: 'REPLICATED'}, + {value: 'PARTITIONED', label: 'PARTITIONED'} + ]; + + $scope.deploymentModes = [ + {value: 'PRIVATE', label: 'PRIVATE'}, + {value: 'ISOLATED', label: 'ISOLATED'}, + {value: 'SHARED', label: 'SHARED'}, + {value: 'CONTINUOUS', label: 'CONTINUOUS'} + ]; + + $scope.transactionConcurrency = [ + {value: 'OPTIMISTIC', label: 'OPTIMISTIC'}, + {value: 'PESSIMISTIC', label: 'PESSIMISTIC'} + ]; + + $scope.transactionIsolation = [ + {value: 'READ_COMMITTED', label: 'READ_COMMITTED'}, + {value: 'REPEATABLE_READ', label: 'REPEATABLE_READ'}, + {value: 'SERIALIZABLE', label: 'SERIALIZABLE'} + ]; + + $scope.segmentationPolicy = [ + {value: 'RESTART_JVM', label: 'RESTART_JVM'}, + {value: 'STOP', label: 'STOP'}, + {value: 'NOOP', label: 'NOOP'} + ]; + + $scope.marshallers = [ + {value: 'JdkMarshaller', label: 'JdkMarshaller'}, + {value: 'OptimizedMarshaller', label: 'OptimizedMarshaller'} + ]; + + $scope.clusters = []; + + $http.get('/form-models/clusters.json') + .success(function (data) { + $scope.templateTip = data.templateTip; + + $scope.general = data.general; + $scope.advanced = data.advanced; + }); + + // When landing on the page, get clusters and show them. + $http.get('/rest/clusters') + .success(function (data) { + $scope.caches = data.caches; + $scope.spaces = data.spaces; + $scope.clusters = data.clusters; + + var restoredItem = angular.fromJson(sessionStorage.clusterBackupItem); + + if (restoredItem) { + var idx = _.findIndex($scope.clusters, function (cluster) { + return cluster._id == restoredItem._id; + }); + + if (idx >= 0) + $scope.selectedItem = $scope.clusters[idx]; + + $scope.backupItem = restoredItem; + } + + $scope.$watch('backupItem', function (val) { + if (val) + sessionStorage.clusterBackupItem = angular.toJson(val); + }, true); + }); + + $scope.selectItem = function (item) { + $scope.selectedItem = item; + + $scope.backupItem = angular.copy(item); + }; + + // Add new cluster. + $scope.createItem = function () { + $scope.backupItem = angular.copy($scope.create.template); + + $scope.backupItem.space = $scope.spaces[0]._id; + }; + + // Save cluster in db. + $scope.saveItem = function () { + var item = $scope.backupItem; + + if (!item.swapSpaceSpi || !item.swapSpaceSpi.kind) { + for (var cacheId in item.caches) { + var idx = _.findIndex($scope.caches, function (cache) { + return cache._id == cacheId.value; + }); + + if (idx >= 0) { + var cache = $scope.caches[idx]; + + if (cache.swapEnabled) { + $alert({title: 'Swap space SPI is not configured, but cache "' + cache.label + '" configured to use swap!'}); + + return; + } + } + } + } + + $http.post('/rest/clusters/save', item) + .success(function (_id) { + var idx = _.findIndex($scope.clusters, function (cluster) { + return cluster._id == _id; + }); + + if (idx >= 0) + angular.extend($scope.clusters[idx], item); + else { + item._id = _id; + + $scope.clusters.push(item); + } + + $scope.selectItem(item); + + $alert({ + type: 'success', + title: 'Cluster "' + item.name + '" saved.', + duration: 2, + container: '#save-btn' + }); + }) + .error(function (errorMessage) { + $alert({title: errorMessage}); + }); + }; + + $scope.removeItem = function () { + var _id = $scope.selectedItem._id; + + $http.post('/rest/clusters/remove', {_id: _id}) + .success(function () { + var i = _.findIndex($scope.clusters, function (cluster) { + return cluster._id == _id; + }); + + if (i >= 0) { + $scope.clusters.splice(i, 1); + + $scope.selectedItem = undefined; + $scope.backupItem = undefined; + } + }) + .error(function (errorMessage) { + $alert({title: errorMessage}); + }); + }; + }] +); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8e792605/modules/web-control-center/nodejs/public/javascripts/controllers/common.js ---------------------------------------------------------------------- diff --git a/modules/web-control-center/nodejs/public/javascripts/controllers/common.js b/modules/web-control-center/nodejs/public/javascripts/controllers/common.js new file mode 100644 index 0000000..4d1e411 --- /dev/null +++ b/modules/web-control-center/nodejs/public/javascripts/controllers/common.js @@ -0,0 +1,169 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var configuratorModule = angular.module('ignite-web-configurator', ['smart-table', 'mgcrea.ngStrap', 'ngSanitize']); + +configuratorModule.service('commonFunctions', function () { + return { + getModel: function(obj, path) { + if (!path) + return obj; + + path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties + path = path.replace(/^\./, ''); // strip a leading dot + + var segs = path.split('.'); + var root = obj; + + while (segs.length > 0) { + var pathStep = segs.shift(); + + if (typeof root[pathStep] === 'undefined') + root[pathStep] = {}; + + root = root[pathStep]; + } + + return root; + }, + swapSimpleItems: function (a, ix1, ix2) { + var tmp = a[ix1]; + + a[ix1] = a[ix2]; + a[ix2] = tmp; + }, + joinTip: function(arr) { + if (!arr) { + return arr; + } + + var lines = arr.map(function (line) { + var rtrimmed = line.replace(/\s+$/g, ''); + + if (rtrimmed.indexOf('>', this.length - 1) == -1) { + rtrimmed = rtrimmed + '<br/>'; + } + + return rtrimmed; + }); + + return lines.join(""); + } + } +}); + +configuratorModule.config(function ($tooltipProvider) { + angular.extend($tooltipProvider.defaults, { + container: 'body', + placement: 'right', + html: 'true', + trigger: 'click hover' + //,delay: { hide: 600 } + }); +}); + +configuratorModule.config(function ($selectProvider) { + angular.extend($selectProvider.defaults, { + maxLength: '1', + allText: 'Select All', + noneText: 'Clear All', + template: '/select' + }); +}); + +// Alert settings +configuratorModule.config(function ($alertProvider) { + angular.extend($alertProvider.defaults, { + container: 'body', + placement: 'top-right', + duration: '5', + type: 'danger' + }); +}); + +// Decode name using map(value, label). +configuratorModule.filter('displayValue', function () { + return function (v, m, dflt) { + var i = _.findIndex(m, function (item) { + return item.value == v; + }); + + if (i >= 0) { + return m[i].label; + } + + if (dflt) { + return dflt; + } + + return 'Unknown value'; + } +}); + +/** + * Replaces all occurrences of {@code org.apache.ignite.} with {@code o.a.i.}, + * {@code org.apache.ignite.internal.} with {@code o.a.i.i.}, + * {@code org.apache.ignite.internal.visor.} with {@code o.a.i.i.v.} and + * {@code org.apache.ignite.scalar.} with {@code o.a.i.s.}. + * + * @param s String to replace in. + * @return Replaces string. + */ +configuratorModule.filter('compact', function () { + return function (s) { + return s.replace("org.apache.ignite.internal.visor.", "o.a.i.i.v."). + replace("org.apache.ignite.internal.", "o.a.i.i."). + replace("org.apache.ignite.scalar.", "o.a.i.s."). + replace("org.apache.ignite.", "o.a.i."); + } +}); + +configuratorModule.controller('activeLink', ['$scope', function ($scope) { + $scope.isActive = function (path) { + return window.location.pathname.substr(0, path.length) == path; + }; +}]); + +configuratorModule.controller('auth', ['$scope', '$modal', '$alert', '$http', '$window', function ($scope, $modal, $alert, $http, $window) { + $scope.action = 'login'; + + $scope.errorMessage = ''; + + $scope.valid = false; + + // Pre-fetch an external template populated with a custom scope + var authModal = $modal({scope: $scope, template: '/login', show: false}); + + $scope.login = function () { + // Show when some event occurs (use $promise property to ensure the template has been loaded) + authModal.$promise.then(authModal.show); + }; + + $scope.auth = function (action, user_info) { + $http.post('/rest/auth/' + action, user_info) + .success(function (data) { + authModal.hide(); + + $window.location = '/clusters'; + }) + .error(function (data) { + console.log(data); + + $alert({placement: 'top', container: '#errors-container', title: data}); + }); + }; +}]); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8e792605/modules/web-control-center/nodejs/public/javascripts/controllers/persistences.js ---------------------------------------------------------------------- diff --git a/modules/web-control-center/nodejs/public/javascripts/controllers/persistences.js b/modules/web-control-center/nodejs/public/javascripts/controllers/persistences.js new file mode 100644 index 0000000..10e3f8f --- /dev/null +++ b/modules/web-control-center/nodejs/public/javascripts/controllers/persistences.js @@ -0,0 +1,202 @@ +/* + * 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. + */ + +configuratorModule.controller('persistenceController', ['$scope', '$alert', '$http', 'commonFunctions', function ($scope, $alert, $http, commonFunctions) { + $scope.joinTip = commonFunctions.joinTip; + $scope.getModel = commonFunctions.getModel; + + $scope.databases = [ + {value: 'oracle', label: 'Oracle database'}, + {value: 'db2', label: 'IBM DB2'}, + {value: 'mssql', label: 'MS SQL Server'}, + {value: 'postgre', label: 'PostgreSQL'}, + {value: 'mysql', label: 'MySQL'}, + {value: 'h2', label: 'H2 database'} + ]; + + $scope.connection = []; + + $http.get('/form-models/persistence.json') + .success(function (data) { + $scope.connection = data.connection; + }); + + $scope.persistences = []; + + // When landing on the page, get persistences and show them. + $http.get('/rest/persistences') + .success(function (data) { + $scope.spaces = data.spaces; + $scope.persistences = data.persistences; + + var restoredItem = angular.fromJson(sessionStorage.persistenceBackupItem); + + if (restoredItem) { + var idx = _.findIndex($scope.persistences, function (persistence) { + return persistence._id == restoredItem._id; + }); + + if (idx >= 0) + $scope.selectedItem = $scope.persistences[idx]; + + $scope.backupItem = restoredItem; + } + + $scope.$watch('backupItem', function (val) { + if (val) + sessionStorage.persistenceBackupItem = angular.toJson(val); + }, true); + }); + + $scope.selectItem = function (item) { + $scope.selectedItem = item; + $scope.backupItem = angular.copy(item); + }; + + // Add new persistence. + $scope.createItem = function () { + $scope.backupItem = {database: 'oracle'}; + $scope.backupItem.space = $scope.spaces[0]._id; + }; + + // Save persistence in db. + $scope.saveItem = function () { + var item = $scope.backupItem; + + $http.post('/rest/persistences/save', item) + .success(function (_id) { + var i = _.findIndex($scope.persistences, function (persistence) { + return persistence._id == _id; + }); + + if (i >= 0) + angular.extend($scope.persistences[i], item); + else { + item._id = _id; + + $scope.persistences.push(item); + } + + $scope.selectItem(item); + }) + .error(function (errorMessage) { + $alert({title: errorMessage}); + }); + }; + + $scope.removeItem = function () { + var _id = $scope.selectedItem._id; + + $http.post('/rest/persistences/remove', {_id: _id}) + .success(function () { + var i = _.findIndex($scope.persistences, function (persistence) { + return persistence._id == _id; + }); + + if (i >= 0) { + $scope.persistences.splice(i, 1); + + $scope.selectedItem = undefined; + $scope.backupItem = undefined; + } + }) + .error(function (errorMessage) { + $alert({title: errorMessage}); + }); + }; + + $scope.data = { + curTableIdx: -1, + curFieldIdx: -1, + curKeyClass: '', + curValueClass: '', + curJavaName: '', + curJavaType: '', + tables: [ + {schemaName: 'Schema1', use: true}, + {schemaName: 'Schema1', use: true, tableName: 'Table1', keyClass: 'KeyClass1', valueClass: 'ValueClass1', + fields: [ + {use: true, key: true, ak: true, dbName: 'name1', dbType: 'dbType1', javaName: 'javaName1', javaType: 'javaType1'}, + {use: true, key: false, ak: false, dbName: 'name2', dbType: 'dbType2', javaName: 'javaName2', javaType: 'javaType2'}, + {use: false, key: false, ak: false, dbName: 'name3', dbType: 'dbType3', javaName: 'javaName3', javaType: 'javaType3'} + ] + }, + {schemaName: 'Schema2 with very long name', use: false}, + {schemaName: 'Schema2', use: false, tableName: 'Table2', keyClass: 'KeyClass2', valueClass: 'ValueClass2', + fields: [ + {use: true, key: true, ak: true, dbName: 'name4', dbType: 'dbType4', javaName: 'javaName4', javaType: 'javaType4'}, + {use: true, key: false, ak: false, dbName: 'name5', dbType: 'dbType5', javaName: 'javaName5', javaType: 'javaType5'}, + {use: false, key: false, ak: false, dbName: 'name6', dbType: 'dbType6', javaName: 'javaName6', javaType: 'javaType6'} + ]}, + {schemaName: 'Schema2', use: false, tableName: 'Table3', keyClass: 'KeyClass3', valueClass: 'ValueClass3', + fields: [ + {use: true, key: true, ak: true, dbName: 'name7', dbType: 'dbType7', javaName: 'javaName7', javaType: 'javaType7'}, + {use: true, key: false, ak: false, dbName: 'name8', dbType: 'dbType8', javaName: 'javaName8', javaType: 'javaType8'}, + {use: false, key: false, ak: false, dbName: 'name9', dbType: 'dbType9', javaName: 'javaName9', javaType: 'javaType9'}, + {use: false, key: false, ak: false, dbName: 'name10', dbType: 'dbType10', javaName: 'javaName10', javaType: 'javaType10'}, + {use: false, key: false, ak: false, dbName: 'name11', dbType: 'dbType11', javaName: 'javaName11', javaType: 'javaType11'}, + {use: false, key: false, ak: false, dbName: 'name12', dbType: 'dbType12', javaName: 'javaName12', javaType: 'javaType12'} + ]}] + }; + + $scope.selectSchema = function (idx) { + var data = $scope.data; + var tables = data.tables; + var schemaName = tables[idx].schemaName; + var use = tables[idx].use; + + for (var i = idx + 1; i < tables.length; i++) { + var item = tables[i]; + + if (item.schemaName == schemaName && item.tableName) + item.use = use; + else + break; + } + + data.curTableIdx = -1; + data.curFieldIdx = -1; + }; + + $scope.selectTable = function (idx) { + var data = $scope.data; + + data.curTableIdx = idx; + data.curFieldIdx = -1; + + if (idx >= 0) { + var tbl = data.tables[idx]; + + data.curKeyClass = tbl.keyClass; + data.curValueClass = tbl.valueClass; + } + }; + + $scope.selectField = function (idx) { + var data = $scope.data; + + data.curFieldIdx = idx; + + if (idx >= 0) { + var fld = data.tables[data.curTableIdx].fields[idx]; + + data.curJavaName = fld.javaName; + data.curJavaType = fld.javaType; + } + }; + }] +); http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8e792605/modules/web-control-center/nodejs/public/javascripts/controllers/summary.js ---------------------------------------------------------------------- diff --git a/modules/web-control-center/nodejs/public/javascripts/controllers/summary.js b/modules/web-control-center/nodejs/public/javascripts/controllers/summary.js new file mode 100644 index 0000000..53cac48 --- /dev/null +++ b/modules/web-control-center/nodejs/public/javascripts/controllers/summary.js @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +configuratorModule.controller('summaryController', ['$scope', '$http', function ($scope, $http) { + $http.get('/rest/clusters').success(function (data) { + $scope.caches = data.caches; + $scope.spaces = data.spaces; + $scope.clusters = data.clusters; + }); + + $scope.selectItem = function (item) { + $scope.selectedItem = item; + + $scope.generateConfig() + }; + + $scope.generateConfig = function() { + var lang = $scope.cfgLang; + + if (lang == 'docker') + return; + + var cluster = $scope.selectedItem; + + if (!cluster) + return; + + $scope.loading = true; + + $http.get('/rest/configGenerator', {params: + {name: cluster.name, lang: lang, generateJavaClass: $scope.generateJavaClass}}) + .success( + function (data) { + if (lang == 'java') { + $("<pre class='brush:java' />").text(data).appendTo($('#javaResultDiv').empty()); + } + else if (lang == 'xml') { + $("<pre class='brush:xml' />").text(data).appendTo($('#xmlResultDiv').empty()); + } + + SyntaxHighlighter.highlight(); + + $scope.loading = false; + }).error(function (data) { + $scope.generateError = "Failed to generate config: " + data; + + $scope.loading = false; + }); + }; + + $scope.cfgLang = 'xml'; + + $scope.$watch('cfgLang', $scope.generateConfig); + $scope.$watch('generateJavaClass', $scope.generateConfig); + + $scope.dockerArg = {}; + + $scope.downloadDocker = function() { + var dockerText = $scope.dockerFile(); + + if (dockerText.length == 0) + return; + + var pom = document.createElement('a'); + pom.setAttribute('href', 'data:application/octet-stream;charset=utf-8,' + encodeURIComponent(dockerText)); + pom.setAttribute('download', 'Dockerfile'); + + pom.style.display = 'none'; + document.body.appendChild(pom); + + pom.click(); + + document.body.removeChild(pom); + }; + + $scope.dockerFile = function() { + if (!$scope.selectedItem || !$scope.dockerArg) { + return ''; + } + + var os = $scope.dockerArg.os; + if (!os) { + os = 'debian:8' + } + + return "" + + "# Start from a Debian image.\n"+ + "FROM " + os + "\n"+ + "\n"+ + "# Install tools.\n"+ + "RUN apt-get update && apt-get install -y --fix-missing \\\n"+ + " wget \\\n"+ + " dstat \\\n"+ + " maven \\\n"+ + " git\n"+ + "\n"+ + "# Intasll Oracle JDK.\n"+ + "RUN mkdir /opt/jdk\n"+ + "\n"+ + "RUN wget --header \"Cookie: oraclelicense=accept-securebackup-cookie\" \\\n"+ + " http://download.oracle.com/otn-pub/java/jdk/7u79-b15/jdk-7u79-linux-x64.tar.gz\n"+ + "\n"+ + "RUN tar -zxf jdk-7u79-linux-x64.tar.gz -C /opt/jdk\n"+ + "\n"+ + "RUN rm jdk-7u79-linux-x64.tar.gz\n"+ + "\n"+ + "RUN update-alternatives --install /usr/bin/java java /opt/jdk/jdk1.7.0_79/bin/java 100\n"+ + "\n"+ + "RUN update-alternatives --install /usr/bin/javac javac /opt/jdk/jdk1.7.0_79/bin/javac 100\n"+ + "\n"+ + "# Sets java variables.\n"+ + "ENV JAVA_HOME /opt/jdk/jdk1.7.0_79/\n"+ + "\n"+ + "# Create working directory\n"+ + "WORKDIR /home\n"+ + "\n"+ + "RUN wget -O ignite.zip http://tiny.cc/updater/download_ignite.php && unzip ignite.zip && rm ignite.zip\n"+ + "\n"+ + "COPY *.xml /tmp/\n"+ + "\n"+ + "RUN mv /tmp/*.xml /home/$(ls)/config"; + }; +}]); http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8e792605/modules/web-control-center/nodejs/public/javascripts/dataStructures.js ---------------------------------------------------------------------- diff --git a/modules/web-control-center/nodejs/public/javascripts/dataStructures.js b/modules/web-control-center/nodejs/public/javascripts/dataStructures.js new file mode 100644 index 0000000..2462708 --- /dev/null +++ b/modules/web-control-center/nodejs/public/javascripts/dataStructures.js @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +eventGroups = { + EVTS_CHECKPOINT: ['EVT_CHECKPOINT_SAVED', 'EVT_CHECKPOINT_LOADED', 'EVT_CHECKPOINT_REMOVED'], + EVTS_DEPLOYMENT: ['EVT_CLASS_DEPLOYED', 'EVT_CLASS_UNDEPLOYED', 'EVT_CLASS_DEPLOY_FAILED', 'EVT_TASK_DEPLOYED', + 'EVT_TASK_UNDEPLOYED', 'EVT_TASK_DEPLOY_FAILED'], + EVTS_ERROR: ['EVT_JOB_TIMEDOUT', 'EVT_JOB_FAILED', 'EVT_JOB_FAILED_OVER', 'EVT_JOB_REJECTED', 'EVT_JOB_CANCELLED', + 'EVT_TASK_TIMEDOUT', 'EVT_TASK_FAILED', 'EVT_CLASS_DEPLOY_FAILED', 'EVT_TASK_DEPLOY_FAILED', + 'EVT_TASK_DEPLOYED', 'EVT_TASK_UNDEPLOYED', 'EVT_CACHE_REBALANCE_STARTED', 'EVT_CACHE_REBALANCE_STOPPED'], + EVTS_DISCOVERY: ['EVT_NODE_JOINED', 'EVT_NODE_LEFT', 'EVT_NODE_FAILED', 'EVT_NODE_SEGMENTED', + 'EVT_CLIENT_NODE_DISCONNECTED', 'EVT_CLIENT_NODE_RECONNECTED'], + EVTS_JOB_EXECUTION: ['EVT_JOB_MAPPED', 'EVT_JOB_RESULTED', 'EVT_JOB_FAILED_OVER', 'EVT_JOB_STARTED', + 'EVT_JOB_FINISHED', 'EVT_JOB_TIMEDOUT', 'EVT_JOB_REJECTED', 'EVT_JOB_FAILED', 'EVT_JOB_QUEUED', + 'EVT_JOB_CANCELLED'], + EVTS_TASK_EXECUTION: ['EVT_TASK_STARTED', 'EVT_TASK_FINISHED', 'EVT_TASK_FAILED', 'EVT_TASK_TIMEDOUT', + 'EVT_TASK_SESSION_ATTR_SET', 'EVT_TASK_REDUCED'], + EVTS_CACHE: ['EVT_CACHE_ENTRY_CREATED', 'EVT_CACHE_ENTRY_DESTROYED', 'EVT_CACHE_OBJECT_PUT', + 'EVT_CACHE_OBJECT_READ', 'EVT_CACHE_OBJECT_REMOVED', 'EVT_CACHE_OBJECT_LOCKED', 'EVT_CACHE_OBJECT_UNLOCKED', + 'EVT_CACHE_OBJECT_SWAPPED', 'EVT_CACHE_OBJECT_UNSWAPPED', 'EVT_CACHE_OBJECT_EXPIRED'], + EVTS_CACHE_REBALANCE: ['EVT_CACHE_REBALANCE_STARTED', 'EVT_CACHE_REBALANCE_STOPPED', + 'EVT_CACHE_REBALANCE_PART_LOADED', 'EVT_CACHE_REBALANCE_PART_UNLOADED', 'EVT_CACHE_REBALANCE_OBJECT_LOADED', + 'EVT_CACHE_REBALANCE_OBJECT_UNLOADED', 'EVT_CACHE_REBALANCE_PART_DATA_LOST'], + EVTS_CACHE_LIFECYCLE: ['EVT_CACHE_STARTED', 'EVT_CACHE_STOPPED', 'EVT_CACHE_NODES_LEFT'], + EVTS_CACHE_QUERY: ['EVT_CACHE_QUERY_EXECUTED', 'EVT_CACHE_QUERY_OBJECT_READ'], + EVTS_SWAPSPACE: ['EVT_SWAP_SPACE_CLEARED', 'EVT_SWAP_SPACE_DATA_REMOVED', 'EVT_SWAP_SPACE_DATA_READ', + 'EVT_SWAP_SPACE_DATA_STORED', 'EVT_SWAP_SPACE_DATA_EVICTED'], + EVTS_IGFS: ['EVT_IGFS_FILE_CREATED', 'EVT_IGFS_FILE_RENAMED', 'EVT_IGFS_FILE_DELETED', 'EVT_IGFS_FILE_OPENED_READ', + 'EVT_IGFS_FILE_OPENED_WRITE', 'EVT_IGFS_FILE_CLOSED_WRITE', 'EVT_IGFS_FILE_CLOSED_READ', 'EVT_IGFS_FILE_PURGED', + 'EVT_IGFS_META_UPDATED', 'EVT_IGFS_DIR_CREATED', 'EVT_IGFS_DIR_RENAMED', 'EVT_IGFS_DIR_DELETED'] +}; + +jdbcTypes = { + BIT: {value: "BIT", code: -7, label: "BIT"}, + TINYINT: {value: "TINYINT", code: -6, label: "TINYINT"}, + SMALLINT: {value: "SMALLINT", code: 5, label: "SMALLINT"}, + INTEGER: {value: "INTEGER", code: 4, label: "INTEGER"}, + BIGINT: {value: "BIGINT", code: -5, label: "BIGINT"}, + FLOAT: {value: "FLOAT", code: 6, label: "FLOAT"}, + REAL: {value: "REAL", code: 7, label: "REAL"}, + DOUBLE: {value: "DOUBLE", code: 8, label: "DOUBLE"}, + NUMERIC: {value: "NUMERIC", code: 2, label: "NUMERIC"}, + DECIMAL: {value: "DECIMAL", code: 3, label: "DECIMAL"}, + CHAR: {value: "CHAR", code: 1, label: "CHAR"}, + VARCHAR: {value: "VARCHAR", code: 12, label: "VARCHAR"}, + DATE: {value: "DATE", code: 91, label: "DATE"}, + TIME: {value: "TIME", code: 92, label: "TIME"}, + TIMESTAMP: {value: "TIMESTAMP", code: 93, label: "TIMESTAMP"}, + BINARY: {value: "BINARY", code: -2, label: "BINARY"} +}; + +javaTypes = { + INTEGER: {value: "java.lang.Integer", label: "Integer"}, + LONG: {value: "java.lang.Long", label: "Long"}, + BIGDECIMAL: {value: "java.math.BigDecimal", label: "BigDecimal"}, + FLOAT: {value: "java.lang.Float", label: "Float"}, + DOUBLE: {value: "java.lang.Double", label: "Double"}, + STRING: {value: "java.lang.String", label: "String"}, + BOOLEAN: {value: "java.lang.Boolean", label: "Boolean"}, + BYTE_ARRAY: {value: "byte[]", label: "byte[]"}, + DATE: {value: "java.sql.Date", label: "Date"}, + TIME: {value: "java.sql.Time", label: "Time"}, + TIMESTAMP: {value: "java.sql.Timestamp", label: "Timestamp"} +}; + +if (typeof window === 'undefined') { + exports.eventGroups = eventGroups; + exports.jdbcTypes = jdbcTypes; + exports.javaTypes = javaTypes; +}