From a053d6762a8e1151c55bbd489541f60ba3be7755 Mon Sep 17 00:00:00 2001 From: BaiHuoYu Date: Wed, 7 Nov 2018 10:35:57 +0800 Subject: [PATCH 01/20] FC --- contrib/connector/common.go | 147 +++++++++++++++++++++++++++ contrib/connector/connector.go | 1 + contrib/connector/fc/fc.go | 9 ++ contrib/connector/fc/fibreChannel.go | 21 ++++ contrib/connector/iscsi/helper.go | 134 ++++-------------------- contrib/connector/iscsi/iscsi.go | 6 ++ contrib/connector/rbd/rbd.go | 5 + 7 files changed, 208 insertions(+), 115 deletions(-) create mode 100644 contrib/connector/common.go diff --git a/contrib/connector/common.go b/contrib/connector/common.go new file mode 100644 index 000000000..eb40d1d56 --- /dev/null +++ b/contrib/connector/common.go @@ -0,0 +1,147 @@ +// Copyright (c) 2018 Huawei Technologies Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package connector + +import ( + "log" + "net" + "os/exec" + "strings" +) + +// execCmd ... +func ExecCmd(name string, arg ...string) (string, error) { + log.Printf("Command: %s %s:\n", name, strings.Join(arg, " ")) + info, err := exec.Command(name, arg...).CombinedOutput() + return string(info), err +} + +// GetFSType returns the File System Type of device +func GetFSType(device string) string { + fsType := "" + res, err := ExecCmd("blkid", device) + if err != nil { + log.Printf("failed to GetFSType: %v", err) + return fsType + } + + if strings.Contains(string(res), "TYPE=") { + for _, v := range strings.Split(string(res), " ") { + if strings.Contains(v, "TYPE=") { + fsType = strings.Split(v, "=")[1] + fsType = strings.Replace(fsType, "\"", "", -1) + } + } + } + return fsType +} + +// Format device by File System Type +func Format(device string, fstype string) error { + log.Printf("Format device: %s fstype: %s", device, fstype) + + // Get current File System Type + curFSType := GetFSType(device) + if curFSType == "" { + // Default File Sysem Type is ext4 + if fstype == "" { + fstype = "ext4" + } + _, err := ExecCmd("mkfs", "-t", fstype, "-F", device) + if err != nil { + log.Printf("failed to Format: %v", err) + return err + } + } else { + log.Printf("Device: %s has been formatted yet. fsType: %s", device, curFSType) + } + return nil +} + +// Mount device into mount point +func Mount(device string, mountpoint string) error { + log.Printf("Mount device: %s mountpoint: %s", device, mountpoint) + + _, err := ExecCmd("mkdir", "-p", mountpoint) + if err != nil { + log.Printf("failed to mkdir: %v", err) + } + _, err = ExecCmd("mount", device, mountpoint) + if err != nil { + log.Printf("failed to mount: %v", err) + return err + } + return nil +} + +// FormatAndMount device +func FormatAndMount(device string, fstype string, mountpoint string) error { + log.Printf("FormatandMount device: %s fstype: %s mountpoint: %s", device, fstype, mountpoint) + + // Format + err := Format(device, fstype) + if err != nil { + return err + } + + // Mount + err = Mount(device, mountpoint) + if err != nil { + return err + } + + return nil +} + +// Umount from mountpoint +func Umount(mountpoint string) error { + log.Printf("Umount mountpoint: %s", mountpoint) + + _, err := ExecCmd("umount", mountpoint) + if err != nil { + log.Printf("failed to Umount: %v", err) + return err + } + return nil +} + +// GetHostIp return Host IP +func GetHostIp() string { + addrs, err := net.InterfaceAddrs() + if err != nil { + return "127.0.0.1" + } + + for _, address := range addrs { + if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { + return ipnet.IP.String() + } + } + + return "127.0.0.1" +} + +// GetHostName return Host Name +func GetHostName() (string, error) { + hostName, err := ExecCmd("hostname") + if err != nil { + log.Printf("failed to get host name: %v", err) + return "", err + } + + hostName = strings.Replace(hostName, "\n", "", -1) + + return hostName, nil +} diff --git a/contrib/connector/connector.go b/contrib/connector/connector.go index 363d741b4..65a1829b3 100644 --- a/contrib/connector/connector.go +++ b/contrib/connector/connector.go @@ -21,6 +21,7 @@ import ( type Connector interface { Attach(map[string]interface{}) (string, error) Detach(map[string]interface{}) error + GetInitiatorInfo() (string, error) } func NewConnector(cType string) Connector { diff --git a/contrib/connector/fc/fc.go b/contrib/connector/fc/fc.go index ca5c46d49..55a4c58e1 100644 --- a/contrib/connector/fc/fc.go +++ b/contrib/connector/fc/fc.go @@ -20,6 +20,10 @@ import ( const ( fcDriver = "fibre_channel" + PortName = "port_name" + NodeName = "node_name" + Wwpn = "wwpn" + Wwnn = "wwnn" ) type FC struct { @@ -46,3 +50,8 @@ func (f *FC) Attach(conn map[string]interface{}) (string, error) { func (f *FC) Detach(conn map[string]interface{}) error { return f.self.disconnectVolume(conn) } + +// GetInitiatorInfo implementation +func (f *FC) GetInitiatorInfo() (string, error) { + return f.self.getInitiatorInfo() +} diff --git a/contrib/connector/fc/fibreChannel.go b/contrib/connector/fc/fibreChannel.go index fb87c714b..3d8050894 100644 --- a/contrib/connector/fc/fibreChannel.go +++ b/contrib/connector/fc/fibreChannel.go @@ -215,3 +215,24 @@ func (f *fibreChannel) getFChbasInfo() ([]map[string]string, error) { return hbasInfos, nil } + +func (f *fibreChannel) getInitiatorInfo() (string, error) { + hbas, err := f.getFChbasInfo() + if err != nil { + return "", err + } + + var initiatorInfo []string + + for _, hba := range hbas { + if v, ok := hba[PortName]; ok { + initiatorInfo = append(initiatorInfo, Wwpn+":"+v) + } + + if v, ok := hba[NodeName]; ok { + initiatorInfo = append(initiatorInfo, Wwnn+":"+v) + } + } + + return strings.Join(initiatorInfo, ","), nil +} diff --git a/contrib/connector/iscsi/helper.go b/contrib/connector/iscsi/helper.go index 0262d61a5..093e504ba 100644 --- a/contrib/connector/iscsi/helper.go +++ b/contrib/connector/iscsi/helper.go @@ -17,15 +17,16 @@ package iscsi import ( "errors" "log" - "net" + "os" - "os/exec" + "path/filepath" "strconv" "strings" "time" "github.com/mitchellh/mapstructure" + "github.com/opensds/opensds/contrib/connector" ) // IscsiConnectorInfo define @@ -101,7 +102,7 @@ func waitForPathToExistInternal(devicePath *string, maxRetries int, deviceTransp // GetInitiator returns all the ISCSI Initiator Name func GetInitiator() ([]string, error) { - res, err := execCmd("cat", "/etc/iscsi/initiatorname.iscsi") + res, err := connector.ExecCmd("cat", "/etc/iscsi/initiatorname.iscsi") iqns := []string{} if err != nil { log.Printf("Error encountered gathering initiator names: %v", err) @@ -122,14 +123,14 @@ func GetInitiator() ([]string, error) { // Login ISCSI Target func SetAuth(portal string, targetiqn string, name string, passwd string) error { // Set UserName - info, err := execCmd("iscsiadm", "-m", "node", "-p", portal, "-T", targetiqn, + info, err := connector.ExecCmd("iscsiadm", "-m", "node", "-p", portal, "-T", targetiqn, "--op=update", "--name", "node.session.auth.username", "--value", name) if err != nil { log.Fatalf("Received error on set income username: %v, %v", err, info) return err } // Set Password - info, err = execCmd("iscsiadm", "-m", "node", "-p", portal, "-T", targetiqn, + info, err = connector.ExecCmd("iscsiadm", "-m", "node", "-p", portal, "-T", targetiqn, "--op=update", "--name", "node.session.auth.password", "--value", passwd) if err != nil { log.Fatalf("Received error on set income password: %v, %v", err, info) @@ -140,7 +141,7 @@ func SetAuth(portal string, targetiqn string, name string, passwd string) error // Discovery ISCSI Target func Discovery(portal string) error { - info, err := execCmd("iscsiadm", "-m", "discovery", "-t", "sendtargets", "-p", portal) + info, err := connector.ExecCmd("iscsiadm", "-m", "discovery", "-t", "sendtargets", "-p", portal) if err != nil { log.Println("Error encountered in sendtargets:", string(info), err) return err @@ -150,7 +151,7 @@ func Discovery(portal string) error { // Login ISCSI Target func Login(portal string, targetiqn string) error { - info, err := execCmd("iscsiadm", "-m", "node", "-p", portal, "-T", targetiqn, "--login") + info, err := connector.ExecCmd("iscsiadm", "-m", "node", "-p", portal, "-T", targetiqn, "--login") if err != nil { log.Println("Received error on login attempt:", string(info), err) return err @@ -160,7 +161,7 @@ func Login(portal string, targetiqn string) error { // Logout ISCSI Target func Logout(portal string, targetiqn string) error { - info, err := execCmd("iscsiadm", "-m", "node", "-p", portal, "-T", targetiqn, "--logout") + info, err := connector.ExecCmd("iscsiadm", "-m", "node", "-p", portal, "-T", targetiqn, "--logout") if err != nil { log.Println("Received error on logout attempt:", string(info), err) return err @@ -170,7 +171,7 @@ func Logout(portal string, targetiqn string) error { // Delete ISCSI Node func Delete(targetiqn string) error { - info, err := execCmd("iscsiadm", "-m", "node", "-o", "delete", "-T", targetiqn) + info, err := connector.ExecCmd("iscsiadm", "-m", "node", "-o", "delete", "-T", targetiqn) if err != nil { log.Println("Received error on Delete attempt:", string(info), err) return err @@ -221,7 +222,7 @@ func Connect(connMap map[string]interface{}) (string, error) { } func sessionExists(portal string, tgtIqn string) bool { - info, err := execCmd("iscsiadm", "-m", "session", "-s") + info, err := connector.ExecCmd("iscsiadm", "-m", "session", "-s") if err != nil { log.Println("Warning: get session failed,", string(info)) return false @@ -236,7 +237,7 @@ func sessionExists(portal string, tgtIqn string) bool { } func recordExists(portal string, tgtIqn string) bool { - _, err := execCmd("iscsiadm", "-m", "node", "-o", "show", + _, err := connector.ExecCmd("iscsiadm", "-m", "node", "-o", "show", "-T", tgtIqn, "-p", portal) return err == nil } @@ -256,95 +257,6 @@ func Disconnect(portal string, targetiqn string) error { return nil } -// GetFSType returns the File System Type of device -func GetFSType(device string) string { - fsType := "" - res, err := execCmd("blkid", device) - if err != nil { - log.Printf("failed to GetFSType: %v", err) - return fsType - } - - if strings.Contains(string(res), "TYPE=") { - for _, v := range strings.Split(string(res), " ") { - if strings.Contains(v, "TYPE=") { - fsType = strings.Split(v, "=")[1] - fsType = strings.Replace(fsType, "\"", "", -1) - } - } - } - return fsType -} - -// Format device by File System Type -func Format(device string, fstype string) error { - log.Printf("Format device: %s fstype: %s", device, fstype) - - // Get current File System Type - curFSType := GetFSType(device) - if curFSType == "" { - // Default File Sysem Type is ext4 - if fstype == "" { - fstype = "ext4" - } - _, err := execCmd("mkfs", "-t", fstype, "-F", device) - if err != nil { - log.Printf("failed to Format: %v", err) - return err - } - } else { - log.Printf("Device: %s has been formatted yet. fsType: %s", device, curFSType) - } - return nil -} - -// Mount device into mount point -func Mount(device string, mountpoint string) error { - log.Printf("Mount device: %s mountpoint: %s", device, mountpoint) - - _, err := execCmd("mkdir", "-p", mountpoint) - if err != nil { - log.Printf("failed to mkdir: %v", err) - } - _, err = execCmd("mount", device, mountpoint) - if err != nil { - log.Printf("failed to mount: %v", err) - return err - } - return nil -} - -// FormatAndMount device -func FormatAndMount(device string, fstype string, mountpoint string) error { - log.Printf("FormatandMount device: %s fstype: %s mountpoint: %s", device, fstype, mountpoint) - - // Format - err := Format(device, fstype) - if err != nil { - return err - } - - // Mount - err = Mount(device, mountpoint) - if err != nil { - return err - } - - return nil -} - -// Umount from mountpoint -func Umount(mountpoint string) error { - log.Printf("Umount mountpoint: %s", mountpoint) - - _, err := execCmd("umount", mountpoint) - if err != nil { - log.Printf("failed to Umount: %v", err) - return err - } - return nil -} - // ParseIscsiConnectInfo decode func ParseIscsiConnectInfo(connectInfo map[string]interface{}) *IscsiConnectorInfo { var con IscsiConnectorInfo @@ -352,24 +264,16 @@ func ParseIscsiConnectInfo(connectInfo map[string]interface{}) *IscsiConnectorIn return &con } -// GetHostIp return Host IP -func GetHostIp() string { - addrs, err := net.InterfaceAddrs() +// getInitiatorInfo implementation +func getInitiatorInfo() (string, error) { + initiators, err := GetInitiator() if err != nil { - return "127.0.0.1" + return "", err } - for _, address := range addrs { - if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { - return ipnet.IP.String() - } + if len(initiators) == 0 { + return "", errors.New("The number of iqn is wrong") } - return "127.0.0.1" -} - -func execCmd(name string, arg ...string) (string, error) { - log.Printf("Command: %s %s:\n", name, strings.Join(arg, " ")) - info, err := exec.Command(name, arg...).CombinedOutput() - return string(info), err + return initiators[0], nil } diff --git a/contrib/connector/iscsi/iscsi.go b/contrib/connector/iscsi/iscsi.go index bae2faf73..eefec1f6b 100644 --- a/contrib/connector/iscsi/iscsi.go +++ b/contrib/connector/iscsi/iscsi.go @@ -20,6 +20,7 @@ import ( const ( iscsiDriver = "iscsi" + Iqn = "iqn" ) type Iscsi struct{} @@ -37,3 +38,8 @@ func (isc *Iscsi) Detach(conn map[string]interface{}) error { return Disconnect(iscsiCon.TgtPortal, iscsiCon.TgtIQN) } + +// GetInitiatorInfo implementation +func (isc *Iscsi) GetInitiatorInfo() (string, error) { + return getInitiatorInfo() +} diff --git a/contrib/connector/rbd/rbd.go b/contrib/connector/rbd/rbd.go index d37089698..05a78a204 100644 --- a/contrib/connector/rbd/rbd.go +++ b/contrib/connector/rbd/rbd.go @@ -96,6 +96,11 @@ func (*RBD) Detach(conn map[string]interface{}) error { return err } +// GetInitiatorInfo implementation +func (*RBD) GetInitiatorInfo() (string, error) { + return "", nil +} + func mapDevice(poolName, imageName string, hosts, ports []interface{}) (string, error) { devName, err := findDevice(poolName, imageName, 1) if err == nil { From 97e8b7fc8ec1a19d58e355060c4fe6381c4eec9f Mon Sep 17 00:00:00 2001 From: BaiHuoYu Date: Wed, 7 Nov 2018 13:54:13 +0800 Subject: [PATCH 02/20] FC --- pkg/dock/discovery/discovery.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/dock/discovery/discovery.go b/pkg/dock/discovery/discovery.go index 485eaecd0..b3708db71 100755 --- a/pkg/dock/discovery/discovery.go +++ b/pkg/dock/discovery/discovery.go @@ -23,10 +23,11 @@ import ( "fmt" "os" "runtime" - "time" "strings" + "time" log "github.com/golang/glog" + "github.com/opensds/opensds/contrib/connector" "github.com/opensds/opensds/contrib/connector/fc" "github.com/opensds/opensds/contrib/connector/iscsi" "github.com/opensds/opensds/contrib/drivers" @@ -214,7 +215,7 @@ func (add *attachDockDiscoverer) Discover() error { bindIp := CONF.BindIp if bindIp == "" { - bindIp = iscsi.GetHostIp() + bindIp = connector.GetHostIp() } wwpns, _ := fc.GetWWPNs() segments := strings.Split(CONF.OsdsDock.ApiEndpoint, ":") From 82ffc2798c2b8f2a92fcd60b7c42f43bbaebdb3a Mon Sep 17 00:00:00 2001 From: jerry Date: Mon, 12 Nov 2018 17:10:40 +0800 Subject: [PATCH 03/20] Fixed syntax error --- script/devsds/lib/keystone.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/script/devsds/lib/keystone.sh b/script/devsds/lib/keystone.sh index c722f5265..16536e997 100644 --- a/script/devsds/lib/keystone.sh +++ b/script/devsds/lib/keystone.sh @@ -127,7 +127,7 @@ osds::keystone::download_code(){ } osds::keystone::install(){ - if [ "true" != $USE_EXISTING_KEYSTONE] + if [ "true" != $USE_EXISTING_KEYSTONE ] then KEYSTONE_IP=$HOST_IP osds::keystone::create_user @@ -169,4 +169,4 @@ osds::keystone::uninstall_purge(){ } ## Restore xtrace -$_XTRACE_KEYSTONE \ No newline at end of file +$_XTRACE_KEYSTONE From 4ba7e2cabb6d3bfbdabbe1b60ed9c789af36ec84 Mon Sep 17 00:00:00 2001 From: jerry Date: Tue, 13 Nov 2018 10:25:55 +0800 Subject: [PATCH 04/20] Fixed get fs parsing bug --- contrib/connector/iscsi/helper.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contrib/connector/iscsi/helper.go b/contrib/connector/iscsi/helper.go index 0262d61a5..6fbbf9916 100644 --- a/contrib/connector/iscsi/helper.go +++ b/contrib/connector/iscsi/helper.go @@ -269,7 +269,8 @@ func GetFSType(device string) string { for _, v := range strings.Split(string(res), " ") { if strings.Contains(v, "TYPE=") { fsType = strings.Split(v, "=")[1] - fsType = strings.Replace(fsType, "\"", "", -1) + fsType = strings.TrimSpace(fsType) + fsType = strings.Trim(fsType, "\"") } } } From 81299c056e3e5f068eaf9e11b62c733914e20f25 Mon Sep 17 00:00:00 2001 From: jerry Date: Tue, 13 Nov 2018 10:57:13 +0800 Subject: [PATCH 05/20] Add deleting uploaded snapshot --- contrib/backup/multicloud/client.go | 2 +- contrib/backup/multicloud/driver.go | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/contrib/backup/multicloud/client.go b/contrib/backup/multicloud/client.go index 8119d29ec..9c4b4c816 100644 --- a/contrib/backup/multicloud/client.go +++ b/contrib/backup/multicloud/client.go @@ -101,7 +101,7 @@ func (c *Client) doRequest(method, u string, in interface{}, cb ReqSettingCB) ([ return nil, nil, err } - log.Errorf("%s: %s OK\n", method, u) + log.V(5).Infof("%s: %s OK\n", method, u) b, err := req.Bytes() if err != nil { log.Errorf("Get byte[] from response failed, method: %s\n url: %s\n error: %v", method, u, err) diff --git a/contrib/backup/multicloud/driver.go b/contrib/backup/multicloud/driver.go index 409e1cb52..3d0d9982f 100644 --- a/contrib/backup/multicloud/driver.go +++ b/contrib/backup/multicloud/driver.go @@ -137,5 +137,7 @@ func (m *MultiCloud) Restore(backup *backup.BackupSpec, volId string, volFile *o } func (m *MultiCloud) Delete(backup *backup.BackupSpec) error { - return nil + bucket := backup.Metadata["bucket"] + key := backup.Id + return m.client.RemoveObject(bucket, key) } From 7cc18cc8e49f84bebf25fb1d70963d834121e324 Mon Sep 17 00:00:00 2001 From: jerry Date: Tue, 13 Nov 2018 11:16:18 +0800 Subject: [PATCH 06/20] Make client request timeout a little bit longer --- client/receiver.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/receiver.go b/client/receiver.go index f14f40988..e24b74e35 100755 --- a/client/receiver.go +++ b/client/receiver.go @@ -20,6 +20,7 @@ import ( "io/ioutil" "net/http" "strings" + "time" "github.com/astaxie/beego/httplib" "github.com/gophercloud/gophercloud" @@ -67,6 +68,8 @@ func NewReceiver() Receiver { func request(url string, method string, headers HeaderOption, input interface{}, output interface{}) error { req := httplib.NewBeegoRequest(url, strings.ToUpper(method)) + // Set the request timeout a little bit longer upload snapshot to cloud temporarily. + req.SetTimeout(time.Minute*6, time.Minute*6) // init body if input != nil { req.JSONBody(input) From d23ca291b11d6894d3c3f4e9439d86063c32c0fb Mon Sep 17 00:00:00 2001 From: PengYiOfOpenSDS Date: Wed, 14 Nov 2018 10:23:10 +0800 Subject: [PATCH 07/20] CSI-Plugin support FC protocol --- contrib/connector/common.go | 11 ++++++++-- contrib/connector/connector.go | 10 ++++++++-- contrib/connector/fc/fc.go | 2 +- contrib/connector/fc/fibreChannel.go | 30 ++++++++++++++++++++++------ contrib/connector/iscsi/helper.go | 24 ++++++++++++++++------ contrib/connector/iscsi/iscsi.go | 4 ++-- contrib/connector/rbd/rbd.go | 13 ++++++++++-- 7 files changed, 73 insertions(+), 21 deletions(-) diff --git a/contrib/connector/common.go b/contrib/connector/common.go index eb40d1d56..fb8d7f759 100644 --- a/contrib/connector/common.go +++ b/contrib/connector/common.go @@ -21,7 +21,13 @@ import ( "strings" ) -// execCmd ... +// InitiatorInfo implementation +type InitiatorInfo struct { + HostName string `json:"hostName"` + InitiatorData map[string]interface{} `json:"initiatorData"` +} + +// ExecCmd Log and convert the result of exec.Command func ExecCmd(name string, arg ...string) (string, error) { log.Printf("Command: %s %s:\n", name, strings.Join(arg, " ")) info, err := exec.Command(name, arg...).CombinedOutput() @@ -137,11 +143,12 @@ func GetHostIp() string { func GetHostName() (string, error) { hostName, err := ExecCmd("hostname") if err != nil { - log.Printf("failed to get host name: %v", err) + log.Printf("failed to get hostname: %v", err) return "", err } hostName = strings.Replace(hostName, "\n", "", -1) + log.Printf("GetHostName result: %v", hostName) return hostName, nil } diff --git a/contrib/connector/connector.go b/contrib/connector/connector.go index 65a1829b3..d8018a9cb 100644 --- a/contrib/connector/connector.go +++ b/contrib/connector/connector.go @@ -16,33 +16,39 @@ package connector import ( "fmt" + "log" ) +// Connector implementation type Connector interface { Attach(map[string]interface{}) (string, error) Detach(map[string]interface{}) error - GetInitiatorInfo() (string, error) + GetInitiatorInfo() (InitiatorInfo, error) } +// NewConnector implementation func NewConnector(cType string) Connector { if cnt, exist := cnts[cType]; exist { return cnt } + log.Printf("%s is not registered to connector", cType) return nil } var cnts = map[string]Connector{} +// RegisterConnector implementation func RegisterConnector(cType string, cnt Connector) error { if _, exist := cnts[cType]; exist { - return fmt.Errorf("Connector %s already exist.", cType) + return fmt.Errorf("Connector %s already exist", cType) } cnts[cType] = cnt return nil } +// UnregisterConnector implementation func UnregisterConnector(cType string) { if _, exist := cnts[cType]; !exist { return diff --git a/contrib/connector/fc/fc.go b/contrib/connector/fc/fc.go index 55a4c58e1..a7730aa91 100644 --- a/contrib/connector/fc/fc.go +++ b/contrib/connector/fc/fc.go @@ -52,6 +52,6 @@ func (f *FC) Detach(conn map[string]interface{}) error { } // GetInitiatorInfo implementation -func (f *FC) GetInitiatorInfo() (string, error) { +func (f *FC) GetInitiatorInfo() (connector.InitiatorInfo, error) { return f.self.getInitiatorInfo() } diff --git a/contrib/connector/fc/fibreChannel.go b/contrib/connector/fc/fibreChannel.go index 3d8050894..14f064cdf 100644 --- a/contrib/connector/fc/fibreChannel.go +++ b/contrib/connector/fc/fibreChannel.go @@ -23,6 +23,7 @@ import ( "time" "github.com/mitchellh/mapstructure" + "github.com/opensds/opensds/contrib/connector" ) type FCConnectorInfo struct { @@ -216,23 +217,40 @@ func (f *fibreChannel) getFChbasInfo() ([]map[string]string, error) { return hbasInfos, nil } -func (f *fibreChannel) getInitiatorInfo() (string, error) { +func (f *fibreChannel) getInitiatorInfo() (connector.InitiatorInfo, error) { + var initiatorInfo connector.InitiatorInfo + hbas, err := f.getFChbasInfo() if err != nil { - return "", err + log.Printf("getFChbasInfo failed: %v", err.Error()) + return initiatorInfo, err } - var initiatorInfo []string + var wwpns []string + var wwnns []string for _, hba := range hbas { if v, ok := hba[PortName]; ok { - initiatorInfo = append(initiatorInfo, Wwpn+":"+v) + wwpns = append(wwpns, v) } if v, ok := hba[NodeName]; ok { - initiatorInfo = append(initiatorInfo, Wwnn+":"+v) + wwnns = append(wwnns, v) } } - return strings.Join(initiatorInfo, ","), nil + initiatorInfo.InitiatorData = make(map[string]interface{}) + initiatorInfo.InitiatorData[Wwpn] = wwpns + initiatorInfo.InitiatorData[Wwnn] = wwnns + + hostName, err := connector.GetHostName() + if err != nil { + return initiatorInfo, err + } + + initiatorInfo.HostName = hostName + log.Printf("getFChbasInfo success: protocol=%v, initiatorInfo=%v", + fcDriver, initiatorInfo) + + return initiatorInfo, nil } diff --git a/contrib/connector/iscsi/helper.go b/contrib/connector/iscsi/helper.go index 093e504ba..01281217b 100644 --- a/contrib/connector/iscsi/helper.go +++ b/contrib/connector/iscsi/helper.go @@ -17,9 +17,7 @@ package iscsi import ( "errors" "log" - "os" - "path/filepath" "strconv" "strings" @@ -265,15 +263,29 @@ func ParseIscsiConnectInfo(connectInfo map[string]interface{}) *IscsiConnectorIn } // getInitiatorInfo implementation -func getInitiatorInfo() (string, error) { +func getInitiatorInfo() (connector.InitiatorInfo, error) { + var initiatorInfo connector.InitiatorInfo + initiators, err := GetInitiator() if err != nil { - return "", err + return initiatorInfo, err } if len(initiators) == 0 { - return "", errors.New("The number of iqn is wrong") + return initiatorInfo, errors.New("The number of iqn is wrong") + } + + initiatorInfo.InitiatorData = make(map[string]interface{}) + initiatorInfo.InitiatorData[Iqn] = initiators[0] + + hostName, err := connector.GetHostName() + if err != nil { + return initiatorInfo, err } - return initiators[0], nil + initiatorInfo.HostName = hostName + log.Printf("getFChbasInfo success: protocol=%v, initiatorInfo=%v", + iscsiDriver, initiatorInfo) + + return initiatorInfo, nil } diff --git a/contrib/connector/iscsi/iscsi.go b/contrib/connector/iscsi/iscsi.go index eefec1f6b..b91617f6a 100644 --- a/contrib/connector/iscsi/iscsi.go +++ b/contrib/connector/iscsi/iscsi.go @@ -20,7 +20,7 @@ import ( const ( iscsiDriver = "iscsi" - Iqn = "iqn" + Iqn = "iqn" ) type Iscsi struct{} @@ -40,6 +40,6 @@ func (isc *Iscsi) Detach(conn map[string]interface{}) error { } // GetInitiatorInfo implementation -func (isc *Iscsi) GetInitiatorInfo() (string, error) { +func (isc *Iscsi) GetInitiatorInfo() (connector.InitiatorInfo, error) { return getInitiatorInfo() } diff --git a/contrib/connector/rbd/rbd.go b/contrib/connector/rbd/rbd.go index 05a78a204..ea9d53bd5 100644 --- a/contrib/connector/rbd/rbd.go +++ b/contrib/connector/rbd/rbd.go @@ -97,8 +97,17 @@ func (*RBD) Detach(conn map[string]interface{}) error { } // GetInitiatorInfo implementation -func (*RBD) GetInitiatorInfo() (string, error) { - return "", nil +func (*RBD) GetInitiatorInfo() (connector.InitiatorInfo, error) { + var initiatorInfo connector.InitiatorInfo + hostName, err := connector.GetHostName() + + if err != nil { + return initiatorInfo, err + } + + initiatorInfo.HostName = hostName + + return initiatorInfo, nil } func mapDevice(poolName, imageName string, hosts, ports []interface{}) (string, error) { From 7651cd752ba39114c8f5aad16e8858356ae0139e Mon Sep 17 00:00:00 2001 From: PengYiOfOpenSDS Date: Thu, 15 Nov 2018 10:06:31 +0800 Subject: [PATCH 08/20] If the volume is created from snapshot on dorado, the volume name cannot exceed 31. --- contrib/drivers/huawei/dorado/dorado.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/contrib/drivers/huawei/dorado/dorado.go b/contrib/drivers/huawei/dorado/dorado.go index 717fb1b6e..3ba42e4f4 100644 --- a/contrib/drivers/huawei/dorado/dorado.go +++ b/contrib/drivers/huawei/dorado/dorado.go @@ -74,7 +74,16 @@ func (d *Driver) createVolumeFromSnapshot(opt *pb.CreateVolumeOpts) (*model.Volu return nil, err1 } - lun, err := d.client.CreateVolume(opt.GetName(), opt.GetSize(), volumeDesc, poolId) + name := opt.GetName() + // If the volume is created from snapshot, the volume name cannot exceed 31. + if len(opt.GetSnapshotId()) > 0 { + if len(name) > 31 { + name = string([]byte(name)[:31]) + log.Infof("volume name is shortened from %s to %s", opt.GetName(), name) + } + } + + lun, err := d.client.CreateVolume(name, opt.GetSize(), volumeDesc, poolId) if err != nil { log.Error("Create Volume Failed:", err) return nil, err From e39830c015adffcdb2c55682b23e4e4dff16872b Mon Sep 17 00:00:00 2001 From: jerry Date: Thu, 15 Nov 2018 11:48:39 +0800 Subject: [PATCH 09/20] Remove uused code, and fixed failback bug --- contrib/drivers/huawei/dorado/replication.go | 79 +------------------- 1 file changed, 4 insertions(+), 75 deletions(-) diff --git a/contrib/drivers/huawei/dorado/replication.go b/contrib/drivers/huawei/dorado/replication.go index 50b70a88d..710d2fb6c 100644 --- a/contrib/drivers/huawei/dorado/replication.go +++ b/contrib/drivers/huawei/dorado/replication.go @@ -204,10 +204,6 @@ func (r *ReplicaPairMgr) CheckRemoteAvailable() bool { return false } -func (r *ReplicaPairMgr) UpdateReplicationCapability(stats []string) { - //rmtOk := r.CheckRemoteAvailable() -} - func (r *ReplicaPairMgr) GetRemoteDevInfo() (id, name string) { wwn := r.TryGetRemoteWwn() if wwn == "" { @@ -220,24 +216,6 @@ func (r *ReplicaPairMgr) GetRemoteDevInfo() (id, name string) { return dev.Id, dev.Name } -func (r *ReplicaPairMgr) BuildRemoteLunParams(localLun *Lun) map[string]interface{} { - return map[string]interface{}{ - "Type": "11", - "Name": localLun.Name, - "Parenttype": "216", - "ParentId": "", - "Description": localLun.Description, - "Alloctype": localLun.AllocType, - "Capacity": localLun.Capability, - //"Writepolicy": Self.Conf.Lun_Write_Type, - //"Prefetchpolicy": Self.Conf.Lun_Prefetch_Type, - //"Prefetchvalue": Self.Conf.Lun_Prefetch_Value, - //"Datatransferpolicy": Self.Conf.Lun_Policy, - //"Readcachepolicy": Self.Conf.Lun_Read_Cache_Policy, - //"Writecachepolicy": Self.Conf.Lun_Write_Cache_Policy, - } -} - func (r *ReplicaPairMgr) WaitVolumeOnline(client *DoradoClient, lun *Lun, interval, timeout time.Duration) error { if lun.RunningStatus == StatusVolumeReady { return nil @@ -263,32 +241,6 @@ func (r *ReplicaPairMgr) WaitVolumeOnline(client *DoradoClient, lun *Lun, interv }, interval, timeout) } -func (r *ReplicaPairMgr) CreateRemoteLun(localLun *Lun) (*Lun, error) { - //params := r.BuildRemoteLunParams(localLun) - sector, err := strconv.ParseInt(localLun.SectorSize, 10, 64) - if err != nil { - return nil, err - } - rmtLun, err := r.remoteClient.CreateVolume(localLun.Name, sector, localLun.Description, "0") - if err != nil { - return nil, err - } - interval := DefaultReplicaWaitInterval - timeout := DefaultReplicaWaitTimeout - if err := r.WaitVolumeOnline(r.remoteClient, rmtLun, interval, timeout); err != nil { - r.remoteClient.DeleteVolume(rmtLun.Id) - return nil, err - } - return rmtLun, err -} - -func (r *ReplicaPairMgr) DeleteRemoteLun(id string) error { - if r.remoteClient.CheckLunExist(id, "") { - return r.remoteClient.DeleteVolume(id) - } - return nil -} - func (r *ReplicaPairMgr) DeletePair(id string) error { if !r.localClient.CheckPairExist(id) { return nil @@ -303,12 +255,12 @@ func (r *ReplicaPairMgr) DeletePair(id string) error { return nil } -func (r *ReplicaPairMgr) CreateReplication(pLunId, sLunId, replicationMode string, replicaPeriod string) (map[string]string, error) { +func (r *ReplicaPairMgr) CreateReplication(localLunId, rmtLunId, replicationMode string, replicaPeriod string) (map[string]string, error) { interval := DefaultReplicaWaitInterval timeout := DefaultReplicaWaitTimeout var respMap = make(map[string]string) - localLun, err := r.localClient.GetVolume(pLunId) + localLun, err := r.localClient.GetVolume(localLunId) if err != nil { return nil, err } @@ -317,39 +269,20 @@ func (r *ReplicaPairMgr) CreateReplication(pLunId, sLunId, replicationMode strin if err != nil { return nil, err } - var rmtLunId = sLunId - if sLunId == "" { - rmtLun, err := r.CreateRemoteLun(localLun) - if err != nil { - return nil, err - } - rmtLunId = rmtLun.Id - respMap[KSecondaryLunId] = rmtLunId - } - - var cleanlun = false - defer func() { - if cleanlun && sLunId == "" { - r.DeleteRemoteLun(rmtLunId) - } - }() rmtDevId, rmtDevName := r.GetRemoteDevInfo() log.Errorf("rmtDevId:%s, rmtDevName:%s", rmtDevId, rmtDevName) if rmtDevId == "" || rmtDevName == "" { - cleanlun = true return nil, fmt.Errorf("get remote deivce info failed") } pair, err := r.localOp.Create(localLun.Id, rmtLunId, rmtDevId, rmtDevName, replicationMode, ReplicaSpeed, replicaPeriod) if err != nil { - cleanlun = true return nil, err } log.Error("start sync ....", pair) if err := r.localDriver.Sync(pair.Id, replicationMode == ReplicaSyncMode); err != nil { r.DeletePair(pair.Id) - cleanlun = true return nil, err } respMap[KPairId] = pair.Id @@ -361,9 +294,6 @@ func (r *ReplicaPairMgr) DeleteReplication(pairId, rmtLunId string) error { log.Error("Delete pair failed,", err) return err } - if rmtLunId != "" { - return r.DeleteRemoteLun(rmtLunId) - } return nil } @@ -376,10 +306,9 @@ func (r *ReplicaPairMgr) DeleteReplication(pairId, rmtLunId string) error { // 5. Enable replications. func (r *ReplicaPairMgr) Failback(pairId string) error { + r.remoteDriver.Enable(pairId, true) + r.remoteDriver.WaitReplicaReady(pairId) r.localDriver.Enable(pairId, false) - r.localDriver.WaitReplicaReady(pairId) - r.remoteDriver.Failover(pairId) - r.remoteDriver.Enable(pairId, false) return nil } From 16cebf9f330e83b7bc7deefd07c818c65d37ff01 Mon Sep 17 00:00:00 2001 From: PengYiOfOpenSDS Date: Tue, 20 Nov 2018 17:06:04 +0800 Subject: [PATCH 10/20] dorado: create volume from snapshot --- contrib/drivers/huawei/dorado/dorado.go | 53 +++++++++++-------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/contrib/drivers/huawei/dorado/dorado.go b/contrib/drivers/huawei/dorado/dorado.go index 3ba42e4f4..45da19746 100644 --- a/contrib/drivers/huawei/dorado/dorado.go +++ b/contrib/drivers/huawei/dorado/dorado.go @@ -74,32 +74,29 @@ func (d *Driver) createVolumeFromSnapshot(opt *pb.CreateVolumeOpts) (*model.Volu return nil, err1 } - name := opt.GetName() - // If the volume is created from snapshot, the volume name cannot exceed 31. - if len(opt.GetSnapshotId()) > 0 { - if len(name) > 31 { - name = string([]byte(name)[:31]) - log.Infof("volume name is shortened from %s to %s", opt.GetName(), name) - } - } - - lun, err := d.client.CreateVolume(name, opt.GetSize(), volumeDesc, poolId) + lun, err := d.client.CreateVolume(EncodeName(opt.GetId()), opt.GetSize(), + volumeDesc, poolId) if err != nil { log.Error("Create Volume Failed:", err) return nil, err } log.Infof("Create Volume from snapshot, source_lun_id : %s , target_lun_id : %s", snapshot.Id, lun.Id) - err = WaitForCondition(func() (bool, error) { - if lun.HealthStatus == StatusHealth && lun.RunningStatus == StatusVolumeReady { - return true, nil + getVolumeResult, getVolumeErr := d.client.GetVolume(lun.Id) + if nil == getVolumeErr { + if getVolumeResult.HealthStatus == StatusHealth && getVolumeResult.RunningStatus == StatusVolumeReady { + return true, nil + } else { + log.V(5).Infof("Current lun HealthStatus : %s , RunningStatus : %s", + getVolumeResult.HealthStatus, getVolumeResult.RunningStatus) + return false, nil + } } else { - msg := fmt.Sprintf("Volume state is not mathch, lun ID : %s , HealthStatus : %s,RunningStatus : %s", - lun.Id, lun.HealthStatus, lun.RunningStatus) - return false, errors.New(msg) + return false, getVolumeErr } }, LunReadyWaitInterval, LunReadyWaitTimeout) + if err != nil { log.Error(err) d.client.DeleteVolume(lun.Id) @@ -127,37 +124,35 @@ func (d *Driver) createVolumeFromSnapshot(opt *pb.CreateVolumeOpts) (*model.Volu func (d *Driver) copyVolume(opt *pb.CreateVolumeOpts, srcid, tgtid string) error { metadata := opt.GetMetadata() copyspeed := metadata["copyspeed"] - luncopyid, err := d.client.CreateLunCopy(opt.GetName(), srcid, tgtid, copyspeed) + luncopyid, err := d.client.CreateLunCopy(EncodeName(opt.GetId()), srcid, + tgtid, copyspeed) if err != nil { log.Error("Create Lun Copy failed,", err) return err } - defer d.client.DeleteLunCopy(luncopyid) + err = d.client.StartLunCopy(luncopyid) if err != nil { log.Errorf("Start lun: %s copy failed :%v,", luncopyid, err) + d.client.DeleteLunCopy(luncopyid) return err } - lunCopyInfo, err1 := d.client.GetLunInfo(luncopyid) - if err1 != nil { - log.Errorf("Get lun info failed :%v", err1) - return err1 - } + err = WaitForCondition(func() (bool, error) { - if lunCopyInfo.RunningStatus == StatusLuncopyReady || lunCopyInfo.RunningStatus == StatusLunCoping { + deleteLunCopyErr := d.client.DeleteLunCopy(luncopyid) + if nil == deleteLunCopyErr { return true, nil - } else if lunCopyInfo.HealthStatus != StatusHealth { - msg := fmt.Sprintf("An error occurred during the luncopy operation. Lun name : %s ,Lun copy health status : %s ,Lun copy running status : %s ", - lunCopyInfo.Name, lunCopyInfo.HealthStatus, lunCopyInfo.RunningStatus) - return false, errors.New(msg) } - return true, nil + + return false, nil }, LunCopyWaitInterval, LunCopyWaitTimeout) + if err != nil { log.Error(err) return err } + log.Infof("Copy Volume %s success", tgtid) return nil } From e2c052b978556a78a73bd0d9a9c782bd8e66ae97 Mon Sep 17 00:00:00 2001 From: PengYiOfOpenSDS Date: Wed, 21 Nov 2018 11:01:13 +0800 Subject: [PATCH 11/20] Optimization code --- contrib/connector/connector.go | 13 +++++++++++++ contrib/connector/fc/fc.go | 10 +--------- contrib/connector/fc/fibreChannel.go | 10 +++++----- contrib/connector/iscsi/helper.go | 4 ++-- contrib/connector/iscsi/iscsi.go | 7 +------ contrib/connector/rbd/rbd.go | 6 +----- 6 files changed, 23 insertions(+), 27 deletions(-) diff --git a/contrib/connector/connector.go b/contrib/connector/connector.go index d8018a9cb..d7c4aed4f 100644 --- a/contrib/connector/connector.go +++ b/contrib/connector/connector.go @@ -19,6 +19,19 @@ import ( "log" ) +const ( + FcDriver = "fibre_channel" + PortName = "port_name" + NodeName = "node_name" + Wwpn = "wwpn" + Wwnn = "wwnn" + + IscsiDriver = "iscsi" + Iqn = "iqn" + + RbdDriver = "rbd" +) + // Connector implementation type Connector interface { Attach(map[string]interface{}) (string, error) diff --git a/contrib/connector/fc/fc.go b/contrib/connector/fc/fc.go index a7730aa91..c8ee66a31 100644 --- a/contrib/connector/fc/fc.go +++ b/contrib/connector/fc/fc.go @@ -18,20 +18,12 @@ import ( "github.com/opensds/opensds/contrib/connector" ) -const ( - fcDriver = "fibre_channel" - PortName = "port_name" - NodeName = "node_name" - Wwpn = "wwpn" - Wwnn = "wwnn" -) - type FC struct { self *fibreChannel } func init() { - connector.RegisterConnector(fcDriver, + connector.RegisterConnector(connector.FcDriver, &FC{ self: &fibreChannel{ helper: &linuxfc{}, diff --git a/contrib/connector/fc/fibreChannel.go b/contrib/connector/fc/fibreChannel.go index 14f064cdf..ecc0c272b 100644 --- a/contrib/connector/fc/fibreChannel.go +++ b/contrib/connector/fc/fibreChannel.go @@ -230,18 +230,18 @@ func (f *fibreChannel) getInitiatorInfo() (connector.InitiatorInfo, error) { var wwnns []string for _, hba := range hbas { - if v, ok := hba[PortName]; ok { + if v, ok := hba[connector.PortName]; ok { wwpns = append(wwpns, v) } - if v, ok := hba[NodeName]; ok { + if v, ok := hba[connector.NodeName]; ok { wwnns = append(wwnns, v) } } initiatorInfo.InitiatorData = make(map[string]interface{}) - initiatorInfo.InitiatorData[Wwpn] = wwpns - initiatorInfo.InitiatorData[Wwnn] = wwnns + initiatorInfo.InitiatorData[connector.Wwpn] = wwpns + initiatorInfo.InitiatorData[connector.Wwnn] = wwnns hostName, err := connector.GetHostName() if err != nil { @@ -250,7 +250,7 @@ func (f *fibreChannel) getInitiatorInfo() (connector.InitiatorInfo, error) { initiatorInfo.HostName = hostName log.Printf("getFChbasInfo success: protocol=%v, initiatorInfo=%v", - fcDriver, initiatorInfo) + connector.FcDriver, initiatorInfo) return initiatorInfo, nil } diff --git a/contrib/connector/iscsi/helper.go b/contrib/connector/iscsi/helper.go index 01281217b..c10a31546 100644 --- a/contrib/connector/iscsi/helper.go +++ b/contrib/connector/iscsi/helper.go @@ -276,7 +276,7 @@ func getInitiatorInfo() (connector.InitiatorInfo, error) { } initiatorInfo.InitiatorData = make(map[string]interface{}) - initiatorInfo.InitiatorData[Iqn] = initiators[0] + initiatorInfo.InitiatorData[connector.Iqn] = initiators[0] hostName, err := connector.GetHostName() if err != nil { @@ -285,7 +285,7 @@ func getInitiatorInfo() (connector.InitiatorInfo, error) { initiatorInfo.HostName = hostName log.Printf("getFChbasInfo success: protocol=%v, initiatorInfo=%v", - iscsiDriver, initiatorInfo) + connector.IscsiDriver, initiatorInfo) return initiatorInfo, nil } diff --git a/contrib/connector/iscsi/iscsi.go b/contrib/connector/iscsi/iscsi.go index b91617f6a..0e899c3ea 100644 --- a/contrib/connector/iscsi/iscsi.go +++ b/contrib/connector/iscsi/iscsi.go @@ -18,15 +18,10 @@ import ( "github.com/opensds/opensds/contrib/connector" ) -const ( - iscsiDriver = "iscsi" - Iqn = "iqn" -) - type Iscsi struct{} func init() { - connector.RegisterConnector(iscsiDriver, &Iscsi{}) + connector.RegisterConnector(connector.IscsiDriver, &Iscsi{}) } func (isc *Iscsi) Attach(conn map[string]interface{}) (string, error) { diff --git a/contrib/connector/rbd/rbd.go b/contrib/connector/rbd/rbd.go index ea9d53bd5..a7b939e5e 100644 --- a/contrib/connector/rbd/rbd.go +++ b/contrib/connector/rbd/rbd.go @@ -27,10 +27,6 @@ import ( "github.com/opensds/opensds/contrib/connector" ) -const ( - rbdDriver = "rbd" -) - var ( rbdBusPath = "/sys/bus/rbd" rbdDevicePath = path.Join(rbdBusPath, "devices") @@ -42,7 +38,7 @@ type RBD struct{} var _ connector.Connector = &RBD{} func init() { - connector.RegisterConnector(rbdDriver, &RBD{}) + connector.RegisterConnector(connector.RbdDriver, &RBD{}) } func (*RBD) Attach(conn map[string]interface{}) (string, error) { From 7878e5afa1906aa0404ba42fdc5826670ae88cc6 Mon Sep 17 00:00:00 2001 From: jerry Date: Wed, 21 Nov 2018 16:43:36 +0800 Subject: [PATCH 12/20] Add create volume from cloud snapshot and optmize some bugs --- client/receiver.go | 11 +- contrib/backup/driver.go | 2 +- contrib/backup/multicloud/client.go | 33 +++- contrib/backup/multicloud/driver.go | 41 ++++- contrib/drivers/lvm/lvm.go | 107 ++++++++++--- osdsctl/cli/cli.go | 16 +- osdsctl/cli/common.go | 8 - osdsctl/cli/dock.go | 2 - osdsctl/cli/profile.go | 3 - osdsctl/cli/replication.go | 4 - osdsctl/cli/version.go | 2 - osdsctl/cli/volume.go | 42 +++-- osdsctl/cli/volumeattachment.go | 4 - osdsctl/cli/volumegroup.go | 4 - osdsctl/cli/volumesnapshot.go | 4 - pkg/api/db.go | 17 ++- pkg/api/volume.go | 1 - pkg/controller/controller.go | 29 ++-- pkg/dock/proto/dock.pb.go | 228 +++++++++++++++------------- pkg/dock/proto/dock.proto | 2 + pkg/model/volume.go | 3 + 21 files changed, 349 insertions(+), 214 deletions(-) diff --git a/client/receiver.go b/client/receiver.go index 8c5e3ba0f..2829a9358 100755 --- a/client/receiver.go +++ b/client/receiver.go @@ -18,6 +18,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "log" "net/http" "strings" "time" @@ -71,9 +72,16 @@ func request(url string, method string, headers HeaderOption, input interface{}, // Set the request timeout a little bit longer upload snapshot to cloud temporarily. req.SetTimeout(time.Minute*6, time.Minute*6) // init body + log.Printf("%s %s\n", strings.ToUpper(method), url) if input != nil { - req.JSONBody(input) + body, err := json.MarshalIndent(input, "", " ") + if err != nil { + return err + } + log.Printf("Request body:\n%s\n", string(body)) + req.Body(body) } + //init header if headers != nil { for k, v := range headers { @@ -90,6 +98,7 @@ func request(url string, method string, headers HeaderOption, input interface{}, return err } + log.Printf("\nStatusCode: %s\nResponse Body:\n%s\n", resp.Status, string(rbody)) if 400 <= resp.StatusCode && resp.StatusCode <= 599 { return NewHttpError(resp.StatusCode, string(rbody)) } diff --git a/contrib/backup/driver.go b/contrib/backup/driver.go index c5007f463..546b7e0df 100644 --- a/contrib/backup/driver.go +++ b/contrib/backup/driver.go @@ -28,7 +28,7 @@ type BackupSpec struct { type BackupDriver interface { SetUp() error Backup(backup *BackupSpec, volumeFile *os.File) error - Restore(backup *BackupSpec, volId string, volFile *os.File) error + Restore(backup *BackupSpec, backupId string, volFile *os.File) error Delete(backup *BackupSpec) error CleanUp() error } diff --git a/contrib/backup/multicloud/client.go b/contrib/backup/multicloud/client.go index 9c4b4c816..fb2c5520d 100644 --- a/contrib/backup/multicloud/client.go +++ b/contrib/backup/multicloud/client.go @@ -25,6 +25,7 @@ import ( "github.com/astaxie/beego/httplib" log "github.com/golang/glog" + "io/ioutil" ) const ( @@ -102,11 +103,12 @@ func (c *Client) doRequest(method, u string, in interface{}, cb ReqSettingCB) ([ } log.V(5).Infof("%s: %s OK\n", method, u) - b, err := req.Bytes() + rbody, err := ioutil.ReadAll(resp.Body) if err != nil { log.Errorf("Get byte[] from response failed, method: %s\n url: %s\n error: %v", method, u, err) + return nil, nil, err } - return b, resp.Header, nil + return rbody, resp.Header, nil } func (c *Client) request(method, p string, in, out interface{}, cb ReqSettingCB) error { @@ -251,3 +253,30 @@ func (c *Client) AbortMultipartUpload(bucketName, objectKey string) error { //} return nil } + +func (c *Client) DownloadPart(bucketName, objectKey string, offset, size int64) ([]byte, error) { + p := path.Join("s3", bucketName, objectKey) + + reqSettingCB := func(req *httplib.BeegoHTTPRequest) error { + rangeStr := fmt.Sprintf("bytes:%d-%d", offset, offset+size-1) + req.Header("Range", rangeStr) + req.SetTimeout(c.uploadTimeout, c.uploadTimeout) + return nil + } + + u, err := url.Parse(p) + if err != nil { + return nil, err + } + base, err := url.Parse(c.baseURL) + if err != nil { + return nil, err + } + + fullUrl := base.ResolveReference(u) + body, _, err := c.doRequest("GET", fullUrl.String(), nil, reqSettingCB) + if err != nil { + return nil, err + } + return body, nil +} diff --git a/contrib/backup/multicloud/driver.go b/contrib/backup/multicloud/driver.go index 3d0d9982f..b6394142f 100644 --- a/contrib/backup/multicloud/driver.go +++ b/contrib/backup/multicloud/driver.go @@ -15,6 +15,7 @@ package multicloud import ( + "errors" "io" "io/ioutil" "os" @@ -25,8 +26,8 @@ import ( ) const ( - ConfFile = "/etc/opensds/driver/multi-cloud.yaml" - UploadChunkSize = 1024 * 1024 * 50 + ConfFile = "/etc/opensds/driver/multi-cloud.yaml" + ChunkSize = 1024 * 1024 * 50 ) func init() { @@ -89,10 +90,13 @@ func (m *MultiCloud) CleanUp() error { } func (m *MultiCloud) Backup(backup *backup.BackupSpec, volFile *os.File) error { - buf := make([]byte, UploadChunkSize) + buf := make([]byte, ChunkSize) input := &CompleteMultipartUpload{} - bucket := backup.Metadata["bucket"] + bucket, ok := backup.Metadata["bucket"] + if !ok { + return errors.New("can't find bucket in metadata") + } key := backup.Id initResp, err := m.client.InitMultiPartUpload(bucket, key) if err != nil { @@ -132,7 +136,34 @@ func (m *MultiCloud) Backup(backup *backup.BackupSpec, volFile *os.File) error { return nil } -func (m *MultiCloud) Restore(backup *backup.BackupSpec, volId string, volFile *os.File) error { +func (m *MultiCloud) Restore(backup *backup.BackupSpec, backupId string, volFile *os.File) error { + bucket, ok := backup.Metadata["bucket"] + if !ok { + return errors.New("can't find bucket in metadata") + } + var downloadSize = ChunkSize + // if the size of data of smaller than require download size + // downloading is completed. + for offset := int64(0); downloadSize == ChunkSize; offset += ChunkSize { + data, err := m.client.DownloadPart(bucket, backupId, offset, ChunkSize) + if err != nil { + glog.Errorf("download part failed: %v", err) + return err + } + downloadSize = len(data) + glog.V(5).Infof("download size: %d\n", downloadSize) + volFile.Seek(offset, 0) + size, err := volFile.Write(data) + if err != nil { + glog.Errorf("write part failed: %v", err) + return err + } + if size != downloadSize { + return errors.New("size not equal to download size") + } + glog.V(5).Infof("write buf size len:%d", size) + } + glog.Infof("restore success ...") return nil } diff --git a/contrib/drivers/lvm/lvm.go b/contrib/drivers/lvm/lvm.go index f4ffca98d..cea6152b0 100755 --- a/contrib/drivers/lvm/lvm.go +++ b/contrib/drivers/lvm/lvm.go @@ -87,7 +87,57 @@ func (d *Driver) Setup() error { func (*Driver) Unset() error { return nil } -func (d *Driver) CreateVolume(opt *pb.CreateVolumeOpts) (*model.VolumeSpec, error) { +func (d *Driver) copySnapshotToVolume(opt *pb.CreateVolumeOpts, lvPath string) error { + var snapSize = uint64(opt.GetSnapshotSize()) + var count = (snapSize << sizeShiftBit) / blocksize + var snapName = snapshotPrefix + opt.GetSnapshotId() + var snapPath = path.Join("/dev", opt.GetPoolName(), snapName) + if _, err := d.handler("dd", []string{ + "if=" + snapPath, + "of=" + lvPath, + "count=" + fmt.Sprint(count), + "bs=" + fmt.Sprint(blocksize), + }); err != nil { + log.Error("Failed to create logic volume:", err) + return err + } + return nil +} + +func (d *Driver) downloadSnapshot(bucket, backupId, dest string) error { + mc, err := backup.NewBackup("multi-cloud") + if err != nil { + log.Errorf("get backup driver, err: %v", err) + return err + } + + if err := mc.SetUp(); err != nil { + return err + } + defer mc.CleanUp() + + file, err := os.OpenFile(dest, os.O_RDWR, 0666) + if err != nil { + log.Errorf("open lvm snapshot file, err: %v", err) + return err + } + defer file.Close() + + metadata := map[string]string{ + "bucket": bucket, + } + b := &backup.BackupSpec{ + Metadata: metadata, + } + + if err := mc.Restore(b, backupId, file); err != nil { + log.Errorf("upload snapshot to multi-cloud failed, err: %v", err) + return err + } + return nil +} + +func (d *Driver) CreateVolume(opt *pb.CreateVolumeOpts) (vol *model.VolumeSpec, err error) { var size = fmt.Sprint(opt.GetSize()) + "G" var polName = opt.GetPoolName() var id = opt.GetId() @@ -121,21 +171,41 @@ func (d *Driver) CreateVolume(opt *pb.CreateVolumeOpts) (*model.VolumeSpec, erro } } - // Copy snapshot to volume - var snap = opt.GetSnapshotId() - if snap != "" { - var snapSize = uint64(opt.GetSnapshotSize()) - var count = (snapSize << sizeShiftBit) / blocksize - var snapName = snapshotPrefix + snap - var snapPath = path.Join("/dev", polName, snapName) - if _, err := d.handler("dd", []string{ - "if=" + snapPath, - "of=" + lvPath, - "count=" + fmt.Sprint(count), - "bs=" + fmt.Sprint(blocksize), - }); err != nil { - log.Error("Failed to create logic volume:", err) - return nil, err + // remove created volume if got error + defer func() { + // using return value as the error flag + if vol == nil { + _, err := d.handler("lvremove", []string{"-f", lvPath}) + if err != nil { + log.Error("Failed to remove logic volume:", err) + } + } + }() + + // Create volume from snapshot + if opt.GetSnapshotId() != "" { + if opt.SnapshotFromCloud { + // download cloud snapshot to volume + data := opt.GetMetadata() + backupId, ok := data["backupId"] + if !ok { + return nil, errors.New("can't find backupId in metadata") + } + bucket, ok := data["bucket"] + if !ok { + return nil, errors.New("can't find bucket name in metadata") + } + err := d.downloadSnapshot(bucket, backupId, lvPath) + if err != nil { + log.Errorf("Download snapshot failed, %v", err) + return nil, err + } + } else { + // copy local snapshot to volume + if err := d.copySnapshotToVolume(opt, lvPath); err != nil { + log.Errorf("Copy snapshot to volume failed, %v", err) + return nil, err + } } } @@ -502,11 +572,10 @@ func (d *Driver) deleteUploadedSnapshot(backupId string, bucket string) error { return nil } -func (d *Driver) CreateSnapshot(opt *pb.CreateVolumeSnapshotOpts) (*model.VolumeSnapshotSpec, error) { +func (d *Driver) CreateSnapshot(opt *pb.CreateVolumeSnapshotOpts) (snap *model.VolumeSnapshotSpec, err error) { var size = fmt.Sprint(opt.GetSize()) + "G" var id = opt.GetId() var snapName = snapshotPrefix + id - var err error lvPath, ok := opt.GetMetadata()["lvPath"] if !ok { @@ -542,7 +611,7 @@ func (d *Driver) CreateSnapshot(opt *pb.CreateVolumeSnapshotOpts) (*model.Volume } defer func() { - if err != nil { + if snap == nil { log.Errorf("create snapshot failed, rollback it") d.handler("lvremove", []string{"-f", lvsPath}) } diff --git a/osdsctl/cli/cli.go b/osdsctl/cli/cli.go index 060b59c03..da87fe305 100644 --- a/osdsctl/cli/cli.go +++ b/osdsctl/cli/cli.go @@ -54,17 +54,27 @@ func init() { flags.BoolVar(&Debug, "debug", false, "shows debugging output.") } -type Writer struct{} +type DummyWriter struct{} // do nothing -func (writer Writer) Write(data []byte) (n int, err error) { +func (writer DummyWriter) Write(data []byte) (n int, err error) { + return len(data), nil +} + +type DebugWriter struct{} + +// do nothing +func (writer DebugWriter) Write(data []byte) (n int, err error) { + Debugf("%s", string(data)) return len(data), nil } // Run method indicates how to start a cli tool through cobra. func Run() error { if !utils.Contained("--debug", os.Args) { - log.SetOutput(Writer{}) + log.SetOutput(DummyWriter{}) + } else { + log.SetOutput(DebugWriter{}) } ep, ok := os.LookupEnv(c.OpensdsEndpoint) diff --git a/osdsctl/cli/common.go b/osdsctl/cli/common.go index 87ea347e3..01ff8a333 100644 --- a/osdsctl/cli/common.go +++ b/osdsctl/cli/common.go @@ -15,7 +15,6 @@ package cli import ( - "encoding/json" "fmt" "os" @@ -97,10 +96,3 @@ func ArgsNumCheck(cmd *cobra.Command, args []string, invalidNum int) { os.Exit(1) } } - -func PrintResponse(v interface{}) { - if Debug { - b, _ := json.Marshal(v) - Debugln(string(b)) - } -} diff --git a/osdsctl/cli/dock.go b/osdsctl/cli/dock.go index 8d4575b34..fbf8ad9eb 100644 --- a/osdsctl/cli/dock.go +++ b/osdsctl/cli/dock.go @@ -83,7 +83,6 @@ func dockAction(cmd *cobra.Command, args []string) { func dockShowAction(cmd *cobra.Command, args []string) { ArgsNumCheck(cmd, args, 1) resp, err := client.GetDock(args[0]) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } @@ -99,7 +98,6 @@ func dockListAction(cmd *cobra.Command, args []string) { "Endpoint": dockEndpoint, "Status": dockStatus, "StorageType": dockStorageType} resp, err := client.ListDocks(opts) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } diff --git a/osdsctl/cli/profile.go b/osdsctl/cli/profile.go index b069af4e3..de9428260 100644 --- a/osdsctl/cli/profile.go +++ b/osdsctl/cli/profile.go @@ -100,7 +100,6 @@ func profileCreateAction(cmd *cobra.Command, args []string) { } resp, err := client.CreateProfile(prf) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } @@ -111,7 +110,6 @@ func profileCreateAction(cmd *cobra.Command, args []string) { func profileShowAction(cmd *cobra.Command, args []string) { ArgsNumCheck(cmd, args, 1) resp, err := client.GetProfile(args[0]) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } @@ -126,7 +124,6 @@ func profileListAction(cmd *cobra.Command, args []string) { "Name": profName, "Description": profDescription, "StorageType": profStorageType} resp, err := client.ListProfiles(opts) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } diff --git a/osdsctl/cli/replication.go b/osdsctl/cli/replication.go index 0089498cd..bb43ed6cf 100644 --- a/osdsctl/cli/replication.go +++ b/osdsctl/cli/replication.go @@ -195,7 +195,6 @@ func replicationCreateAction(cmd *cobra.Command, args []string) { } resp, err := client.CreateReplication(replica) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } @@ -208,7 +207,6 @@ func replicationCreateAction(cmd *cobra.Command, args []string) { func replicationShowAction(cmd *cobra.Command, args []string) { ArgsNumCheck(cmd, args, 1) resp, err := client.GetReplication(args[0]) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } @@ -227,7 +225,6 @@ func replicationListAction(cmd *cobra.Command, args []string) { "SecondaryVolumeId": repSecondaryVolumeId} resp, err := client.ListReplications(opts) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } @@ -244,7 +241,6 @@ func replicationUpdateAction(cmd *cobra.Command, args []string) { } resp, err := client.UpdateReplication(args[0], replica) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } diff --git a/osdsctl/cli/version.go b/osdsctl/cli/version.go index 67a114390..6e2a8c898 100644 --- a/osdsctl/cli/version.go +++ b/osdsctl/cli/version.go @@ -56,7 +56,6 @@ func versionAction(cmd *cobra.Command, args []string) { func versionShowAction(cmd *cobra.Command, args []string) { ArgsNumCheck(cmd, args, 1) resp, err := client.GetVersion(args[0]) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } @@ -67,7 +66,6 @@ func versionShowAction(cmd *cobra.Command, args []string) { func versionListAction(cmd *cobra.Command, args []string) { ArgsNumCheck(cmd, args, 0) resp, err := client.ListVersions() - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } diff --git a/osdsctl/cli/volume.go b/osdsctl/cli/volume.go index 69df03670..ad8d21640 100644 --- a/osdsctl/cli/volume.go +++ b/osdsctl/cli/volume.go @@ -78,17 +78,18 @@ var ( ) var ( - volLimit string - volOffset string - volSortDir string - volSortKey string - volId string - volTenantId string - volUserId string - volStatus string - volPoolId string - volProfileId string - volGroupId string + volLimit string + volOffset string + volSortDir string + volSortKey string + volId string + volTenantId string + volUserId string + volStatus string + volPoolId string + volProfileId string + volGroupId string + snapshotFromCloud bool ) func init() { @@ -115,6 +116,7 @@ func init() { volumeCreateCommand.Flags().StringVarP(&volDesp, "description", "d", "", "the description of created volume") volumeCreateCommand.Flags().StringVarP(&volAz, "az", "a", "", "the availability zone of created volume") volumeCreateCommand.Flags().StringVarP(&volSnap, "snapshot", "s", "", "the snapshot to create volume") + volumeCreateCommand.Flags().BoolVarP(&snapshotFromCloud, "snapshotFromCloud", "c", false, "download snapshot from cloud") volumeCommand.AddCommand(volumeShowCommand) volumeCommand.AddCommand(volumeListCommand) volumeCommand.AddCommand(volumeDeleteCommand) @@ -141,16 +143,16 @@ func volumeCreateAction(cmd *cobra.Command, args []string) { } vol := &model.VolumeSpec{ - Name: volName, - Description: volDesp, - AvailabilityZone: volAz, - Size: int64(size), - ProfileId: profileId, - SnapshotId: volSnap, + Name: volName, + Description: volDesp, + AvailabilityZone: volAz, + Size: int64(size), + ProfileId: profileId, + SnapshotId: volSnap, + SnapshotFromCloud: snapshotFromCloud, } resp, err := client.CreateVolume(vol) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } @@ -163,7 +165,6 @@ func volumeCreateAction(cmd *cobra.Command, args []string) { func volumeShowAction(cmd *cobra.Command, args []string) { ArgsNumCheck(cmd, args, 1) resp, err := client.GetVolume(args[0]) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } @@ -181,7 +182,6 @@ func volumeListAction(cmd *cobra.Command, args []string) { "Status": volStatus, "PoolId": volPoolId, "ProfileId": volProfileId, "GroupId": volGroupId} resp, err := client.ListVolumes(opts) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } @@ -209,7 +209,6 @@ func volumeUpdateAction(cmd *cobra.Command, args []string) { } resp, err := client.UpdateVolume(args[0], vol) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } @@ -230,7 +229,6 @@ func volumeExtendAction(cmd *cobra.Command, args []string) { } resp, err := client.ExtendVolume(args[0], body) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } diff --git a/osdsctl/cli/volumeattachment.go b/osdsctl/cli/volumeattachment.go index 33d1841e7..db7b5d007 100644 --- a/osdsctl/cli/volumeattachment.go +++ b/osdsctl/cli/volumeattachment.go @@ -110,7 +110,6 @@ func volumeAttachmentCreateAction(cmd *cobra.Command, args []string) { os.Exit(1) } resp, err := client.CreateVolumeAttachment(attachment) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } @@ -122,7 +121,6 @@ func volumeAttachmentCreateAction(cmd *cobra.Command, args []string) { func volumeAttachmentShowAction(cmd *cobra.Command, args []string) { ArgsNumCheck(cmd, args, 1) resp, err := client.GetVolumeAttachment(args[0]) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } @@ -140,7 +138,6 @@ func volumeAttachmentListAction(cmd *cobra.Command, args []string) { "Status": volAtmStatus, "Mountpoint": volAtmMountpoint} resp, err := client.ListVolumeAttachments(opts) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } @@ -167,7 +164,6 @@ func volumeAttachmentUpdateAction(cmd *cobra.Command, args []string) { } resp, err := client.UpdateVolumeAttachment(args[0], attachment) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } diff --git a/osdsctl/cli/volumegroup.go b/osdsctl/cli/volumegroup.go index 0cc314876..c74f7c538 100644 --- a/osdsctl/cli/volumegroup.go +++ b/osdsctl/cli/volumegroup.go @@ -126,7 +126,6 @@ func volumeGroupCreateAction(cmd *cobra.Command, args []string) { } resp, err := client.CreateVolumeGroup(vg) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } @@ -137,7 +136,6 @@ func volumeGroupCreateAction(cmd *cobra.Command, args []string) { func volumeGroupShowAction(cmd *cobra.Command, args []string) { ArgsNumCheck(cmd, args, 1) resp, err := client.GetVolumeGroup(args[0]) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } @@ -154,7 +152,6 @@ func volumeGroupListAction(cmd *cobra.Command, args []string) { "Status": vgStatus, "PoolId": vgPoolId} resp, err := client.ListVolumeGroups(opts) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } @@ -181,7 +178,6 @@ func volumeGroupUpdateAction(cmd *cobra.Command, args []string) { } resp, err := client.UpdateVolumeGroup(args[0], snp) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } diff --git a/osdsctl/cli/volumesnapshot.go b/osdsctl/cli/volumesnapshot.go index adf78a392..463d11493 100644 --- a/osdsctl/cli/volumesnapshot.go +++ b/osdsctl/cli/volumesnapshot.go @@ -119,7 +119,6 @@ func volumeSnapshotCreateAction(cmd *cobra.Command, args []string) { } resp, err := client.CreateVolumeSnapshot(snp) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } @@ -130,7 +129,6 @@ func volumeSnapshotCreateAction(cmd *cobra.Command, args []string) { func volumeSnapshotShowAction(cmd *cobra.Command, args []string) { ArgsNumCheck(cmd, args, 1) resp, err := client.GetVolumeSnapshot(args[0]) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } @@ -147,7 +145,6 @@ func volumeSnapshotListAction(cmd *cobra.Command, args []string) { "Status": volSnapStatus, "VolumeId": volSnapVolumeId} resp, err := client.ListVolumeSnapshots(opts) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } @@ -172,7 +169,6 @@ func volumeSnapshotUpdateAction(cmd *cobra.Command, args []string) { } resp, err := client.UpdateVolumeSnapshot(args[0], snp) - PrintResponse(resp) if err != nil { Fatalln(HttpErrStrip(err)) } diff --git a/pkg/api/db.go b/pkg/api/db.go index 2ecc9d7da..1be2bdebc 100644 --- a/pkg/api/db.go +++ b/pkg/api/db.go @@ -72,14 +72,15 @@ func CreateVolumeDBEntry(ctx *c.Context, in *model.VolumeSpec) (*model.VolumeSpe Id: in.Id, CreatedAt: in.CreatedAt, }, - UserId: ctx.UserId, - Name: in.Name, - Description: in.Description, - ProfileId: in.ProfileId, - Size: in.Size, - AvailabilityZone: in.AvailabilityZone, - Status: model.VolumeCreating, - SnapshotId: in.SnapshotId, + UserId: ctx.UserId, + Name: in.Name, + Description: in.Description, + ProfileId: in.ProfileId, + Size: in.Size, + AvailabilityZone: in.AvailabilityZone, + Status: model.VolumeCreating, + SnapshotId: in.SnapshotId, + SnapshotFromCloud: in.SnapshotFromCloud, } result, err := db.C.CreateVolume(ctx, vol) if err != nil { diff --git a/pkg/api/volume.go b/pkg/api/volume.go index ae27da59f..f6edc51fa 100755 --- a/pkg/api/volume.go +++ b/pkg/api/volume.go @@ -51,7 +51,6 @@ func (this *VolumePortal) CreateVolume() { log.Error(reason) return } - // NOTE:It will create a volume entry into the database and initialize its status // as "creating". It will not wait for the real volume creation to complete // and will return result immediately. diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index 64b29bfe6..d0a73cdf2 100755 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -106,6 +106,9 @@ func (c *Controller) CreateVolume(ctx *c.Context, in *model.VolumeSpec, errchanV } snapSize = snapVol.Size in.PoolId = snapVol.PoolId + if in.SnapshotFromCloud { + in.Metadata = utils.MergeStringMaps(in.Metadata, snap.Metadata) + } } polInfo, err := c.selector.SelectSupportedPoolForVolume(in) @@ -130,18 +133,20 @@ func (c *Controller) CreateVolume(ctx *c.Context, in *model.VolumeSpec, errchanV } c.volumeController.SetDock(dockInfo) opt := &pb.CreateVolumeOpts{ - Id: in.Id, - Name: in.Name, - Description: in.Description, - Size: in.Size, - AvailabilityZone: in.AvailabilityZone, - PoolId: polInfo.Id, - ProfileId: prf.Id, - SnapshotId: in.SnapshotId, - SnapshotSize: snapSize, - PoolName: polInfo.Name, - DriverName: dockInfo.DriverName, - Context: ctx.ToJson(), + Id: in.Id, + Name: in.Name, + Description: in.Description, + Size: in.Size, + AvailabilityZone: in.AvailabilityZone, + PoolId: polInfo.Id, + ProfileId: prf.Id, + SnapshotId: in.SnapshotId, + SnapshotSize: snapSize, + PoolName: polInfo.Name, + DriverName: dockInfo.DriverName, + Context: ctx.ToJson(), + Metadata: in.Metadata, + SnapshotFromCloud: in.SnapshotFromCloud, } result, err := c.volumeController.CreateVolume(opt) diff --git a/pkg/dock/proto/dock.pb.go b/pkg/dock/proto/dock.pb.go index 81062def2..cec0addd6 100644 --- a/pkg/dock/proto/dock.pb.go +++ b/pkg/dock/proto/dock.pb.go @@ -86,6 +86,8 @@ type CreateVolumeOpts struct { ReplicationId string `protobuf:"bytes,14,opt,name=replicationId" json:"replicationId,omitempty"` // The size of snapshot SnapshotSize int64 `protobuf:"varint,15,opt,name=snapshotSize" json:"snapshotSize,omitempty"` + // Down load snapshot from cloud + SnapshotFromCloud bool `protobuf:"varint,16,opt,name=snapshotFromCloud" json:"snapshotFromCloud,omitempty"` } func (m *CreateVolumeOpts) Reset() { *m = CreateVolumeOpts{} } @@ -198,6 +200,13 @@ func (m *CreateVolumeOpts) GetSnapshotSize() int64 { return 0 } +func (m *CreateVolumeOpts) GetSnapshotFromCloud() bool { + if m != nil { + return m.SnapshotFromCloud + } + return false +} + // DeleteVolumeOpts is a structure which indicates all required properties // for deleting a volume. type DeleteVolumeOpts struct { @@ -2850,114 +2859,115 @@ var _AttachDock_serviceDesc = grpc.ServiceDesc{ func init() { proto1.RegisterFile("dock.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1729 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0xcd, 0x73, 0xdc, 0xc4, - 0x12, 0xcf, 0x4a, 0x5e, 0xef, 0x6e, 0xfb, 0x6b, 0x3d, 0xb6, 0x13, 0xd5, 0xc6, 0xf1, 0xf3, 0xdb, - 0x97, 0x97, 0xf2, 0x4b, 0xf2, 0x0c, 0x59, 0xa8, 0x0a, 0x1f, 0xc5, 0x87, 0x8d, 0x9d, 0x78, 0x8b, - 0x98, 0x38, 0x0a, 0xe4, 0xc0, 0x4d, 0x91, 0x26, 0x58, 0x65, 0xad, 0x46, 0x25, 0xc9, 0x9b, 0x98, - 0x13, 0x15, 0x38, 0x04, 0x8e, 0xdc, 0x38, 0x52, 0x1c, 0x38, 0xf1, 0x4f, 0x50, 0x14, 0x7f, 0x00, - 0x55, 0xdc, 0x72, 0xe0, 0x4a, 0x15, 0x7f, 0x42, 0x0e, 0x94, 0x66, 0x24, 0x59, 0x1f, 0xa3, 0x59, - 0x99, 0xb5, 0x1d, 0xa7, 0xe2, 0xd3, 0xae, 0x7a, 0x46, 0x3d, 0xdd, 0xbf, 0xee, 0x5f, 0x8f, 0x34, - 0x6a, 0x00, 0x83, 0xe8, 0x3b, 0xcb, 0x8e, 0x4b, 0x7c, 0x82, 0xaa, 0xf4, 0xa7, 0xfd, 0x73, 0x15, - 0x9a, 0x1f, 0xb8, 0x58, 0xf3, 0xf1, 0x3d, 0x62, 0xed, 0xf6, 0xf0, 0x6d, 0xc7, 0xf7, 0xd0, 0x24, - 0x48, 0xa6, 0xa1, 0x54, 0x16, 0x2b, 0x4b, 0x0d, 0x55, 0x32, 0x0d, 0x84, 0x60, 0xc4, 0xd6, 0x7a, - 0x58, 0x91, 0xa8, 0x84, 0xfe, 0x0f, 0x64, 0x9e, 0xf9, 0x39, 0x56, 0xe4, 0xc5, 0xca, 0x92, 0xac, - 0xd2, 0xff, 0x68, 0x11, 0xc6, 0x0c, 0xec, 0xe9, 0xae, 0xe9, 0xf8, 0x26, 0xb1, 0x95, 0x11, 0x3a, - 0x3d, 0x29, 0x42, 0x0b, 0x00, 0x9e, 0xad, 0x39, 0xde, 0x36, 0xf1, 0xbb, 0x86, 0x52, 0xa5, 0x13, - 0x12, 0x12, 0x74, 0x19, 0x9a, 0x5a, 0x5f, 0x33, 0x2d, 0xed, 0xbe, 0x69, 0x99, 0xfe, 0xde, 0xa7, - 0xc4, 0xc6, 0xca, 0x28, 0x9d, 0x95, 0x93, 0xa3, 0x79, 0x68, 0x38, 0x2e, 0x79, 0x60, 0x5a, 0xb8, - 0x6b, 0x28, 0x35, 0x3a, 0x69, 0x5f, 0x80, 0xce, 0xc2, 0xa8, 0x43, 0x88, 0xd5, 0x35, 0x94, 0x3a, - 0x1d, 0x0a, 0xaf, 0x50, 0x0b, 0xea, 0xc1, 0xbf, 0x8f, 0x02, 0x7f, 0x1a, 0x74, 0x24, 0xbe, 0x46, - 0x2b, 0x50, 0xef, 0x61, 0x5f, 0x33, 0x34, 0x5f, 0x53, 0x60, 0x51, 0x5e, 0x1a, 0xeb, 0xfc, 0x97, - 0xa1, 0xb5, 0x9c, 0x85, 0x68, 0x79, 0x33, 0x9c, 0xb7, 0x6e, 0xfb, 0xee, 0x9e, 0x1a, 0xdf, 0x16, - 0x38, 0x68, 0xb8, 0x66, 0x1f, 0xbb, 0x74, 0x81, 0x31, 0xe6, 0xe0, 0xbe, 0x04, 0x29, 0x50, 0xd3, - 0x89, 0xed, 0xe3, 0x47, 0xbe, 0x32, 0x4e, 0x07, 0xa3, 0x4b, 0xb4, 0x0d, 0x73, 0x2e, 0x76, 0x2c, - 0x53, 0xd7, 0x02, 0xa4, 0xd6, 0xe8, 0x2d, 0x6b, 0x81, 0x25, 0x13, 0xd4, 0x92, 0x4e, 0x91, 0x25, - 0x2a, 0xef, 0x26, 0x66, 0x16, 0x5f, 0x21, 0xba, 0x08, 0x13, 0x89, 0x81, 0xae, 0xa1, 0x4c, 0x52, - 0x4b, 0xd2, 0x42, 0xd4, 0x86, 0xf1, 0x28, 0x30, 0x77, 0x83, 0x40, 0x4f, 0xd1, 0x40, 0xa7, 0x64, - 0xad, 0xb7, 0x61, 0x22, 0x05, 0x04, 0x6a, 0x82, 0xbc, 0x83, 0xf7, 0xc2, 0xd4, 0x09, 0xfe, 0xa2, - 0x59, 0xa8, 0xf6, 0x35, 0x6b, 0x37, 0x4a, 0x1e, 0x76, 0xf1, 0x96, 0xf4, 0x46, 0xa5, 0xb5, 0x01, - 0xad, 0x62, 0xdb, 0x0f, 0xa2, 0xa9, 0xfd, 0xb4, 0x02, 0xcd, 0x35, 0x6c, 0x61, 0x61, 0x12, 0x27, - 0x83, 0x2b, 0xa5, 0x82, 0x9b, 0xbd, 0xb5, 0x64, 0x70, 0x65, 0x51, 0x70, 0x47, 0x52, 0xc1, 0x1d, - 0x0a, 0xa8, 0xf6, 0x2f, 0x32, 0x34, 0xd7, 0x1f, 0xf9, 0xd8, 0x36, 0x4e, 0x39, 0x2a, 0xe0, 0x68, - 0x16, 0xa2, 0xc3, 0xe7, 0xe8, 0x70, 0x61, 0xfc, 0x4d, 0x02, 0x25, 0xc9, 0xde, 0xbb, 0x21, 0xa4, - 0x47, 0x1c, 0xce, 0x16, 0xd4, 0xfb, 0x74, 0xbd, 0x38, 0x98, 0xf1, 0x35, 0xea, 0x26, 0xc0, 0x1c, - 0xa5, 0x60, 0xfe, 0x9f, 0x53, 0x66, 0x92, 0x86, 0x96, 0x04, 0xb5, 0x26, 0x02, 0xb5, 0x7e, 0x88, - 0xa0, 0x3e, 0x91, 0x40, 0x49, 0xf2, 0x57, 0x08, 0x6a, 0x12, 0x0a, 0x49, 0x00, 0x85, 0x9c, 0x82, - 0xa2, 0x48, 0x7d, 0x49, 0x28, 0x46, 0x44, 0x50, 0x54, 0x0f, 0x11, 0x8a, 0xef, 0x64, 0x98, 0x65, - 0x61, 0x5b, 0xf1, 0x7d, 0x4d, 0xdf, 0xee, 0x61, 0xfb, 0xe0, 0x30, 0x5c, 0x84, 0x09, 0x83, 0xdc, - 0x22, 0xba, 0x66, 0x31, 0x25, 0x34, 0xd9, 0xea, 0x6a, 0x5a, 0x18, 0xd0, 0xba, 0xb7, 0x6b, 0xf9, - 0xe6, 0x96, 0xe6, 0x6f, 0x53, 0x07, 0xeb, 0xea, 0xbe, 0x00, 0x5d, 0x81, 0xfa, 0x36, 0xf1, 0xfc, - 0xae, 0xfd, 0x80, 0x50, 0x07, 0xc7, 0x3a, 0x53, 0x21, 0x94, 0x1b, 0xa1, 0x58, 0x8d, 0x27, 0xa0, - 0xf5, 0x5c, 0x0a, 0xfe, 0x2f, 0x95, 0x82, 0x69, 0x5f, 0x0e, 0x3f, 0xfd, 0xd0, 0x25, 0x98, 0x5c, - 0xd1, 0x75, 0xec, 0x79, 0x5b, 0xc1, 0xaa, 0x3a, 0xb1, 0xc2, 0x92, 0x93, 0x91, 0x0e, 0x17, 0x9b, - 0xdf, 0x25, 0x98, 0x65, 0x79, 0x34, 0x44, 0x6c, 0x92, 0xb8, 0xca, 0x07, 0xc1, 0x75, 0x24, 0x85, - 0x2b, 0xcf, 0x8e, 0x92, 0xb8, 0x56, 0x45, 0xb8, 0x8e, 0x0e, 0xc2, 0xb5, 0x76, 0xf8, 0xb8, 0xfe, - 0x24, 0xc3, 0x3c, 0xcb, 0x93, 0x88, 0x99, 0x03, 0xf0, 0x4d, 0x6f, 0x6e, 0x52, 0x6e, 0x73, 0x3b, - 0xf6, 0xfc, 0xdf, 0xcc, 0xe5, 0xff, 0xb5, 0x54, 0xfe, 0xf3, 0xfd, 0x7a, 0x51, 0x79, 0xf0, 0xa7, - 0x04, 0xf3, 0x2c, 0xff, 0x0e, 0x29, 0x5e, 0x07, 0xe2, 0xc4, 0x66, 0x8e, 0x13, 0xd7, 0x52, 0x9c, - 0x18, 0x0a, 0xeb, 0x13, 0xc7, 0x8d, 0x2f, 0x2a, 0x50, 0x8f, 0x40, 0xa0, 0x8f, 0x54, 0x96, 0xe6, - 0x3f, 0x20, 0x6e, 0x2f, 0xbc, 0x3b, 0xbe, 0x0e, 0x1e, 0xc3, 0x88, 0xf7, 0xf1, 0x9e, 0x13, 0xe9, - 0x08, 0xaf, 0x82, 0xe7, 0x8d, 0x00, 0xba, 0xf0, 0x41, 0x97, 0xfe, 0xa7, 0xf1, 0x71, 0xc2, 0x3d, - 0x4d, 0x32, 0x9d, 0x80, 0x09, 0xa6, 0x6d, 0xfa, 0xa6, 0xe6, 0x13, 0x37, 0x84, 0x60, 0x5f, 0xd0, - 0xee, 0x03, 0xb0, 0x7d, 0x93, 0xbe, 0x77, 0xbc, 0x02, 0x23, 0x14, 0xfa, 0x0a, 0x85, 0xfe, 0x7c, - 0x08, 0xfd, 0xfe, 0x84, 0xe5, 0xfd, 0x37, 0x17, 0x3a, 0xb1, 0x75, 0x1d, 0x1a, 0xff, 0xec, 0x85, - 0xe0, 0x87, 0x06, 0xcc, 0x31, 0xfa, 0x24, 0xde, 0x30, 0x4a, 0x3f, 0x67, 0x65, 0x9e, 0xa9, 0xe4, - 0xfc, 0x33, 0xd5, 0x12, 0x4c, 0x39, 0xae, 0xd9, 0xd3, 0xdc, 0xbd, 0x7b, 0x51, 0xb1, 0x66, 0x90, - 0x64, 0xc5, 0xe8, 0x2a, 0x4c, 0x7b, 0x58, 0x27, 0xb6, 0x91, 0x9c, 0xcb, 0x70, 0xca, 0x0f, 0x3c, - 0xe7, 0x47, 0xeb, 0xc7, 0x15, 0x98, 0x0f, 0xed, 0xe7, 0xbe, 0x98, 0x29, 0x63, 0x34, 0x70, 0xef, - 0xa6, 0xea, 0x53, 0x06, 0xe0, 0xe5, 0x2d, 0x81, 0x02, 0x16, 0x5b, 0xe1, 0x1a, 0xe8, 0x49, 0x05, - 0x16, 0x62, 0x60, 0xf8, 0x66, 0x8c, 0x53, 0x33, 0xde, 0x17, 0x9a, 0x71, 0x57, 0xa8, 0x82, 0x19, - 0x32, 0x60, 0x9d, 0x00, 0x43, 0x83, 0xe8, 0x3b, 0x5d, 0x43, 0x99, 0x60, 0x18, 0xb2, 0xab, 0x0c, - 0xef, 0x27, 0x45, 0xbc, 0x9f, 0x4a, 0xf3, 0x3e, 0x60, 0x8b, 0x17, 0x22, 0xa4, 0x34, 0xd9, 0xbe, - 0x11, 0x0b, 0xd0, 0x8d, 0x44, 0x79, 0x9a, 0xa6, 0x3e, 0x5e, 0x16, 0xfa, 0x58, 0x54, 0x97, 0xde, - 0x84, 0xc9, 0x7e, 0x4c, 0xaa, 0x5b, 0xa6, 0xe7, 0x2b, 0x88, 0x6a, 0x9b, 0xce, 0x31, 0x4e, 0xcd, - 0x4c, 0x0c, 0x12, 0x3b, 0x71, 0x0a, 0xb0, 0x49, 0x0c, 0xac, 0xcc, 0xb0, 0xc4, 0xce, 0x88, 0x83, - 0xc4, 0x4e, 0xd8, 0xb3, 0x85, 0x5d, 0x93, 0x18, 0xca, 0x2c, 0x7d, 0x33, 0xc9, 0x0f, 0xa0, 0x0e, - 0xcc, 0x26, 0x84, 0xab, 0x9a, 0x6d, 0x3c, 0x34, 0x0d, 0x7f, 0x5b, 0x99, 0xa3, 0x37, 0x70, 0xc7, - 0x5a, 0xb7, 0xe1, 0xdf, 0x03, 0x93, 0xe9, 0x40, 0x07, 0x0e, 0x77, 0xe0, 0x3f, 0x25, 0xd2, 0xe2, - 0x40, 0x2a, 0x87, 0x2a, 0xd0, 0x4f, 0x6b, 0x30, 0xc7, 0x36, 0x9e, 0xd3, 0x2a, 0x75, 0x64, 0x55, - 0x8a, 0x0b, 0xf0, 0xf1, 0x57, 0x29, 0xbe, 0x19, 0x27, 0xb3, 0x4a, 0x25, 0xeb, 0x50, 0x33, 0x55, - 0x87, 0xf8, 0x5e, 0x14, 0xd5, 0xa1, 0x54, 0xb5, 0x9b, 0xce, 0x54, 0xbb, 0x97, 0x83, 0xde, 0xeb, - 0xb6, 0x76, 0xdf, 0x3a, 0xa5, 0xf7, 0xd1, 0xd1, 0x9b, 0x0b, 0xf0, 0xf1, 0xd3, 0x9b, 0x6f, 0xc6, - 0x8b, 0x46, 0x6f, 0xbe, 0x17, 0xa7, 0xf4, 0xe6, 0xd2, 0xfb, 0x8f, 0x1a, 0x9c, 0x5d, 0x33, 0xbd, - 0x53, 0x7e, 0x1f, 0x8c, 0xdf, 0x5f, 0x96, 0xe3, 0xf7, 0x7b, 0xd1, 0x8e, 0xc3, 0x45, 0x78, 0x68, - 0x82, 0x7f, 0x5d, 0x96, 0xe0, 0x2b, 0x62, 0x3b, 0x4e, 0x26, 0xc3, 0x6f, 0xe6, 0x18, 0x7e, 0x45, - 0xec, 0xc6, 0x29, 0xc5, 0xb9, 0x14, 0xff, 0xb5, 0x0e, 0xe7, 0x6e, 0x68, 0xa6, 0x45, 0xfa, 0xd8, - 0x3d, 0xe5, 0x78, 0x79, 0x8e, 0x7f, 0x55, 0x8e, 0xe3, 0xd1, 0xe6, 0x59, 0x00, 0xf1, 0xd0, 0x24, - 0xff, 0xa6, 0x2c, 0xc9, 0x57, 0x07, 0x18, 0x72, 0x32, 0x59, 0xfe, 0x2a, 0xcc, 0x68, 0x96, 0x45, - 0x1e, 0xb2, 0xd3, 0x4a, 0x1c, 0x7e, 0xf9, 0x0c, 0x8f, 0x15, 0x78, 0x43, 0x68, 0x19, 0x50, 0x6c, - 0xe5, 0xaa, 0xa6, 0xef, 0x60, 0xdb, 0xe8, 0x1a, 0x94, 0xd7, 0x0d, 0x95, 0x33, 0x82, 0x36, 0x12, - 0x75, 0x84, 0x1d, 0x21, 0x5c, 0x1d, 0x80, 0x54, 0xa9, 0x42, 0x32, 0xf3, 0xd2, 0x15, 0x92, 0xef, - 0xa5, 0xe8, 0x3c, 0x92, 0x45, 0xe2, 0xa6, 0x4b, 0x76, 0x9d, 0xd2, 0x65, 0x64, 0x50, 0xdb, 0xc1, - 0xe0, 0x6f, 0xc0, 0xbc, 0x72, 0x50, 0x2d, 0x28, 0x07, 0x0b, 0x00, 0x9a, 0x11, 0x66, 0x8c, 0x47, - 0x3f, 0x49, 0x34, 0xd4, 0x84, 0x84, 0x75, 0x8f, 0xf4, 0x48, 0x1f, 0x47, 0x53, 0x6a, 0x74, 0x4a, - 0x5a, 0x58, 0x58, 0x36, 0x12, 0xe9, 0xdc, 0x48, 0xa5, 0x73, 0xfb, 0xc7, 0x0a, 0xcc, 0x7d, 0xe2, - 0x18, 0x25, 0x30, 0x4a, 0xe3, 0x21, 0xe5, 0xf0, 0x48, 0x7b, 0x20, 0x0f, 0xf6, 0x60, 0x84, 0xe7, - 0x41, 0xe1, 0x57, 0xda, 0xb6, 0x16, 0x1d, 0xdb, 0x0c, 0x6b, 0x68, 0x62, 0x09, 0x39, 0xbd, 0xc4, - 0xb3, 0x0a, 0x34, 0x19, 0x79, 0x13, 0x2d, 0x1f, 0x97, 0x60, 0x52, 0x4b, 0x7f, 0x35, 0x60, 0x4b, - 0x65, 0xa4, 0xc1, 0x3c, 0x9d, 0xd8, 0x36, 0xd6, 0x69, 0xce, 0xb3, 0x7e, 0x17, 0x3a, 0x2f, 0x2d, - 0x4d, 0xb5, 0x52, 0xc8, 0xa9, 0x56, 0x8a, 0xec, 0xd2, 0x85, 0xbc, 0x3e, 0xa2, 0x8e, 0x97, 0x67, - 0xb4, 0xa1, 0xe7, 0xb9, 0xb9, 0x9f, 0x5d, 0xfa, 0xb8, 0xdd, 0xff, 0xab, 0x02, 0x53, 0x37, 0xb1, - 0x8d, 0x5d, 0x53, 0x57, 0xb1, 0xe7, 0x10, 0xdb, 0xc3, 0xe8, 0x3a, 0x8c, 0xba, 0xd8, 0xdb, 0xb5, - 0x7c, 0xaa, 0x62, 0xac, 0x73, 0x21, 0xb4, 0x35, 0x33, 0x6f, 0x59, 0xa5, 0x93, 0x36, 0xce, 0xa8, - 0xe1, 0x74, 0xf4, 0x3a, 0x54, 0xb1, 0xeb, 0x12, 0x97, 0x2e, 0x33, 0xd6, 0x99, 0x2f, 0xb8, 0x6f, - 0x3d, 0x98, 0xb3, 0x71, 0x46, 0x65, 0x93, 0x5b, 0x6d, 0x18, 0x65, 0x9a, 0x02, 0x1f, 0x7b, 0xd8, - 0xf3, 0xb4, 0xcf, 0x70, 0x68, 0x7c, 0x74, 0xd9, 0x7a, 0x07, 0xaa, 0xf4, 0xae, 0xa0, 0x68, 0xe9, - 0xc4, 0x88, 0xc6, 0xe9, 0xff, 0x6c, 0x51, 0x92, 0x72, 0x45, 0x69, 0xb5, 0x06, 0x55, 0x17, 0x3b, - 0xd6, 0x5e, 0xe7, 0x71, 0x03, 0x26, 0xb6, 0x5c, 0xd2, 0x37, 0xbd, 0x20, 0x34, 0x44, 0xdf, 0x41, - 0x2b, 0x30, 0x9e, 0x2c, 0x97, 0xe8, 0x5c, 0x41, 0xf3, 0x5b, 0xeb, 0x2c, 0xdf, 0x9b, 0xf6, 0x99, - 0x40, 0x45, 0x92, 0xa4, 0xb1, 0x8a, 0x6c, 0xb3, 0x97, 0x58, 0x45, 0xb2, 0xa7, 0x28, 0x56, 0x91, - 0x6d, 0x34, 0x12, 0xa8, 0xb8, 0x13, 0xb5, 0x64, 0xa4, 0xdb, 0x47, 0xd0, 0xbf, 0x06, 0xb4, 0xd9, - 0x88, 0x55, 0xf2, 0x3a, 0x52, 0x62, 0x95, 0x45, 0xed, 0x2a, 0x02, 0x95, 0xdd, 0xa8, 0x07, 0x74, - 0xff, 0xc3, 0x27, 0x3a, 0x2f, 0xe8, 0xc2, 0x10, 0xab, 0xca, 0xf6, 0x17, 0xc4, 0xaa, 0x78, 0x8d, - 0x07, 0x02, 0x55, 0x1f, 0xc2, 0x74, 0xee, 0xbb, 0x07, 0x9a, 0x17, 0x7d, 0x11, 0x11, 0x2b, 0xcb, - 0x1d, 0x5e, 0xc6, 0xca, 0xb8, 0xc7, 0x9a, 0x62, 0x65, 0xb9, 0xa3, 0x92, 0x58, 0x19, 0xf7, 0x10, - 0x45, 0xa0, 0x6c, 0x13, 0x50, 0xfe, 0xad, 0x0c, 0x5d, 0x10, 0xbe, 0xb0, 0x09, 0xd4, 0xdd, 0x86, - 0x19, 0xce, 0xc3, 0x19, 0x5a, 0x10, 0x3f, 0xb8, 0x95, 0x09, 0x43, 0x62, 0xb7, 0xcb, 0x84, 0x21, - 0xb3, 0x0f, 0x8a, 0x95, 0xe5, 0xf6, 0xf8, 0x58, 0x19, 0x77, 0xf7, 0x2f, 0x13, 0x53, 0x9e, 0x32, - 0xee, 0x0e, 0x5d, 0xac, 0xac, 0xf3, 0x6d, 0x05, 0x80, 0xa5, 0x66, 0x54, 0x81, 0x92, 0x9b, 0x60, - 0xcc, 0xfd, 0xec, 0xce, 0x38, 0xa8, 0x02, 0x71, 0x54, 0x64, 0x77, 0x97, 0x62, 0x15, 0xf7, 0x47, - 0xe9, 0xc0, 0x6b, 0x7f, 0x07, 0x00, 0x00, 0xff, 0xff, 0x8a, 0x10, 0x4d, 0x50, 0xb9, 0x2d, 0x00, + // 1745 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0xcd, 0x73, 0xdb, 0x44, + 0x14, 0xaf, 0xe5, 0x38, 0xb6, 0x5f, 0xbe, 0x9c, 0x4d, 0xd2, 0x6a, 0xdc, 0x34, 0x04, 0x53, 0x3a, + 0xa1, 0x2d, 0x81, 0x1a, 0x66, 0xca, 0xc7, 0xf0, 0x91, 0x34, 0x69, 0xe3, 0xa1, 0xa1, 0xa9, 0x0a, + 0x3d, 0x70, 0x53, 0xa5, 0x2d, 0xd1, 0x44, 0xd6, 0x6a, 0x24, 0xc5, 0x6d, 0x38, 0x31, 0x85, 0x43, + 0xe1, 0xc8, 0x8d, 0x23, 0xc3, 0x81, 0x13, 0xff, 0x05, 0xc3, 0x1f, 0xc0, 0x0c, 0xb7, 0x1e, 0xb8, + 0x32, 0xc3, 0x81, 0x3f, 0xa0, 0x07, 0x46, 0xbb, 0x92, 0xac, 0x8f, 0xd5, 0x5a, 0xc1, 0x49, 0x9a, + 0x4e, 0x73, 0xb2, 0xf5, 0x76, 0xf5, 0xf6, 0xbd, 0xdf, 0xbe, 0xdf, 0xdb, 0x0f, 0x3d, 0x00, 0x9d, + 0x68, 0x3b, 0xcb, 0xb6, 0x43, 0x3c, 0x82, 0x2a, 0xf4, 0xa7, 0xf5, 0x6f, 0x05, 0x1a, 0xd7, 0x1c, + 0xac, 0x7a, 0xf8, 0x2e, 0x31, 0x77, 0xbb, 0xf8, 0x96, 0xed, 0xb9, 0x68, 0x12, 0x24, 0x43, 0x97, + 0x4b, 0x8b, 0xa5, 0xa5, 0xba, 0x22, 0x19, 0x3a, 0x42, 0x30, 0x62, 0xa9, 0x5d, 0x2c, 0x4b, 0x54, + 0x42, 0xff, 0xfb, 0x32, 0xd7, 0xf8, 0x0a, 0xcb, 0xe5, 0xc5, 0xd2, 0x52, 0x59, 0xa1, 0xff, 0xd1, + 0x22, 0x8c, 0xe9, 0xd8, 0xd5, 0x1c, 0xc3, 0xf6, 0x0c, 0x62, 0xc9, 0x23, 0xb4, 0x7b, 0x5c, 0x84, + 0x16, 0x00, 0x5c, 0x4b, 0xb5, 0xdd, 0x6d, 0xe2, 0x75, 0x74, 0xb9, 0x42, 0x3b, 0xc4, 0x24, 0xe8, + 0x22, 0x34, 0xd4, 0x9e, 0x6a, 0x98, 0xea, 0x3d, 0xc3, 0x34, 0xbc, 0xbd, 0x2f, 0x88, 0x85, 0xe5, + 0x51, 0xda, 0x2b, 0x23, 0x47, 0xf3, 0x50, 0xb7, 0x1d, 0x72, 0xdf, 0x30, 0x71, 0x47, 0x97, 0xab, + 0xb4, 0x53, 0x5f, 0x80, 0x4e, 0xc3, 0xa8, 0x4d, 0x88, 0xd9, 0xd1, 0xe5, 0x1a, 0x6d, 0x0a, 0x9e, + 0x50, 0x13, 0x6a, 0xfe, 0xbf, 0x4f, 0x7d, 0x7f, 0xea, 0xb4, 0x25, 0x7a, 0x46, 0x2b, 0x50, 0xeb, + 0x62, 0x4f, 0xd5, 0x55, 0x4f, 0x95, 0x61, 0xb1, 0xbc, 0x34, 0xd6, 0x7e, 0x95, 0xa1, 0xb5, 0x9c, + 0x86, 0x68, 0x79, 0x33, 0xe8, 0xb7, 0x6e, 0x79, 0xce, 0x9e, 0x12, 0xbd, 0xe6, 0x3b, 0xa8, 0x3b, + 0x46, 0x0f, 0x3b, 0x74, 0x80, 0x31, 0xe6, 0x60, 0x5f, 0x82, 0x64, 0xa8, 0x6a, 0xc4, 0xf2, 0xf0, + 0x43, 0x4f, 0x1e, 0xa7, 0x8d, 0xe1, 0x23, 0xda, 0x86, 0x39, 0x07, 0xdb, 0xa6, 0xa1, 0xa9, 0x3e, + 0x52, 0x6b, 0xf4, 0x95, 0x35, 0xdf, 0x92, 0x09, 0x6a, 0x49, 0x3b, 0xcf, 0x12, 0x85, 0xf7, 0x12, + 0x33, 0x8b, 0xaf, 0x10, 0x9d, 0x87, 0x89, 0x58, 0x43, 0x47, 0x97, 0x27, 0xa9, 0x25, 0x49, 0x21, + 0x6a, 0xc1, 0x78, 0x38, 0x31, 0x77, 0xfc, 0x89, 0x9e, 0xa2, 0x13, 0x9d, 0x90, 0xa1, 0xcb, 0x30, + 0x1d, 0x3e, 0x5f, 0x77, 0x48, 0xf7, 0x9a, 0x49, 0x76, 0x75, 0xb9, 0xb1, 0x58, 0x5a, 0xaa, 0x29, + 0xd9, 0x86, 0xe6, 0xfb, 0x30, 0x91, 0x80, 0x0d, 0x35, 0xa0, 0xbc, 0x83, 0xf7, 0x82, 0x40, 0xf3, + 0xff, 0xa2, 0x59, 0xa8, 0xf4, 0x54, 0x73, 0x37, 0x0c, 0x35, 0xf6, 0xf0, 0x9e, 0xf4, 0x4e, 0xa9, + 0xb9, 0x01, 0xcd, 0x7c, 0x4f, 0xf7, 0xa3, 0xa9, 0xf5, 0xa4, 0x04, 0x8d, 0x35, 0x6c, 0x62, 0x61, + 0xc8, 0xc7, 0x43, 0x41, 0x4a, 0x84, 0x42, 0xfa, 0xd5, 0x82, 0xa1, 0x50, 0x16, 0x85, 0xc2, 0x48, + 0x22, 0x14, 0x86, 0x02, 0xaa, 0xf5, 0x5b, 0x19, 0x1a, 0xeb, 0x0f, 0x3d, 0x6c, 0xe9, 0x27, 0x8c, + 0x16, 0x30, 0x3a, 0x0d, 0xd1, 0xc1, 0x33, 0x7a, 0xb8, 0x69, 0xfc, 0x43, 0x02, 0x39, 0xce, 0xf5, + 0x3b, 0x01, 0xa4, 0x87, 0x3c, 0x9d, 0x4d, 0xa8, 0xf5, 0xe8, 0x78, 0xd1, 0x64, 0x46, 0xcf, 0xa8, + 0x13, 0x03, 0x73, 0x94, 0x82, 0xf9, 0x3a, 0x27, 0x29, 0xc5, 0x0d, 0x2d, 0x08, 0x6a, 0x55, 0x04, + 0x6a, 0xed, 0x00, 0x41, 0x7d, 0x2c, 0x81, 0x1c, 0xe7, 0xaf, 0x10, 0xd4, 0x38, 0x14, 0x92, 0x00, + 0x8a, 0x72, 0x02, 0x8a, 0x3c, 0xf5, 0x05, 0xa1, 0x18, 0x11, 0x41, 0x51, 0x39, 0x40, 0x28, 0x7e, + 0x2c, 0xc3, 0x2c, 0x9b, 0xb6, 0x15, 0xcf, 0x53, 0xb5, 0xed, 0x2e, 0xb6, 0xf6, 0x0f, 0xc3, 0x79, + 0x98, 0xd0, 0xc9, 0x4d, 0xa2, 0xa9, 0x26, 0x53, 0x42, 0x83, 0xad, 0xa6, 0x24, 0x85, 0x3e, 0xad, + 0xbb, 0xbb, 0xa6, 0x67, 0x6c, 0xa9, 0xde, 0x36, 0x75, 0xb0, 0xa6, 0xf4, 0x05, 0xe8, 0x12, 0xd4, + 0xb6, 0x89, 0xeb, 0x75, 0xac, 0xfb, 0x84, 0x3a, 0x38, 0xd6, 0x9e, 0x0a, 0xa0, 0xdc, 0x08, 0xc4, + 0x4a, 0xd4, 0x01, 0xad, 0x67, 0x42, 0xf0, 0xb5, 0x44, 0x08, 0x26, 0x7d, 0x39, 0xf8, 0xf0, 0x43, + 0x17, 0x60, 0x72, 0x45, 0xd3, 0xb0, 0xeb, 0x6e, 0xf9, 0xa3, 0x6a, 0xc4, 0x0c, 0x52, 0x4e, 0x4a, + 0x3a, 0xdc, 0xdc, 0xfc, 0x29, 0xc1, 0x2c, 0x8b, 0xa3, 0x21, 0xe6, 0x26, 0x8e, 0x6b, 0x79, 0x3f, + 0xb8, 0x8e, 0x24, 0x70, 0xe5, 0xd9, 0x51, 0x10, 0xd7, 0x8a, 0x08, 0xd7, 0xd1, 0x41, 0xb8, 0x56, + 0x0f, 0x1e, 0xd7, 0x5f, 0xcb, 0x30, 0xcf, 0xe2, 0x24, 0x64, 0xe6, 0x00, 0x7c, 0x93, 0x8b, 0x9b, + 0x94, 0x59, 0xdc, 0x8e, 0x3c, 0xfe, 0x37, 0x33, 0xf1, 0x7f, 0x25, 0x11, 0xff, 0x7c, 0xbf, 0x9e, + 0x57, 0x1e, 0xfc, 0x2d, 0xc1, 0x3c, 0x8b, 0xbf, 0x03, 0x9a, 0xaf, 0x7d, 0x71, 0x62, 0x33, 0xc3, + 0x89, 0x2b, 0x09, 0x4e, 0x0c, 0x85, 0xf5, 0xb1, 0xe3, 0xc6, 0xd7, 0x25, 0xa8, 0x85, 0x20, 0xd0, + 0x2d, 0x95, 0xa9, 0x7a, 0xf7, 0x89, 0xd3, 0x0d, 0xde, 0x8e, 0x9e, 0xfd, 0x6d, 0x18, 0x71, 0x3f, + 0xdb, 0xb3, 0x43, 0x1d, 0xc1, 0x93, 0xbf, 0xdf, 0xf0, 0xa1, 0x0b, 0x36, 0xba, 0xf4, 0x3f, 0x9d, + 0x1f, 0x3b, 0x58, 0xd3, 0x24, 0xc3, 0xf6, 0x99, 0x60, 0x58, 0x86, 0x67, 0xa8, 0x1e, 0x71, 0x02, + 0x08, 0xfa, 0x82, 0x56, 0x0f, 0x80, 0xad, 0x9b, 0xf4, 0x94, 0xf2, 0x06, 0x8c, 0x50, 0xe8, 0x4b, + 0x14, 0xfa, 0xb3, 0x01, 0xf4, 0xfd, 0x0e, 0xcb, 0xfd, 0x73, 0x0e, 0xed, 0xd8, 0xbc, 0x0a, 0xf5, + 0xff, 0x77, 0x20, 0xf8, 0xb9, 0x0e, 0x73, 0x8c, 0x3e, 0xb1, 0x13, 0x46, 0xe1, 0x7d, 0x56, 0x6a, + 0x4f, 0x55, 0xce, 0xee, 0xa9, 0x96, 0x60, 0xca, 0x76, 0x8c, 0xae, 0xea, 0xec, 0xdd, 0x0d, 0x93, + 0x35, 0x83, 0x24, 0x2d, 0xa6, 0xe7, 0x29, 0xac, 0x11, 0x4b, 0x8f, 0xf7, 0x65, 0x38, 0x65, 0x1b, + 0x9e, 0xf1, 0xd6, 0xfa, 0x51, 0x09, 0xe6, 0x03, 0xfb, 0xb9, 0x07, 0x33, 0x79, 0x8c, 0x4e, 0xdc, + 0x87, 0x89, 0xfc, 0x94, 0x02, 0x78, 0x79, 0x4b, 0xa0, 0x80, 0xcd, 0xad, 0x70, 0x0c, 0xf4, 0xb8, + 0x04, 0x0b, 0x11, 0x30, 0x7c, 0x33, 0xc6, 0xa9, 0x19, 0x1f, 0x0b, 0xcd, 0xb8, 0x23, 0x54, 0xc1, + 0x0c, 0x19, 0x30, 0x8e, 0x8f, 0xa1, 0x4e, 0xb4, 0x9d, 0x8e, 0x2e, 0x4f, 0x30, 0x0c, 0xd9, 0x53, + 0x8a, 0xf7, 0x93, 0x22, 0xde, 0x4f, 0x25, 0x79, 0xef, 0xb3, 0xc5, 0x0d, 0x10, 0x0a, 0x4e, 0xd5, + 0x7d, 0x01, 0xba, 0x1e, 0x4b, 0x4f, 0xd3, 0xd4, 0xc7, 0x8b, 0x42, 0x1f, 0xf3, 0xf2, 0xd2, 0xbb, + 0x30, 0xd9, 0x8b, 0x48, 0x75, 0xd3, 0x70, 0x3d, 0x19, 0x51, 0x6d, 0xd3, 0x19, 0xc6, 0x29, 0xa9, + 0x8e, 0x7e, 0x60, 0xc7, 0xee, 0x0c, 0x36, 0x89, 0x8e, 0xe5, 0x19, 0x16, 0xd8, 0x29, 0xb1, 0x1f, + 0xd8, 0x31, 0x7b, 0xb6, 0xb0, 0x63, 0x10, 0x5d, 0x9e, 0xa5, 0x27, 0x93, 0x6c, 0x03, 0x6a, 0xc3, + 0x6c, 0x4c, 0xb8, 0xaa, 0x5a, 0xfa, 0x03, 0x43, 0xf7, 0xb6, 0xe5, 0x39, 0xfa, 0x02, 0xb7, 0xad, + 0x79, 0x0b, 0x5e, 0x1e, 0x18, 0x4c, 0xfb, 0xba, 0x70, 0xb8, 0x0d, 0xaf, 0x14, 0x08, 0x8b, 0x7d, + 0xa9, 0x1c, 0x2a, 0x41, 0x3f, 0xa9, 0xc2, 0x1c, 0x5b, 0x78, 0x4e, 0xb2, 0xd4, 0xa1, 0x65, 0x29, + 0x2e, 0xc0, 0x47, 0x9f, 0xa5, 0xf8, 0x66, 0x1c, 0xcf, 0x2c, 0x15, 0xcf, 0x43, 0x8d, 0x44, 0x1e, + 0xe2, 0x7b, 0x91, 0x97, 0x87, 0x12, 0xd9, 0x6e, 0x3a, 0x95, 0xed, 0x5e, 0x0c, 0x7a, 0xaf, 0x5b, + 0xea, 0x3d, 0xf3, 0x84, 0xde, 0x87, 0x47, 0x6f, 0x2e, 0xc0, 0x47, 0x4f, 0x6f, 0xbe, 0x19, 0xcf, + 0x1b, 0xbd, 0xf9, 0x5e, 0x9c, 0xd0, 0x9b, 0x4b, 0xef, 0xbf, 0xaa, 0x70, 0x7a, 0xcd, 0x70, 0x4f, + 0xf8, 0xbd, 0x3f, 0x7e, 0x7f, 0x53, 0x8c, 0xdf, 0x1f, 0x85, 0x2b, 0x0e, 0x17, 0xe1, 0xa1, 0x09, + 0xfe, 0x5d, 0x51, 0x82, 0xaf, 0x88, 0xed, 0x38, 0x9e, 0x0c, 0xbf, 0x91, 0x61, 0xf8, 0x25, 0xb1, + 0x1b, 0x27, 0x14, 0xe7, 0x52, 0xfc, 0xf7, 0x1a, 0x9c, 0xb9, 0xae, 0x1a, 0x26, 0xe9, 0x61, 0xe7, + 0x84, 0xe3, 0xc5, 0x39, 0xfe, 0x6d, 0x31, 0x8e, 0x87, 0x8b, 0x67, 0x0e, 0xc4, 0x43, 0x93, 0xfc, + 0xfb, 0xa2, 0x24, 0x5f, 0x1d, 0x60, 0xc8, 0xf1, 0x64, 0xf9, 0x9b, 0x30, 0xa3, 0x9a, 0x26, 0x79, + 0xc0, 0x6e, 0x2b, 0x71, 0xf0, 0xe5, 0x33, 0xb8, 0x56, 0xe0, 0x35, 0xa1, 0x65, 0x40, 0x91, 0x95, + 0xab, 0xaa, 0xb6, 0x83, 0x2d, 0xbd, 0xa3, 0x53, 0x5e, 0xd7, 0x15, 0x4e, 0x0b, 0xda, 0x88, 0xe5, + 0x11, 0x76, 0x85, 0x70, 0x79, 0x00, 0x52, 0x85, 0x12, 0xc9, 0xcc, 0x0b, 0x97, 0x48, 0x7e, 0x92, + 0xc2, 0xfb, 0x48, 0x36, 0x13, 0x37, 0x1c, 0xb2, 0x6b, 0x17, 0x4e, 0x23, 0x83, 0xca, 0x0e, 0x06, + 0x7f, 0x03, 0xe6, 0xa5, 0x83, 0x4a, 0x4e, 0x3a, 0x58, 0x00, 0x50, 0xf5, 0x20, 0x62, 0x5c, 0xfa, + 0x49, 0xa2, 0xae, 0xc4, 0x24, 0xac, 0xd6, 0xa4, 0x4b, 0x7a, 0x38, 0xec, 0x52, 0xa5, 0x5d, 0x92, + 0xc2, 0xdc, 0xb4, 0x11, 0x0b, 0xe7, 0x7a, 0x22, 0x9c, 0x5b, 0xbf, 0x94, 0x60, 0xee, 0x73, 0x5b, + 0x2f, 0x80, 0x51, 0x12, 0x0f, 0x29, 0x83, 0x47, 0xd2, 0x83, 0xf2, 0x60, 0x0f, 0x46, 0x78, 0x1e, + 0xe4, 0x7e, 0xa5, 0x6d, 0xa9, 0xe1, 0xb5, 0xcd, 0xb0, 0x86, 0xc6, 0x86, 0x28, 0x27, 0x87, 0x78, + 0x5a, 0x82, 0x06, 0x23, 0x6f, 0xac, 0xe4, 0xe3, 0x02, 0x4c, 0xaa, 0xc9, 0xaf, 0x06, 0x6c, 0xa8, + 0x94, 0xd4, 0xef, 0xa7, 0x11, 0xcb, 0xc2, 0x1a, 0x8d, 0x79, 0x56, 0xef, 0x42, 0xfb, 0x25, 0xa5, + 0x89, 0x52, 0x8a, 0x72, 0xa2, 0x94, 0x22, 0x3d, 0x74, 0x2e, 0xaf, 0x0f, 0xa9, 0xe2, 0xe5, 0x29, + 0x2d, 0xe8, 0x79, 0x66, 0xee, 0xa7, 0x87, 0x3e, 0x6a, 0xf7, 0xff, 0x29, 0xc1, 0xd4, 0x0d, 0x6c, + 0x61, 0xc7, 0xd0, 0x14, 0xec, 0xda, 0xc4, 0x72, 0x31, 0xba, 0x0a, 0xa3, 0x0e, 0x76, 0x77, 0x4d, + 0x8f, 0xaa, 0x18, 0x6b, 0x9f, 0x0b, 0x6c, 0x4d, 0xf5, 0x5b, 0x56, 0x68, 0xa7, 0x8d, 0x53, 0x4a, + 0xd0, 0x1d, 0xbd, 0x0d, 0x15, 0xec, 0x38, 0xc4, 0xa1, 0xc3, 0x8c, 0xb5, 0xe7, 0x73, 0xde, 0x5b, + 0xf7, 0xfb, 0x6c, 0x9c, 0x52, 0x58, 0xe7, 0x66, 0x0b, 0x46, 0x99, 0x26, 0xdf, 0xc7, 0x2e, 0x76, + 0x5d, 0xf5, 0x4b, 0x1c, 0x18, 0x1f, 0x3e, 0x36, 0x3f, 0x80, 0x0a, 0x7d, 0xcb, 0x4f, 0x5a, 0x1a, + 0xd1, 0xc3, 0x76, 0xfa, 0x3f, 0x9d, 0x94, 0xa4, 0x4c, 0x52, 0x5a, 0xad, 0x42, 0xc5, 0xc1, 0xb6, + 0xb9, 0xd7, 0x7e, 0x54, 0x87, 0x89, 0x2d, 0x87, 0xf4, 0x0c, 0xd7, 0x9f, 0x1a, 0xa2, 0xed, 0xa0, + 0x15, 0x18, 0x8f, 0xa7, 0x4b, 0x74, 0x26, 0xa7, 0x54, 0xae, 0x79, 0x9a, 0xef, 0x4d, 0xeb, 0x94, + 0xaf, 0x22, 0x4e, 0xd2, 0x48, 0x45, 0xba, 0xd8, 0x4b, 0xac, 0x22, 0x5e, 0x53, 0x14, 0xa9, 0x48, + 0x17, 0x1a, 0x09, 0x54, 0xdc, 0x0e, 0x4b, 0x32, 0x92, 0xe5, 0x23, 0xe8, 0xa5, 0x01, 0x65, 0x36, + 0x62, 0x95, 0xbc, 0x8a, 0x94, 0x48, 0x65, 0x5e, 0xb9, 0x8a, 0x40, 0x65, 0x27, 0xac, 0x18, 0xed, + 0x7f, 0xf8, 0x44, 0x67, 0x05, 0x55, 0x18, 0x62, 0x55, 0xe9, 0xfa, 0x82, 0x48, 0x15, 0xaf, 0xf0, + 0x40, 0xa0, 0xea, 0x13, 0x98, 0xce, 0x7c, 0xf7, 0x40, 0xf3, 0xa2, 0x2f, 0x22, 0x62, 0x65, 0x99, + 0xcb, 0xcb, 0x48, 0x19, 0xf7, 0x5a, 0x53, 0xac, 0x2c, 0x73, 0x55, 0x12, 0x29, 0xe3, 0x5e, 0xa2, + 0x08, 0x94, 0x6d, 0x02, 0xca, 0x9e, 0xca, 0xd0, 0x39, 0xe1, 0x81, 0x4d, 0xa0, 0xee, 0x16, 0xcc, + 0x70, 0x36, 0x67, 0x68, 0x41, 0xbc, 0x71, 0x2b, 0x32, 0x0d, 0xb1, 0xd5, 0x2e, 0x35, 0x0d, 0xa9, + 0x75, 0x50, 0xac, 0x2c, 0xb3, 0xc6, 0x47, 0xca, 0xb8, 0xab, 0x7f, 0x91, 0x39, 0xe5, 0x29, 0xe3, + 0xae, 0xd0, 0xf9, 0xca, 0xda, 0x3f, 0x94, 0x00, 0x58, 0x68, 0x86, 0x19, 0x28, 0xbe, 0x08, 0x46, + 0xdc, 0x4f, 0xaf, 0x8c, 0x83, 0x32, 0x10, 0x47, 0x45, 0x7a, 0x75, 0xc9, 0x57, 0x71, 0x6f, 0x94, + 0x36, 0xbc, 0xf5, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf2, 0xc0, 0xba, 0xdf, 0xe7, 0x2d, 0x00, 0x00, } diff --git a/pkg/dock/proto/dock.proto b/pkg/dock/proto/dock.proto index 726fe837a..2d067f75a 100755 --- a/pkg/dock/proto/dock.proto +++ b/pkg/dock/proto/dock.proto @@ -114,6 +114,8 @@ message CreateVolumeOpts { string replicationId = 14; // The size of snapshot int64 snapshotSize = 15; + // Down load snapshot from cloud + bool snapshotFromCloud = 16; } // DeleteVolumeOpts is a structure which indicates all required properties diff --git a/pkg/model/volume.go b/pkg/model/volume.go index 8c7b9439f..ee9c48890 100755 --- a/pkg/model/volume.go +++ b/pkg/model/volume.go @@ -71,6 +71,9 @@ type VolumeSpec struct { // The uuid of the snapshot which the volume is created SnapshotId string `json:"snapshotId, omitempty"` + // Download Snapshot From Cloud + SnapshotFromCloud bool `json:"snapshotFromCloud, omitempty"` + // The uuid of the replication which the volume belongs to. ReplicationId string `json:"replicationId,omitempty"` From 41e0cec85d7fb380bcd867e5a83e5658a7c017dd Mon Sep 17 00:00:00 2001 From: jerry Date: Thu, 22 Nov 2018 20:21:07 +0800 Subject: [PATCH 13/20] make log flushing shorter, and fixed some flag bugs --- cmd/osdsdock/osdsdock.go | 3 ++- cmd/osdslet/osdslet.go | 3 ++- pkg/api/filter/accesslog/accesslog.go | 29 +++++++++++++++++++++++ pkg/api/router.go | 2 ++ pkg/utils/config/config_define.go | 15 +++++++----- pkg/utils/config/flag.go | 33 +++++++++------------------ pkg/utils/logs/logs.go | 26 +++++++++++++++++++++ 7 files changed, 81 insertions(+), 30 deletions(-) create mode 100644 pkg/api/filter/accesslog/accesslog.go diff --git a/cmd/osdsdock/osdsdock.go b/cmd/osdsdock/osdsdock.go index 2d15113fe..16244c185 100755 --- a/cmd/osdsdock/osdsdock.go +++ b/cmd/osdsdock/osdsdock.go @@ -30,12 +30,13 @@ import ( func init() { def := GetDefaultConfig() - flag := CONF.Flag + flag := &CONF.Flag flag.StringVar(&CONF.OsdsDock.ApiEndpoint, "api-endpoint", def.OsdsDock.ApiEndpoint, "Listen endpoint of dock service") flag.StringVar(&CONF.OsdsDock.DockType, "dock-type", def.OsdsDock.DockType, "Type of dock service") flag.StringVar(&CONF.Database.Endpoint, "db-endpoint", def.Database.Endpoint, "Connection endpoint of database service") flag.StringVar(&CONF.Database.Driver, "db-driver", def.Database.Driver, "Driver name of database service") // flag.StringVar(&CONF.Database.Credential, "db-credential", def.Database.Credential, "Connection credential of database service") + flag.DurationVar(&CONF.OsdsLet.LogFlushFrequency, "log-flush-frequency", def.OsdsLet.LogFlushFrequency, "Maximum number of seconds between log flushes") daemon.SetDaemonFlag(&CONF.OsdsDock.Daemon, def.OsdsDock.Daemon) CONF.Load("/etc/opensds/opensds.conf") daemon.CheckAndRunDaemon(CONF.OsdsDock.Daemon) diff --git a/cmd/osdslet/osdslet.go b/cmd/osdslet/osdslet.go index 429a21e8b..cdcaa4695 100755 --- a/cmd/osdslet/osdslet.go +++ b/cmd/osdslet/osdslet.go @@ -30,11 +30,12 @@ import ( func init() { def := GetDefaultConfig() - flag := CONF.Flag + flag := &CONF.Flag flag.StringVar(&CONF.OsdsLet.ApiEndpoint, "api-endpoint", def.OsdsLet.ApiEndpoint, "Listen endpoint of controller service") flag.StringVar(&CONF.Database.Endpoint, "db-endpoint", def.Database.Endpoint, "Connection endpoint of database service") flag.StringVar(&CONF.Database.Driver, "db-driver", def.Database.Driver, "Driver name of database service") flag.StringVar(&CONF.Database.Credential, "db-credential", def.Database.Credential, "Connection credential of database service") + flag.DurationVar(&CONF.OsdsLet.LogFlushFrequency, "log-flush-frequency", def.OsdsLet.LogFlushFrequency, "Maximum number of seconds between log flushes") daemon.SetDaemonFlag(&CONF.OsdsLet.Daemon, def.OsdsLet.Daemon) CONF.Load("/etc/opensds/opensds.conf") daemon.CheckAndRunDaemon(CONF.OsdsLet.Daemon) diff --git a/pkg/api/filter/accesslog/accesslog.go b/pkg/api/filter/accesslog/accesslog.go new file mode 100644 index 000000000..7ed845864 --- /dev/null +++ b/pkg/api/filter/accesslog/accesslog.go @@ -0,0 +1,29 @@ +// Copyright (c) 2017 Huawei Technologies Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package accesslog + +import ( + "github.com/astaxie/beego" + bctx "github.com/astaxie/beego/context" + "github.com/golang/glog" +) + +func Factory() beego.FilterFunc { + return func(httpCtx *bctx.Context) { + r := httpCtx.Request + glog.Infof("\033[32m[D] %s -- %s %s\033[0m\n", r.RemoteAddr, r.Method, + r.URL) + } +} diff --git a/pkg/api/router.go b/pkg/api/router.go index 54d171bac..40611683c 100755 --- a/pkg/api/router.go +++ b/pkg/api/router.go @@ -25,6 +25,7 @@ import ( "github.com/astaxie/beego" bctx "github.com/astaxie/beego/context" + "github.com/opensds/opensds/pkg/api/filter/accesslog" "github.com/opensds/opensds/pkg/api/filter/auth" "github.com/opensds/opensds/pkg/api/filter/context" "github.com/opensds/opensds/pkg/utils/constants" @@ -103,6 +104,7 @@ func Run(host string) { pattern := fmt.Sprintf("/%s/*", constants.APIVersion) beego.InsertFilter(pattern, beego.BeforeExec, context.Factory()) beego.InsertFilter(pattern, beego.BeforeExec, auth.Factory()) + beego.InsertFilter("*", beego.BeforeExec, accesslog.Factory()) beego.AddNamespace(ns) // add router for api version diff --git a/pkg/utils/config/config_define.go b/pkg/utils/config/config_define.go index fcddbbd00..a0057cbbb 100755 --- a/pkg/utils/config/config_define.go +++ b/pkg/utils/config/config_define.go @@ -14,15 +14,18 @@ package config +import "time" + type Default struct{} type OsdsLet struct { - ApiEndpoint string `conf:"api_endpoint,localhost:50040"` - Graceful bool `conf:"graceful,true"` - SocketOrder string `conf:"socket_order"` - AuthStrategy string `conf:"auth_strategy,noauth"` - Daemon bool `conf:"daemon,false"` - PolicyPath string `conf:"policy_path,/etc/opensds/policy.json"` + ApiEndpoint string `conf:"api_endpoint,localhost:50040"` + Graceful bool `conf:"graceful,true"` + SocketOrder string `conf:"socket_order"` + AuthStrategy string `conf:"auth_strategy,noauth"` + Daemon bool `conf:"daemon,false"` + PolicyPath string `conf:"policy_path,/etc/opensds/policy.json"` + LogFlushFrequency time.Duration `conf:"log_flush_frequency,5000000000"` // Default value is 5s } type OsdsDock struct { diff --git a/pkg/utils/config/flag.go b/pkg/utils/config/flag.go index e3a02acae..c4ac24c5e 100755 --- a/pkg/utils/config/flag.go +++ b/pkg/utils/config/flag.go @@ -17,8 +17,7 @@ package config import ( gflag "flag" "reflect" - - log "github.com/golang/glog" + "time" ) type Flag struct { @@ -83,6 +82,13 @@ func (f *FlagSet) StringVar(p *string, name string, defValue string, usage strin f.Add(name, flag) } +func (f *FlagSet) DurationVar(p *time.Duration, name string, defValue time.Duration, usage string) { + inVal := new(time.Duration) + flag := &Flag{Value: p, InValue: inVal} + gflag.DurationVar(inVal, name, defValue, usage) + f.Add(name, flag) +} + func (f *FlagSet) Add(name string, flag *Flag) { if f.flagMap == nil { f.flagMap = make(map[string]*Flag) @@ -103,25 +109,8 @@ func (f *FlagSet) AssignValue() { if _, ok := f.flagMap[name]; !ok { continue } - typ := reflect.TypeOf(f.flagMap[name].InValue) - val := reflect.ValueOf(f.flagMap[name].InValue) - switch typ.Elem().Kind() { - case reflect.String: - *f.flagMap[name].Value.(*string) = val.Elem().String() - case reflect.Bool: - *f.flagMap[name].Value.(*bool) = val.Elem().Bool() - case reflect.Int: - *f.flagMap[name].Value.(*int) = int(val.Elem().Int()) - case reflect.Int64: - *f.flagMap[name].Value.(*int64) = val.Elem().Int() - case reflect.Uint: - *f.flagMap[name].Value.(*uint) = uint(val.Elem().Uint()) - case reflect.Uint64: - *f.flagMap[name].Value.(*uint64) = val.Elem().Uint() - case reflect.Float64: - *f.flagMap[name].Value.(*float64) = val.Elem().Float() - default: - log.Error("Flag do not support this type.") - } + iv := reflect.ValueOf(f.flagMap[name].InValue).Elem() + v := reflect.ValueOf(f.flagMap[name].Value).Elem() + v.Set(iv) } } diff --git a/pkg/utils/logs/logs.go b/pkg/utils/logs/logs.go index eea1f7ba1..6e7d201a5 100755 --- a/pkg/utils/logs/logs.go +++ b/pkg/utils/logs/logs.go @@ -18,13 +18,25 @@ import ( "flag" "log" "os" + "time" + "fmt" "github.com/golang/glog" "github.com/opensds/opensds/pkg/utils" + "github.com/opensds/opensds/pkg/utils/config" + "os/signal" + "syscall" ) const DefaultLogDir = "/var/log/opensds" +// flushDaemon periodically flushes the log file buffers. +func flushDaemon(period time.Duration) { + for _ = range time.NewTicker(period).C { + glog.Flush() + } +} + func init() { //Set OpenSDS default log directory. flag.CommandLine.VisitAll(func(flag *flag.Flag) { @@ -42,6 +54,18 @@ func (writer GlogWriter) Write(data []byte) (n int, err error) { return len(data), nil } +// flush log when be interrupted. +func handleInterrupt() { + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGKILL, syscall.SIGQUIT) + go func() { + sig := <-sigs + fmt.Println(sig) + FlushLogs() + os.Exit(-1) + }() +} + func InitLogs() { log.SetOutput(GlogWriter{}) log.SetFlags(log.LstdFlags | log.Lshortfile) @@ -49,6 +73,8 @@ func InitLogs() { if exist, _ := utils.PathExists(logDir); !exist { os.MkdirAll(logDir, 0755) } + go flushDaemon(config.CONF.LogFlushFrequency) + handleInterrupt() } func FlushLogs() { From 88f1d3cb459e9e54985bfb76dbe932a3db3f1d94 Mon Sep 17 00:00:00 2001 From: jerry Date: Thu, 22 Nov 2018 20:33:58 +0800 Subject: [PATCH 14/20] Fixed gofmt issue --- pkg/utils/logs/logs.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/utils/logs/logs.go b/pkg/utils/logs/logs.go index 6e7d201a5..611420bc5 100755 --- a/pkg/utils/logs/logs.go +++ b/pkg/utils/logs/logs.go @@ -16,16 +16,16 @@ package logs import ( "flag" + "fmt" "log" "os" + "os/signal" + "syscall" "time" - "fmt" "github.com/golang/glog" "github.com/opensds/opensds/pkg/utils" "github.com/opensds/opensds/pkg/utils/config" - "os/signal" - "syscall" ) const DefaultLogDir = "/var/log/opensds" From 019a212fff1675f729852bed3689d47ec5874969 Mon Sep 17 00:00:00 2001 From: jerry Date: Fri, 23 Nov 2018 11:25:55 +0800 Subject: [PATCH 15/20] add paramters to volume specs, and fixed some api specs error --- openapi-spec/swagger.yaml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/openapi-spec/swagger.yaml b/openapi-spec/swagger.yaml index 58bb18dd8..6381f25d9 100755 --- a/openapi-spec/swagger.yaml +++ b/openapi-spec/swagger.yaml @@ -1470,13 +1470,12 @@ definitions: type: string poolId: type: string - readOnly: true - SnapshotId: + snapshotId: type: string - readOnly: true groupId: - type: string - readOnly: true + type: string + snapshotFromCloud: + type: boolean Attachment: description: >- Attachment is a description of volume attached resource. From bb64def0aa223913ab1d09142b5baee76ed1f5d3 Mon Sep 17 00:00:00 2001 From: Jerry Date: Fri, 23 Nov 2018 17:25:22 +0800 Subject: [PATCH 16/20] Add unit test and fixed some bugs (#553) * Add unit test and fixed some bugs * Fixed CI error * Fxied CI error --- cmd/osdsdock/osdsdock.go | 4 +- cmd/osdslet/osdslet.go | 2 +- contrib/cindercompatibleapi/main.go | 3 +- .../huawei/fusionstorage/fusionstorage.go | 2 +- .../drivers/huawei/fusionstorage/parser.go | 4 +- pkg/utils/config/config.go | 125 ++++++++++++++---- pkg/utils/config/config_define.go | 15 ++- pkg/utils/config/config_test.go | 42 ++++-- pkg/utils/config/testdata/opensds.conf | 3 + pkg/utils/logs/logs.go | 6 +- script/CI/coverage | 2 +- test/e2e/e2ef_test.go | 1 + 12 files changed, 150 insertions(+), 59 deletions(-) diff --git a/cmd/osdsdock/osdsdock.go b/cmd/osdsdock/osdsdock.go index 16244c185..acdd642e4 100755 --- a/cmd/osdsdock/osdsdock.go +++ b/cmd/osdsdock/osdsdock.go @@ -36,7 +36,7 @@ func init() { flag.StringVar(&CONF.Database.Endpoint, "db-endpoint", def.Database.Endpoint, "Connection endpoint of database service") flag.StringVar(&CONF.Database.Driver, "db-driver", def.Database.Driver, "Driver name of database service") // flag.StringVar(&CONF.Database.Credential, "db-credential", def.Database.Credential, "Connection credential of database service") - flag.DurationVar(&CONF.OsdsLet.LogFlushFrequency, "log-flush-frequency", def.OsdsLet.LogFlushFrequency, "Maximum number of seconds between log flushes") + flag.DurationVar(&CONF.OsdsDock.LogFlushFrequency, "log-flush-frequency", def.OsdsLet.LogFlushFrequency, "Maximum number of seconds between log flushes") daemon.SetDaemonFlag(&CONF.OsdsDock.Daemon, def.OsdsDock.Daemon) CONF.Load("/etc/opensds/opensds.conf") daemon.CheckAndRunDaemon(CONF.OsdsDock.Daemon) @@ -44,7 +44,7 @@ func init() { func main() { // Open OpenSDS dock service log file. - logs.InitLogs() + logs.InitLogs(CONF.OsdsDock.LogFlushFrequency) defer logs.FlushLogs() // Set up database session. diff --git a/cmd/osdslet/osdslet.go b/cmd/osdslet/osdslet.go index cdcaa4695..f5cc15a9c 100755 --- a/cmd/osdslet/osdslet.go +++ b/cmd/osdslet/osdslet.go @@ -43,7 +43,7 @@ func init() { func main() { // Open OpenSDS orchestrator service log file. - logs.InitLogs() + logs.InitLogs(CONF.OsdsLet.LogFlushFrequency) defer logs.FlushLogs() // Set up database session. diff --git a/contrib/cindercompatibleapi/main.go b/contrib/cindercompatibleapi/main.go index 52d76933e..e12a8488b 100644 --- a/contrib/cindercompatibleapi/main.go +++ b/contrib/cindercompatibleapi/main.go @@ -23,6 +23,7 @@ import ( "flag" "fmt" "os" + "time" "github.com/opensds/opensds/contrib/cindercompatibleapi/api" "github.com/opensds/opensds/pkg/utils/logs" @@ -30,7 +31,7 @@ import ( func main() { flag.Parse() - logs.InitLogs() + logs.InitLogs(5 * time.Second) defer logs.FlushLogs() cinderEndpoint, ok := os.LookupEnv("CINDER_ENDPOINT") diff --git a/contrib/drivers/huawei/fusionstorage/fusionstorage.go b/contrib/drivers/huawei/fusionstorage/fusionstorage.go index 6faed39b1..8ab10ea24 100644 --- a/contrib/drivers/huawei/fusionstorage/fusionstorage.go +++ b/contrib/drivers/huawei/fusionstorage/fusionstorage.go @@ -204,7 +204,7 @@ func (d *Driver) DeleteSnapshot(opt *pb.DeleteVolumeSnapshotOpts) error { log.Errorf("Delete volume snapshot (%s) failed: %v", opt.GetId(), err) return err } - log.Info("Remove volume snapshot (%s) success", opt.GetId()) + log.Infof("Remove volume snapshot (%s) success", opt.GetId()) return nil } diff --git a/contrib/drivers/huawei/fusionstorage/parser.go b/contrib/drivers/huawei/fusionstorage/parser.go index d04c1bed7..1b5561170 100644 --- a/contrib/drivers/huawei/fusionstorage/parser.go +++ b/contrib/drivers/huawei/fusionstorage/parser.go @@ -76,7 +76,7 @@ func Value(data map[string]string, v reflect.Value) error { case reflect.String: iv.SetString(s) default: - return fmt.Errorf("fsc: Unexpected key type", iv.Kind()) // should never occur + return fmt.Errorf("fsc: Unexpected key type %v", iv.Kind()) // should never occur } } return nil @@ -112,7 +112,7 @@ func unmarshalSlice(data string, v reflect.Value) error { func Unmarshal(data []byte, v interface{}) error { rv := reflect.ValueOf(v) if rv.Kind() != reflect.Ptr || rv.IsNil() { - return fmt.Errorf("invalid type of %s ,reflect.TypeOf(v) ") + return fmt.Errorf("invalid value kind %v", rv.Kind()) } rv = rv.Elem() switch rv.Kind() { diff --git a/pkg/utils/config/config.go b/pkg/utils/config/config.go index a81929a7e..79909bd92 100755 --- a/pkg/utils/config/config.go +++ b/pkg/utils/config/config.go @@ -16,12 +16,14 @@ package config import ( gflag "flag" + "fmt" + "log" "reflect" "strconv" "strings" + "time" "github.com/go-ini/ini" - log "github.com/golang/glog" ) const ( @@ -29,73 +31,112 @@ const ( ConfDefaultValue ) -func setSlice(v reflect.Value, str string) { +func setSlice(v reflect.Value, str string) error { sList := strings.Split(str, ",") s := reflect.MakeSlice(v.Type(), 0, 5) switch v.Type().Elem().Kind() { case reflect.Bool: for _, elm := range sList { - val, _ := strconv.ParseBool(elm) + val, err := strconv.ParseBool(elm) + if err != nil { + return fmt.Errorf("cann't convert slice item %s to Bool, %v", elm, err) + } s = reflect.Append(s, reflect.ValueOf(val)) } case reflect.Int: for _, elm := range sList { - val, _ := strconv.Atoi(elm) + val, err := strconv.Atoi(elm) + if err != nil { + return fmt.Errorf("cann't convert slice item %s to Int, %v", elm, err) + } s = reflect.Append(s, reflect.ValueOf(val)) } case reflect.Int8: for _, elm := range sList { - val, _ := strconv.ParseInt(elm, 10, 64) + val, err := strconv.ParseInt(elm, 10, 64) + if err != nil { + return fmt.Errorf("cann't convert slice item %s to Int8, %v", elm, err) + } s = reflect.Append(s, reflect.ValueOf(int8(val))) } case reflect.Int16: for _, elm := range sList { - val, _ := strconv.ParseInt(elm, 10, 64) + val, err := strconv.ParseInt(elm, 10, 64) + if err != nil { + return fmt.Errorf("cann't convert slice item %s to Int16, %v", elm, err) + } s = reflect.Append(s, reflect.ValueOf(int16(val))) } case reflect.Int32: for _, elm := range sList { - val, _ := strconv.ParseInt(elm, 10, 64) + val, err := strconv.ParseInt(elm, 10, 64) + if err != nil { + return fmt.Errorf("cann't convert slice item %s to Int32, %v", elm, err) + } s = reflect.Append(s, reflect.ValueOf(int32(val))) } case reflect.Int64: for _, elm := range sList { - val, _ := strconv.ParseInt(elm, 10, 64) + val, err := strconv.ParseInt(elm, 10, 64) + if err != nil { + return fmt.Errorf("cann't convert slice item %s to Int64, %v", elm, err) + } s = reflect.Append(s, reflect.ValueOf(int64(val))) } case reflect.Uint: for _, elm := range sList { - val, _ := strconv.ParseUint(elm, 10, 64) + val, err := strconv.ParseUint(elm, 10, 64) + if err != nil { + return fmt.Errorf("cann't convert slice item %s to Uint, %v", elm, err) + } s = reflect.Append(s, reflect.ValueOf(uint(val))) } case reflect.Uint8: for _, elm := range sList { - val, _ := strconv.ParseUint(elm, 10, 64) + val, err := strconv.ParseUint(elm, 10, 64) + if err != nil { + return fmt.Errorf("cann't convert slice item %s to Uint8, %v", elm, err) + } s = reflect.Append(s, reflect.ValueOf(uint8(val))) } case reflect.Uint16: for _, elm := range sList { - val, _ := strconv.ParseUint(elm, 10, 64) + val, err := strconv.ParseUint(elm, 10, 64) + if err != nil { + return fmt.Errorf("cann't convert slice item %s to Uint16, %v", elm, err) + } s = reflect.Append(s, reflect.ValueOf(uint16(val))) } case reflect.Uint32: for _, elm := range sList { - val, _ := strconv.ParseUint(elm, 10, 64) + val, err := strconv.ParseUint(elm, 10, 64) + if err != nil { + return fmt.Errorf("cann't convert slice item %s to Uint32, %v", elm, err) + } s = reflect.Append(s, reflect.ValueOf(uint32(val))) } case reflect.Uint64: for _, elm := range sList { - val, _ := strconv.ParseUint(elm, 10, 64) + val, err := strconv.ParseUint(elm, 10, 64) + if err != nil { + return fmt.Errorf("cann't convert slice item %s to Uint64, %v", elm, err) + } s = reflect.Append(s, reflect.ValueOf(uint64(val))) } case reflect.Float32: for _, elm := range sList { - val, _ := strconv.ParseFloat(elm, 64) + val, err := strconv.ParseFloat(elm, 64) + if err != nil { + return fmt.Errorf("cann't convert slice item %s to Float32, %v", elm, err) + } s = reflect.Append(s, reflect.ValueOf(float32(val))) } case reflect.Float64: for _, elm := range sList { - val, _ := strconv.ParseFloat(elm, 64) + val, err := strconv.ParseFloat(elm, 64) + if err != nil { + return fmt.Errorf("cann't convert slice item %s to Float54, %v", elm, err) + } s = reflect.Append(s, reflect.ValueOf(val)) } case reflect.String: @@ -103,12 +144,13 @@ func setSlice(v reflect.Value, str string) { s = reflect.Append(s, reflect.ValueOf(elm)) } default: - log.Error("Not support this type of slice.") + log.Printf("[ERROR] Does not support this type of slice.") } v.Set(s) + return nil } -func parseItems(section string, v reflect.Value, cfg *ini.File) { +func parseItems(section string, v reflect.Value, cfg *ini.File) error { for i := 0; i < v.Type().NumField(); i++ { field := v.Field(i) @@ -132,16 +174,38 @@ func parseItems(section string, v reflect.Value, cfg *ini.File) { } switch field.Kind() { case reflect.Bool: - val, _ := strconv.ParseBool(strVal) + val, err := strconv.ParseBool(strVal) + if err != nil { + return fmt.Errorf("cann't convert %s:%s to Bool, %v", tags[0], strVal, err) + } field.SetBool(val) + case reflect.ValueOf(time.Second).Kind(): + if field.Type().String() == "time.Duration" { + v, err := time.ParseDuration(strVal) + if err != nil { + return fmt.Errorf("cann't convert %s:%s to Duration, %v", tags[0], strVal, err) + } + field.SetInt(int64(v)) + break + } + fallthrough case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - val, _ := strconv.ParseInt(strVal, 10, 64) + val, err := strconv.ParseInt(strVal, 10, 64) + if err != nil { + return fmt.Errorf("cann't convert %s:%s to Int, %v", tags[0], strVal, err) + } field.SetInt(val) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - val, _ := strconv.ParseUint(strVal, 10, 64) + val, err := strconv.ParseUint(strVal, 10, 64) + if err != nil { + return fmt.Errorf("cann't convert %s:%s to Uint, %v", tags[0], strVal, err) + } field.SetUint(val) case reflect.Float32, reflect.Float64: - val, _ := strconv.ParseFloat(strVal, 64) + val, err := strconv.ParseFloat(strVal, 64) + if err != nil { + return fmt.Errorf("cann't convert %s:%s to Float, %v", tags[0], strVal, err) + } field.SetFloat(val) case reflect.String: field.SetString(strVal) @@ -150,9 +214,10 @@ func parseItems(section string, v reflect.Value, cfg *ini.File) { default: } } + return nil } -func parseSections(cfg *ini.File, t reflect.Type, v reflect.Value) { +func parseSections(cfg *ini.File, t reflect.Type, v reflect.Value) error { if v.Kind() == reflect.Ptr { v = v.Elem() t = t.Elem() @@ -164,21 +229,27 @@ func parseSections(cfg *ini.File, t reflect.Type, v reflect.Value) { continue } if "" == section { - parseSections(cfg, field.Type(), field) + if err := parseSections(cfg, field.Type(), field); err != nil { + return err + } + } + if err := parseItems(section, field, cfg); err != nil { + return err } - parseItems(section, field, cfg) } + return nil } func initConf(confFile string, conf interface{}) { cfg, err := ini.Load(confFile) if err != nil && confFile != "" { - log.Info("Read configuration failed, use default value") + log.Printf("[ERROR] Read configuration failed, use default value") } t := reflect.TypeOf(conf) v := reflect.ValueOf(conf) - parseSections(cfg, t, v) - + if err := parseSections(cfg, t, v); err != nil { + log.Fatalf("[ERROR] parse configure file failed: %v", err) + } } // Global Configuration Variable diff --git a/pkg/utils/config/config_define.go b/pkg/utils/config/config_define.go index a0057cbbb..c1f44ee16 100755 --- a/pkg/utils/config/config_define.go +++ b/pkg/utils/config/config_define.go @@ -25,16 +25,17 @@ type OsdsLet struct { AuthStrategy string `conf:"auth_strategy,noauth"` Daemon bool `conf:"daemon,false"` PolicyPath string `conf:"policy_path,/etc/opensds/policy.json"` - LogFlushFrequency time.Duration `conf:"log_flush_frequency,5000000000"` // Default value is 5s + LogFlushFrequency time.Duration `conf:"log_flush_frequency,5s"` // Default value is 5s } type OsdsDock struct { - ApiEndpoint string `conf:"api_endpoint,localhost:50050"` - DockType string `conf:"dock_type,provisioner"` - EnabledBackends []string `conf:"enabled_backends,lvm"` - Daemon bool `conf:"daemon,false"` - BindIp string `conf:"bind_ip"` // Just used for attacher dock - HostBasedReplicationDriver string `conf:"host_based_replication_driver,drbd"` + ApiEndpoint string `conf:"api_endpoint,localhost:50050"` + DockType string `conf:"dock_type,provisioner"` + EnabledBackends []string `conf:"enabled_backends,lvm"` + Daemon bool `conf:"daemon,false"` + BindIp string `conf:"bind_ip"` // Just used for attacher dock + HostBasedReplicationDriver string `conf:"host_based_replication_driver,drbd"` + LogFlushFrequency time.Duration `conf:"log_flush_frequency,5s"` // Default value is 5s Backends } diff --git a/pkg/utils/config/config_test.go b/pkg/utils/config/config_test.go index 13f207444..7fe1b4318 100755 --- a/pkg/utils/config/config_test.go +++ b/pkg/utils/config/config_test.go @@ -17,23 +17,25 @@ package config import ( "reflect" "testing" + "time" ) type TestStruct struct { - Bool bool `conf:"bool,true"` - Int int `conf:"int,-456789"` - Int8 int8 `conf:"int8,-111"` - Int16 int `conf:"int16,-4567"` - Int32 int `conf:"int32,-456789"` - Int64 int64 `conf:"int64,-456789"` - Uint uint `conf:"uint,456789"` - Uint8 uint8 `conf:"uint8,111"` - Uint16 uint16 `conf:"uint16,4567"` - Uint32 uint32 `conf:"uint32,456789"` - Uint64 uint64 `conf:"uint64,456789"` - Float32 float32 `conf:"float32,0.456789"` - Float64 float64 `conf:"float64,0.456789"` - String string `conf:"string,DefaultValue"` + Bool bool `conf:"bool,true"` + Int int `conf:"int,-456789"` + Int8 int8 `conf:"int8,-111"` + Int16 int `conf:"int16,-4567"` + Int32 int `conf:"int32,-456789"` + Int64 int64 `conf:"int64,-456789"` + Uint uint `conf:"uint,456789"` + Uint8 uint8 `conf:"uint8,111"` + Uint16 uint16 `conf:"uint16,4567"` + Uint32 uint32 `conf:"uint32,456789"` + Uint64 uint64 `conf:"uint64,456789"` + Float32 float32 `conf:"float32,0.456789"` + Float64 float64 `conf:"float64,0.456789"` + String string `conf:"string,DefaultValue"` + Duration time.Duration `conf:"duration,10s"` } type TestSliceStruct struct { @@ -105,6 +107,9 @@ func TestFunctionAllType(t *testing.T) { if conf.TestStruct.Float64 != 0.123456 { t.Error("Test TestStuct Float64 error") } + if conf.TestStruct.Duration != 5*time.Second { + t.Error("Test TestStuct time Duration error") + } if conf.TestStruct.String != "HelloWorld" { t.Error("Test TestStuct String error") } @@ -207,6 +212,9 @@ func TestFunctionDefaultValue(t *testing.T) { if conf.TestStruct.String != "DefaultValue" { t.Error("Test TestStuct String error") } + if conf.TestStruct.Duration != 10*time.Second { + t.Error("Test TestStuct String error") + } if !reflect.DeepEqual(conf.TestSliceStruct.SliceString, []string{"slice", "string", "test"}) { t.Error("Test TestSliceStruct String error") @@ -263,9 +271,15 @@ func TestOpensdsConfig(t *testing.T) { if CONF.OsdsLet.SocketOrder != "inc" { t.Error("Test OsdsLet.SocketOrder error") } + if CONF.OsdsLet.LogFlushFrequency != 2*time.Second { + t.Error("Test OsdsDock.ApiEndpoint error") + } if CONF.OsdsDock.ApiEndpoint != "localhost:50050" { t.Error("Test OsdsDock.ApiEndpoint error") } + if CONF.OsdsDock.LogFlushFrequency != 4*time.Second { + t.Error("Test OsdsDock.ApiEndpoint error") + } if CONF.OsdsDock.EnabledBackends[0] != "ceph" { t.Error("OsdsDock.EnabledBackends[0] error") } diff --git a/pkg/utils/config/testdata/opensds.conf b/pkg/utils/config/testdata/opensds.conf index e9546749e..78f50b8dd 100755 --- a/pkg/utils/config/testdata/opensds.conf +++ b/pkg/utils/config/testdata/opensds.conf @@ -3,11 +3,13 @@ api_endpoint = localhost:50040 graceful = True log_file = /var/log/opensds/osdslet.log socket_order = inc +log_flush_frequency = 2s [osdsdock] api_endpoint = localhost:50050 log_file = /var/log/opensds/osdsdock.log enabled_backends = ceph,cinder,sample,lvm +log_flush_frequency = 4s [ceph] name = ceph @@ -53,6 +55,7 @@ uint64=123456 float32=0.123456 float64=0.123456 string=HelloWorld +duration=5s [test_slice_struct] slice_bool=False,True,False diff --git a/pkg/utils/logs/logs.go b/pkg/utils/logs/logs.go index 611420bc5..25e6c384b 100755 --- a/pkg/utils/logs/logs.go +++ b/pkg/utils/logs/logs.go @@ -25,7 +25,6 @@ import ( "github.com/golang/glog" "github.com/opensds/opensds/pkg/utils" - "github.com/opensds/opensds/pkg/utils/config" ) const DefaultLogDir = "/var/log/opensds" @@ -66,14 +65,15 @@ func handleInterrupt() { }() } -func InitLogs() { +func InitLogs(LogFlushFrequency time.Duration) { log.SetOutput(GlogWriter{}) log.SetFlags(log.LstdFlags | log.Lshortfile) logDir := flag.CommandLine.Lookup("log_dir").Value.String() if exist, _ := utils.PathExists(logDir); !exist { os.MkdirAll(logDir, 0755) } - go flushDaemon(config.CONF.LogFlushFrequency) + glog.Infof("[Info] LogFlushFrequency: %v", LogFlushFrequency) + go flushDaemon(LogFlushFrequency) handleInterrupt() } diff --git a/script/CI/coverage b/script/CI/coverage index ca1bd4141..2b62cefe0 100755 --- a/script/CI/coverage +++ b/script/CI/coverage @@ -24,7 +24,7 @@ for testpkg in $(go list ./osdsctl/... ./client/... ./pkg/... ./contrib/...); do test $testpkg == "$MODEL_PACKAGE" && continue test $testpkg == "$PROTOBUF_PACKAGE" && continue covpkg="${testpkg/"/testing"/}" - go test -covermode count -coverprofile "testing_"$n.coverprofile -coverpkg $covpkg $testpkg 2>/dev/null + go test -covermode count -coverprofile "testing_"$n.coverprofile -coverpkg $covpkg $testpkg n=$((n+1)) done diff --git a/test/e2e/e2ef_test.go b/test/e2e/e2ef_test.go index 822ee9ce0..4eca86272 100644 --- a/test/e2e/e2ef_test.go +++ b/test/e2e/e2ef_test.go @@ -175,6 +175,7 @@ func TestExtendVolumeFlow(t *testing.T) { body = &model.ExtendVolumeSpec{ NewSize: int64(3), } + time.Sleep(3 * 1e9) _, err = u.ExtendVolume(vol.Id, body) if err != nil { t.Error("Extend volume fail", err) From c71ac7f1efdedf3c9f1fd1de8816c3368782e3f5 Mon Sep 17 00:00:00 2001 From: Xing Yang Date: Fri, 23 Nov 2018 13:12:40 -0500 Subject: [PATCH 17/20] Fix function name in the log msg --- contrib/connector/iscsi/helper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/connector/iscsi/helper.go b/contrib/connector/iscsi/helper.go index c10a31546..d5734f1d4 100644 --- a/contrib/connector/iscsi/helper.go +++ b/contrib/connector/iscsi/helper.go @@ -284,7 +284,7 @@ func getInitiatorInfo() (connector.InitiatorInfo, error) { } initiatorInfo.HostName = hostName - log.Printf("getFChbasInfo success: protocol=%v, initiatorInfo=%v", + log.Printf("getInitiatorInfo success: protocol=%v, initiatorInfo=%v", connector.IscsiDriver, initiatorInfo) return initiatorInfo, nil From bbac7d4270fe514a8d9e4537176a19a0733c2a77 Mon Sep 17 00:00:00 2001 From: leonwanghui Date: Wed, 28 Nov 2018 10:38:12 +0800 Subject: [PATCH 18/20] Remove dashboard module --- .travis.yml | 1 + dashboard/.angular-cli.json | 71 - dashboard/.editorconfig | 13 - dashboard/.gitignore | 50 - dashboard/.npmignore | 67 - dashboard/.travis.yml | 23 - dashboard/Dockerfile | 35 - dashboard/LICENSE.md | 21 - dashboard/Makefile | 53 - dashboard/README.md | 77 - dashboard/e2e/accordion.e2e-spec.ts | 20 - dashboard/e2e/app.e2e-spec.ts | 16 - dashboard/e2e/app.po.ts | 11 - dashboard/e2e/fieldset.e2e-spec.ts | 27 - dashboard/e2e/inputtext.e2e-spec.ts | 34 - dashboard/e2e/panel.e2e-spec.ts | 27 - dashboard/e2e/tabview.e2e-spec.ts | 49 - dashboard/e2e/tsconfig.e2e.json | 12 - dashboard/exports/accordion.d.ts | 1 - dashboard/exports/accordion.js | 7 - dashboard/exports/api.d.ts | 1 - dashboard/exports/api.js | 7 - dashboard/exports/autocomplete.d.ts | 1 - dashboard/exports/autocomplete.js | 7 - dashboard/exports/blockui.d.ts | 1 - dashboard/exports/blockui.js | 7 - dashboard/exports/breadcrumb.d.ts | 1 - dashboard/exports/breadcrumb.js | 7 - dashboard/exports/button.d.ts | 1 - dashboard/exports/button.js | 7 - dashboard/exports/calendar.d.ts | 1 - dashboard/exports/calendar.js | 7 - dashboard/exports/captcha.d.ts | 1 - dashboard/exports/captcha.js | 7 - dashboard/exports/card.d.ts | 1 - dashboard/exports/card.js | 7 - dashboard/exports/carousel.d.ts | 1 - dashboard/exports/carousel.js | 7 - dashboard/exports/chart.d.ts | 1 - dashboard/exports/chart.js | 7 - dashboard/exports/checkbox.d.ts | 1 - dashboard/exports/checkbox.js | 7 - dashboard/exports/chips.d.ts | 1 - dashboard/exports/chips.js | 7 - dashboard/exports/codehighlighter.d.ts | 1 - dashboard/exports/codehighlighter.js | 7 - dashboard/exports/colorpicker.d.ts | 1 - dashboard/exports/colorpicker.js | 7 - dashboard/exports/confirmdialog.d.ts | 1 - dashboard/exports/confirmdialog.js | 7 - dashboard/exports/contextmenu.d.ts | 1 - dashboard/exports/contextmenu.js | 7 - dashboard/exports/datagrid.d.ts | 1 - dashboard/exports/datagrid.js | 7 - dashboard/exports/datalist.d.ts | 1 - dashboard/exports/datalist.js | 7 - dashboard/exports/datascroller.d.ts | 1 - dashboard/exports/datascroller.js | 7 - dashboard/exports/datatable.d.ts | 1 - dashboard/exports/datatable.js | 7 - dashboard/exports/dataview.d.ts | 1 - dashboard/exports/dataview.js | 7 - dashboard/exports/defer.d.ts | 1 - dashboard/exports/defer.js | 7 - dashboard/exports/dialog.d.ts | 1 - dashboard/exports/dialog.js | 7 - dashboard/exports/dragdrop.d.ts | 1 - dashboard/exports/dragdrop.js | 7 - dashboard/exports/dropdown.d.ts | 1 - dashboard/exports/dropdown.js | 7 - dashboard/exports/editor.d.ts | 1 - dashboard/exports/editor.js | 7 - dashboard/exports/fieldset.d.ts | 1 - dashboard/exports/fieldset.js | 7 - dashboard/exports/fileupload.d.ts | 1 - dashboard/exports/fileupload.js | 7 - dashboard/exports/galleria.d.ts | 1 - dashboard/exports/galleria.js | 7 - dashboard/exports/gmap.d.ts | 1 - dashboard/exports/gmap.js | 7 - dashboard/exports/growl.d.ts | 1 - dashboard/exports/growl.js | 7 - dashboard/exports/inplace.d.ts | 1 - dashboard/exports/inplace.js | 7 - dashboard/exports/inputmask.d.ts | 1 - dashboard/exports/inputmask.js | 7 - dashboard/exports/inputswitch.d.ts | 1 - dashboard/exports/inputswitch.js | 7 - dashboard/exports/inputtext.d.ts | 1 - dashboard/exports/inputtext.js | 7 - dashboard/exports/inputtextarea.d.ts | 1 - dashboard/exports/inputtextarea.js | 7 - dashboard/exports/keyfilter.d.ts | 1 - dashboard/exports/keyfilter.js | 7 - dashboard/exports/lightbox.d.ts | 1 - dashboard/exports/lightbox.js | 7 - dashboard/exports/listbox.d.ts | 1 - dashboard/exports/listbox.js | 7 - dashboard/exports/megamenu.d.ts | 1 - dashboard/exports/megamenu.js | 7 - dashboard/exports/menu.d.ts | 1 - dashboard/exports/menu.js | 7 - dashboard/exports/menubar.d.ts | 1 - dashboard/exports/menubar.js | 7 - dashboard/exports/message.d.ts | 1 - dashboard/exports/message.js | 7 - dashboard/exports/messages.d.ts | 1 - dashboard/exports/messages.js | 7 - dashboard/exports/multiselect.d.ts | 1 - dashboard/exports/multiselect.js | 7 - dashboard/exports/orderlist.d.ts | 1 - dashboard/exports/orderlist.js | 7 - dashboard/exports/organizationchart.d.ts | 1 - dashboard/exports/organizationchart.js | 7 - dashboard/exports/overlaypanel.d.ts | 1 - dashboard/exports/overlaypanel.js | 7 - dashboard/exports/paginator.d.ts | 1 - dashboard/exports/paginator.js | 7 - dashboard/exports/panel.d.ts | 1 - dashboard/exports/panel.js | 7 - dashboard/exports/panelmenu.d.ts | 1 - dashboard/exports/panelmenu.js | 7 - dashboard/exports/password.d.ts | 1 - dashboard/exports/password.js | 7 - dashboard/exports/picklist.d.ts | 1 - dashboard/exports/picklist.js | 7 - dashboard/exports/progressbar.d.ts | 1 - dashboard/exports/progressbar.js | 7 - dashboard/exports/progressspinner.d.ts | 1 - dashboard/exports/progressspinner.js | 7 - dashboard/exports/radiobutton.d.ts | 1 - dashboard/exports/radiobutton.js | 7 - dashboard/exports/rating.d.ts | 1 - dashboard/exports/rating.js | 7 - dashboard/exports/schedule.d.ts | 1 - dashboard/exports/schedule.js | 7 - dashboard/exports/scrollpanel.d.ts | 1 - dashboard/exports/scrollpanel.js | 7 - dashboard/exports/selectbutton.d.ts | 1 - dashboard/exports/selectbutton.js | 7 - dashboard/exports/shared.d.ts | 1 - dashboard/exports/shared.js | 7 - dashboard/exports/sidebar.d.ts | 1 - dashboard/exports/sidebar.js | 7 - dashboard/exports/slidemenu.d.ts | 1 - dashboard/exports/slidemenu.js | 7 - dashboard/exports/slider.d.ts | 1 - dashboard/exports/slider.js | 7 - dashboard/exports/spinner.d.ts | 1 - dashboard/exports/spinner.js | 7 - dashboard/exports/splitbutton.d.ts | 1 - dashboard/exports/splitbutton.js | 7 - dashboard/exports/steps.d.ts | 1 - dashboard/exports/steps.js | 7 - dashboard/exports/table.d.ts | 1 - dashboard/exports/table.js | 7 - dashboard/exports/tabmenu.d.ts | 1 - dashboard/exports/tabmenu.js | 7 - dashboard/exports/tabview.d.ts | 1 - dashboard/exports/tabview.js | 7 - dashboard/exports/terminal.d.ts | 1 - dashboard/exports/terminal.js | 7 - dashboard/exports/tieredmenu.d.ts | 1 - dashboard/exports/tieredmenu.js | 7 - dashboard/exports/togglebutton.d.ts | 1 - dashboard/exports/togglebutton.js | 7 - dashboard/exports/toolbar.d.ts | 1 - dashboard/exports/toolbar.js | 7 - dashboard/exports/tooltip.d.ts | 1 - dashboard/exports/tooltip.js | 7 - dashboard/exports/tree.d.ts | 1 - dashboard/exports/tree.js | 7 - dashboard/exports/treetable.d.ts | 1 - dashboard/exports/treetable.js | 7 - dashboard/exports/tristatecheckbox.d.ts | 1 - dashboard/exports/tristatecheckbox.js | 7 - dashboard/gulpfile.js | 62 - dashboard/image_builder.sh | 41 - dashboard/karma.conf.js | 39 - dashboard/package-lock.json | 13057 ---------------- dashboard/package.json | 71 - dashboard/protractor.conf.js | 28 - dashboard/proxy.conf.json | 10 - dashboard/src/app/app-routing.module.ts | 25 - dashboard/src/app/app.component.html | 51 - dashboard/src/app/app.component.ts | 445 - dashboard/src/app/app.module.ts | 38 - dashboard/src/app/app.service.ts | 18 - .../src/app/business/block/block.component.ts | 51 - dashboard/src/app/business/block/block.html | 14 - .../src/app/business/block/block.module.ts | 28 - .../create-volume-group.component.html | 3 - .../create-volume-group.component.ts | 17 - .../create-volume.component.html | 92 - .../create-volume/create-volume.component.ts | 274 - .../create-volume/create-volume.module.ts | 47 - .../replication-group.component.html | 106 - .../replication-group.component.ts | 111 - .../replication-list.component.html | 71 - .../replication-list.component.ts | 241 - .../snapshot-list.component.html | 71 - .../snapshot-list/snapshot-list.component.ts | 221 - .../volume-detail.component.html | 64 - .../volume-detail/volume-detail.component.ts | 65 - .../volume-detail/volume-detail.module.ts | 48 - .../volume-group-detail.component.html | 84 - .../volume-group-detail.component.ts | 156 - .../volume-group-detail.module.ts | 39 - .../src/app/business/block/volume.service.ts | 192 - .../business/block/volumeGroup.component.ts | 213 - .../src/app/business/block/volumeGroup.html | 66 - .../app/business/block/volumeGroup.module.ts | 23 - .../business/block/volumeList.component.ts | 367 - .../src/app/business/block/volumeList.html | 159 - .../app/business/block/volumeList.module.ts | 39 - .../cloud-service-item.component.html | 13 - .../cloud-service-item.component.scss | 15 - .../cloud-service-item.component.spec.ts | 0 .../cloud-service-item.component.ts | 22 - .../app/business/cloud/cloud.component.html | 11 - .../app/business/cloud/cloud.component.scss | 0 .../src/app/business/cloud/cloud.component.ts | 15 - .../src/app/business/cloud/cloud.module.ts | 38 - .../cloud/migration/migration.component.html | 3 - .../cloud/migration/migration.component.scss | 0 .../cloud/migration/migration.component.ts | 15 - .../cloud/registry/registry.component.html | 41 - .../cloud/registry/registry.component.scss | 0 .../cloud/registry/registry.component.ts | 90 - .../replication/replication.component.html | 29 - .../replication/replication.component.scss | 0 .../replication/replication.component.ts | 15 - .../src/app/business/home/home.component.html | 125 - .../src/app/business/home/home.component.scss | 43 - .../src/app/business/home/home.component.ts | 271 - .../src/app/business/home/home.module.ts | 28 - .../imgItem.component/imgItem.component.html | 10 - .../imgItem.component/imgItem.component.scss | 13 - .../imgItem.component/imgItem.component.ts | 21 - .../business/identity/identity.component.ts | 48 - .../src/app/business/identity/identity.html | 12 - .../app/business/identity/identity.module.ts | 25 - .../tenantDetail/tenantDetail.component.ts | 205 - .../identity/tenantDetail/tenantDetail.html | 61 - .../tenantDetail/tenantDetail.module.ts | 12 - .../identity/tenantDetail/tenantDetail.scss | 15 - .../business/identity/tenantList.component.ts | 248 - .../src/app/business/identity/tenantList.html | 53 - .../business/identity/tenantList.module.ts | 29 - .../userDetail/userDetail.component.ts | 54 - .../identity/userDetail/userDetail.html | 7 - .../identity/userDetail/userDetail.module.ts | 12 - .../identity/userDetail/userDetail.scss | 18 - .../business/identity/userList.component.ts | 395 - .../src/app/business/identity/userList.html | 81 - .../app/business/identity/userList.module.ts | 33 - .../createProfile.component.html | 185 - .../createProfile/createProfile.component.ts | 482 - .../createProfile/createProfile.module.ts | 43 - .../modifyProfile.component.html | 50 - .../modifyProfile/modifyProfile.component.ts | 152 - .../modifyProfile/modifyProfile.module.ts | 35 - .../business/profile/profile.component.html | 26 - .../app/business/profile/profile.component.ts | 96 - .../app/business/profile/profile.module.ts | 40 - .../app/business/profile/profile.service.ts | 48 - .../profileCard/profile-card.component.html | 33 - .../profileCard/profile-card.component.ts | 156 - .../suspension-frame.component.html | 9 - .../suspension-frame.component.ts | 53 - .../storage-pools-table.component.html | 41 - .../storage-pools-table.component.ts | 75 - .../storage-pools-table.module.ts | 26 - .../resource/region/region.component.ts | 57 - .../app/business/resource/region/region.html | 5 - .../business/resource/region/region.module.ts | 18 - .../business/resource/resource.component.ts | 49 - .../src/app/business/resource/resource.html | 11 - .../app/business/resource/resource.module.ts | 32 - .../app/business/resource/resource.service.ts | 20 - .../resource/storage/storage.component.ts | 83 - .../business/resource/storage/storage.html | 19 - .../resource/storage/storage.module.ts | 20 - .../business/resource/zone/zone.component.ts | 67 - .../src/app/business/resource/zone/zone.html | 6 - .../app/business/resource/zone/zone.module.ts | 21 - dashboard/src/app/business/scss-variable.scss | 75 - .../business/service/service.component.html | 3 - .../app/business/service/service.component.ts | 48 - .../app/business/service/service.module.ts | 17 - .../app/components/accordion/accordion.css | 44 - .../components/accordion/accordion.spec.ts | 24 - .../src/app/components/accordion/accordion.ts | 209 - .../components/autocomplete/autocomplete.css | 163 - .../autocomplete/autocomplete.spec.ts | 24 - .../components/autocomplete/autocomplete.ts | 643 - dashboard/src/app/components/badge/badge.scss | 117 - dashboard/src/app/components/badge/badge.ts | 196 - .../src/app/components/blockui/blockui.css | 11 - .../app/components/blockui/blockui.spec.ts | 24 - .../src/app/components/blockui/blockui.ts | 80 - .../app/components/breadcrumb/breadcrumb.css | 21 - .../components/breadcrumb/breadcrumb.spec.ts | 24 - .../app/components/breadcrumb/breadcrumb.ts | 80 - .../src/app/components/button/button.scss | 324 - .../src/app/components/button/button.spec.ts | 24 - dashboard/src/app/components/button/button.ts | 158 - .../src/app/components/calendar/calendar.css | 236 - .../app/components/calendar/calendar.spec.ts | 24 - .../src/app/components/calendar/calendar.ts | 1777 --- .../app/components/captcha/captcha.spec.ts | 24 - .../src/app/components/captcha/captcha.ts | 92 - dashboard/src/app/components/card/card.css | 50 - .../src/app/components/card/card.spec.ts | 24 - dashboard/src/app/components/card/card.ts | 53 - .../src/app/components/carousel/carousel.css | 85 - .../app/components/carousel/carousel.spec.ts | 24 - .../src/app/components/carousel/carousel.ts | 327 - .../src/app/components/chart/chart.spec.ts | 24 - dashboard/src/app/components/chart/chart.ts | 112 - .../src/app/components/checkbox/checkbox.css | 25 - .../app/components/checkbox/checkbox.spec.ts | 33 - .../src/app/components/checkbox/checkbox.ts | 157 - dashboard/src/app/components/chips/chips.css | 59 - .../src/app/components/chips/chips.spec.ts | 24 - dashboard/src/app/components/chips/chips.ts | 227 - .../codehighlighter/codehighlighter.spec.ts | 24 - .../codehighlighter/codehighlighter.ts | 25 - .../components/colorpicker/colorpicker.css | 87 - .../colorpicker/colorpicker.spec.ts | 24 - .../app/components/colorpicker/colorpicker.ts | 507 - .../components/colorpicker/images/color.png | Bin 10355 -> 0 bytes .../app/components/colorpicker/images/hue.png | Bin 293 -> 0 bytes dashboard/src/app/components/common/I18N.ts | 12 - dashboard/src/app/components/common/api.ts | 44 - .../src/app/components/common/blockableui.ts | 3 - .../src/app/components/common/common.scss | 193 - .../src/app/components/common/confirmation.ts | 17 - .../components/common/confirmationservice.ts | 23 - .../app/components/common/filtermetadata.ts | 4 - .../src/app/components/common/keys.pipe.ts | 8 - .../app/components/common/lazyloadevent.ts | 12 - .../src/app/components/common/menuitem.ts | 24 - .../src/app/components/common/message.ts | 7 - .../app/components/common/messageservice.ts | 28 - .../src/app/components/common/selectitem.ts | 7 - .../app/components/common/selectitemgroup.ts | 7 - dashboard/src/app/components/common/shared.ts | 153 - .../src/app/components/common/sortevent.ts | 9 - .../src/app/components/common/sortmeta.ts | 4 - .../components/common/treedragdropservice.ts | 23 - .../src/app/components/common/treenode.ts | 17 - .../components/common/treenodedragevent.ts | 9 - .../confirmdialog/confirmdialog.spec.ts | 24 - .../components/confirmdialog/confirmdialog.ts | 314 - .../components/contextmenu/contextmenu.css | 44 - .../contextmenu/contextmenu.spec.ts | 24 - .../app/components/contextmenu/contextmenu.ts | 284 - .../src/app/components/datagrid/datagrid.css | 34 - .../app/components/datagrid/datagrid.spec.ts | 24 - .../src/app/components/datagrid/datagrid.ts | 205 - .../src/app/components/datalist/datalist.css | 39 - .../app/components/datalist/datalist.spec.ts | 24 - .../src/app/components/datalist/datalist.ts | 211 - .../components/datascroller/datascroller.css | 28 - .../datascroller/datascroller.spec.ts | 24 - .../components/datascroller/datascroller.ts | 203 - .../app/components/datatable/datatable.scss | 404 - .../components/datatable/datatable.spec.ts | 24 - .../src/app/components/datatable/datatable.ts | 2671 ---- .../src/app/components/dataview/dataview.css | 37 - .../src/app/components/dataview/dataview.ts | 293 - dashboard/src/app/components/defer/defer.ts | 66 - .../src/app/components/dialog/dialog.scss | 165 - .../src/app/components/dialog/dialog.spec.ts | 92 - dashboard/src/app/components/dialog/dialog.ts | 593 - .../src/app/components/dom/domhandler.ts | 468 - .../app/components/dragdrop/dragdrop.spec.ts | 24 - .../src/app/components/dragdrop/dragdrop.ts | 226 - .../src/app/components/dropdown/dropdown.scss | 131 - .../app/components/dropdown/dropdown.spec.ts | 24 - .../src/app/components/dropdown/dropdown.ts | 761 - .../src/app/components/dropmenu/dropmenu.scss | 145 - .../src/app/components/dropmenu/dropmenu.ts | 266 - .../src/app/components/editor/editor.spec.ts | 24 - dashboard/src/app/components/editor/editor.ts | 193 - .../src/app/components/fieldset/fieldset.css | 29 - .../app/components/fieldset/fieldset.spec.ts | 59 - .../src/app/components/fieldset/fieldset.ts | 113 - .../app/components/fileupload/fileupload.css | 96 - .../components/fileupload/fileupload.spec.ts | 24 - .../app/components/fileupload/fileupload.ts | 459 - dashboard/src/app/components/form/form.scss | 103 - dashboard/src/app/components/form/form.ts | 136 - .../src/app/components/galleria/galleria.css | 81 - .../app/components/galleria/galleria.spec.ts | 24 - .../src/app/components/galleria/galleria.ts | 246 - .../src/app/components/gmap/gmap.spec.ts | 24 - dashboard/src/app/components/gmap/gmap.ts | 165 - dashboard/src/app/components/grid/grid.css | 774 - dashboard/src/app/components/growl/growl.css | 54 - .../src/app/components/growl/growl.spec.ts | 24 - dashboard/src/app/components/growl/growl.ts | 218 - .../src/app/components/inplace/inplace.css | 11 - .../app/components/inplace/inplace.spec.ts | 24 - .../src/app/components/inplace/inplace.ts | 71 - .../components/inputmask/inputmask.spec.ts | 24 - .../src/app/components/inputmask/inputmask.ts | 620 - .../components/inputswitch/inputswitch.css | 58 - .../inputswitch/inputswitch.spec.ts | 24 - .../app/components/inputswitch/inputswitch.ts | 215 - .../app/components/inputtext/inputtext.scss | 112 - .../components/inputtext/inputtext.spec.ts | 24 - .../src/app/components/inputtext/inputtext.ts | 42 - .../inputtextarea/inputtextarea.css | 15 - .../inputtextarea/inputtextarea.spec.ts | 24 - .../components/inputtextarea/inputtextarea.ts | 94 - .../components/keyfilter/keyfilter.spec.ts | 24 - .../src/app/components/keyfilter/keyfilter.ts | 140 - .../components/lightbox/images/loading.gif | Bin 9427 -> 0 bytes .../src/app/components/lightbox/lightbox.css | 61 - .../app/components/lightbox/lightbox.spec.ts | 24 - .../src/app/components/lightbox/lightbox.ts | 231 - .../src/app/components/listbox/listbox.css | 72 - .../app/components/listbox/listbox.spec.ts | 24 - .../src/app/components/listbox/listbox.ts | 416 - .../src/app/components/megamenu/megamenu.css | 76 - .../app/components/megamenu/megamenu.spec.ts | 24 - .../src/app/components/megamenu/megamenu.ts | 183 - dashboard/src/app/components/menu/menu.css | 34 - .../src/app/components/menu/menu.spec.ts | 24 - dashboard/src/app/components/menu/menu.ts | 188 - .../src/app/components/menubar/menubar.css | 70 - .../app/components/menubar/menubar.spec.ts | 24 - .../src/app/components/menubar/menubar.ts | 219 - .../src/app/components/message/message.css | 10 - .../app/components/message/message.spec.ts | 24 - .../src/app/components/message/message.ts | 59 - .../src/app/components/messages/messages.css | 81 - .../app/components/messages/messages.spec.ts | 24 - .../src/app/components/messages/messages.ts | 125 - dashboard/src/app/components/msgbox/msgbox.ts | 41 - .../components/multiselect/multiselect.css | 149 - .../multiselect/multiselect.spec.ts | 24 - .../app/components/multiselect/multiselect.ts | 504 - .../app/components/orderlist/orderlist.css | 118 - .../components/orderlist/orderlist.spec.ts | 24 - .../src/app/components/orderlist/orderlist.ts | 354 - .../organizationchart/organizationchart.css | 46 - .../organizationchart.spec.ts | 24 - .../organizationchart/organizationchart.ts | 215 - .../components/overlaypanel/overlaypanel.css | 18 - .../overlaypanel/overlaypanel.spec.ts | 24 - .../components/overlaypanel/overlaypanel.ts | 186 - .../app/components/paginator/paginator.scss | 114 - .../components/paginator/paginator.spec.ts | 24 - .../src/app/components/paginator/paginator.ts | 231 - dashboard/src/app/components/panel/panel.css | 33 - .../src/app/components/panel/panel.spec.ts | 59 - dashboard/src/app/components/panel/panel.ts | 122 - .../app/components/panelmenu/panelmenu.css | 54 - .../components/panelmenu/panelmenu.spec.ts | 24 - .../src/app/components/panelmenu/panelmenu.ts | 164 - .../password/images/password-meter.png | Bin 1565 -> 0 bytes .../src/app/components/password/password.css | 20 - .../app/components/password/password.spec.ts | 24 - .../src/app/components/password/password.ts | 164 - .../src/app/components/picklist/picklist.css | 202 - .../app/components/picklist/picklist.spec.ts | 24 - .../src/app/components/picklist/picklist.ts | 660 - .../components/progressbar/progressbar.css | 110 - .../progressbar/progressbar.spec.ts | 24 - .../app/components/progressbar/progressbar.ts | 35 - .../progressspinner/progressspinner.css | 71 - .../progressspinner/progressspinner.spec.ts | 24 - .../progressspinner/progressspinner.ts | 33 - .../components/radiobutton/radiobutton.css | 33 - .../radiobutton/radiobutton.spec.ts | 32 - .../app/components/radiobutton/radiobutton.ts | 119 - .../src/app/components/rating/rating.spec.ts | 24 - dashboard/src/app/components/rating/rating.ts | 117 - .../src/app/components/schedule/schedule.css | 3 - .../app/components/schedule/schedule.spec.ts | 24 - .../src/app/components/schedule/schedule.ts | 402 - .../components/scrollpanel/scrollpanel.css | 54 - .../scrollpanel/scrollpanel.spec.ts | 24 - .../app/components/scrollpanel/scrollpanel.ts | 202 - .../components/selectbutton/selectbutton.css | 19 - .../selectbutton/selectbutton.spec.ts | 55 - .../components/selectbutton/selectbutton.ts | 155 - .../src/app/components/sidebar/sidebar.css | 117 - .../app/components/sidebar/sidebar.spec.ts | 24 - .../src/app/components/sidebar/sidebar.ts | 188 - .../app/components/slidemenu/slidemenu.css | 86 - .../components/slidemenu/slidemenu.spec.ts | 24 - .../src/app/components/slidemenu/slidemenu.ts | 228 - .../src/app/components/slider/slider.css | 65 - .../src/app/components/slider/slider.spec.ts | 24 - dashboard/src/app/components/slider/slider.ts | 369 - .../src/app/components/spinner/spinner.css | 72 - .../app/components/spinner/spinner.spec.ts | 67 - .../src/app/components/spinner/spinner.ts | 316 - .../components/splitbutton/splitbutton.css | 29 - .../splitbutton/splitbutton.spec.ts | 24 - .../app/components/splitbutton/splitbutton.ts | 194 - dashboard/src/app/components/steps/steps.css | 49 - .../src/app/components/steps/steps.spec.ts | 24 - dashboard/src/app/components/steps/steps.ts | 69 - dashboard/src/app/components/table/table.css | 224 - dashboard/src/app/components/table/table.ts | 2889 ---- .../src/app/components/tabmenu/tabmenu.css | 35 - .../app/components/tabmenu/tabmenu.spec.ts | 24 - .../src/app/components/tabmenu/tabmenu.ts | 71 - .../src/app/components/tabview/tabview.scss | 143 - .../app/components/tabview/tabview.spec.ts | 24 - .../src/app/components/tabview/tabview.ts | 310 - .../src/app/components/terminal/terminal.css | 25 - .../app/components/terminal/terminal.spec.ts | 24 - .../src/app/components/terminal/terminal.ts | 99 - .../components/terminal/terminalservice.ts | 25 - .../app/components/tieredmenu/tieredmenu.css | 49 - .../components/tieredmenu/tieredmenu.spec.ts | 24 - .../app/components/tieredmenu/tieredmenu.ts | 217 - .../togglebutton/togglebutton.spec.ts | 47 - .../components/togglebutton/togglebutton.ts | 122 - .../src/app/components/toolbar/toolbar.css | 11 - .../app/components/toolbar/toolbar.spec.ts | 24 - .../src/app/components/toolbar/toolbar.ts | 32 - .../src/app/components/tooltip/tooltip.css | 67 - .../app/components/tooltip/tooltip.spec.ts | 24 - .../src/app/components/tooltip/tooltip.ts | 388 - .../src/app/components/tree/images/line.gif | Bin 13112 -> 0 bytes dashboard/src/app/components/tree/tree.css | 186 - .../src/app/components/tree/tree.spec.ts | 24 - dashboard/src/app/components/tree/tree.ts | 779 - .../app/components/treetable/treetable.css | 134 - .../components/treetable/treetable.spec.ts | 24 - .../src/app/components/treetable/treetable.ts | 449 - .../tristatecheckbox/tristatecheckbox.spec.ts | 24 - .../tristatecheckbox/tristatecheckbox.ts | 125 - .../app/components/utils/objectutils.spec.ts | 114 - .../src/app/components/utils/objectutils.ts | 164 - dashboard/src/app/i18n/en/exception.json | 4 - dashboard/src/app/i18n/en/keyID.json | 117 - dashboard/src/app/i18n/en/widgetsKeyID.json | 15 - dashboard/src/app/i18n/zh/exception.json | 4 - dashboard/src/app/i18n/zh/keyID.json | 117 - dashboard/src/app/i18n/zh/widgetsKeyID.json | 15 - dashboard/src/app/shared/api.ts | 7 - .../app/shared/service/Exception.service.ts | 49 - .../src/app/shared/service/Http.service.ts | 103 - .../src/app/shared/service/I18N.service.ts | 52 - .../src/app/shared/service/MsgBox.service.ts | 91 - .../app/shared/service/ParamStor.service.ts | 59 - dashboard/src/app/shared/service/api.ts | 47 - dashboard/src/app/shared/shared.config.ts | 93 - dashboard/src/app/shared/shared.module.ts | 46 - dashboard/src/app/shared/utils/consts.ts | 29 - dashboard/src/app/shared/utils/mask.ts | 35 - dashboard/src/app/shared/utils/utils.ts | 146 - dashboard/src/assets/.gitkeep | 0 .../src/assets/business/css/primeng.scss | 69 - dashboard/src/assets/business/css/site.scss | 1563 -- .../src/assets/business/favicon/favicon.ico | Bin 1150 -> 0 bytes .../fonts/roboto-v15-latin-regular.eot | Bin 16227 -> 0 bytes .../fonts/roboto-v15-latin-regular.svg | 308 - .../fonts/roboto-v15-latin-regular.ttf | Bin 32652 -> 0 bytes .../fonts/roboto-v15-latin-regular.woff | Bin 18520 -> 0 bytes .../fonts/roboto-v15-latin-regular.woff2 | Bin 14584 -> 0 bytes .../business/images/cloud_service/AWS S3.png | Bin 10197 -> 0 bytes .../images/cloud_service/Huawei OBS.png | Bin 12423 -> 0 bytes .../Microsoft Azure Blob Storage.png | Bin 6611 -> 0 bytes .../business/images/cloud_service/u2309.png | Bin 8761 -> 0 bytes .../images/home_admin/Block Storages.png | Bin 941 -> 0 bytes .../home_admin/Cross-Region Migrations.png | Bin 1408 -> 0 bytes .../home_admin/Cross-Region Replications.png | Bin 1566 -> 0 bytes .../images/home_admin/Storage Pools.png | Bin 719 -> 0 bytes .../business/images/home_admin/Tenants.png | Bin 1495 -> 0 bytes .../business/images/home_admin/Users.png | Bin 1322 -> 0 bytes .../images/home_admin/Volume Replications.png | Bin 2182 -> 0 bytes .../images/home_admin/Volume Snapshots.png | Bin 1658 -> 0 bytes .../business/images/home_admin/Volumes.png | Bin 1635 -> 0 bytes .../business/images/home_admin/u199.png | Bin 23145 -> 0 bytes .../business/images/home_admin/u236.png | Bin 152 -> 0 bytes .../business/images/icons/button-active.svg | 41 - .../assets/business/images/icons/button.svg | 41 - .../business/images/icons/charts-active.svg | 13 - .../assets/business/images/icons/charts.svg | 13 - .../business/images/icons/data-active.svg | 15 - .../src/assets/business/images/icons/data.svg | 15 - .../business/images/icons/dragdrop-active.svg | 132 - .../assets/business/images/icons/dragdrop.svg | 132 - .../business/images/icons/file-active.svg | 15 - .../src/assets/business/images/icons/file.svg | 15 - .../business/images/icons/input-active.svg | 34 - .../assets/business/images/icons/input.svg | 34 - .../business/images/icons/menu-active.svg | 29 - .../src/assets/business/images/icons/menu.svg | 29 - .../business/images/icons/message-active.svg | 15 - .../assets/business/images/icons/message.svg | 15 - .../business/images/icons/misc-active.svg | 20 - .../src/assets/business/images/icons/misc.svg | 20 - .../images/icons/multimedia-active.svg | 20 - .../business/images/icons/multimedia.svg | 20 - .../business/images/icons/overlay-active.svg | 17 - .../assets/business/images/icons/overlay.svg | 17 - .../business/images/icons/panel-active.svg | 12 - .../assets/business/images/icons/panel.svg | 12 - .../src/assets/business/images/login-bg.png | Bin 66797 -> 0 bytes .../src/assets/business/images/logo-white.png | Bin 4809 -> 0 bytes dashboard/src/assets/business/images/logo.png | Bin 7009 -> 0 bytes .../src/assets/business/images/menu-bg.png | Bin 6787 -> 0 bytes .../assets/business/images/profile/u1065.png | Bin 513 -> 0 bytes .../assets/business/images/profile/u1985.png | Bin 584 -> 0 bytes .../assets/business/images/profile/u2861.png | Bin 304 -> 0 bytes .../assets/business/images/profile/u2987.png | Bin 572 -> 0 bytes .../assets/business/images/volume/u436.png | Bin 511 -> 0 bytes .../assets/business/images/volume/u583.png | Bin 2241 -> 0 bytes .../assets/business/images/volume/u585.png | Bin 2472 -> 0 bytes .../business/images/volume/u740p000.png | Bin 237 -> 0 bytes .../business/images/volume/u740p002.png | Bin 348 -> 0 bytes .../business/images/volume/u760p000.png | Bin 211 -> 0 bytes .../assets/business/images/volume/u937.png | Bin 1794 -> 0 bytes .../src/assets/components/images/line.gif | Bin 13112 -> 0 bytes .../src/assets/components/images/loading.gif | Bin 9427 -> 0 bytes .../components/images/password-meter.png | Bin 1565 -> 0 bytes .../src/assets/components/themes/_theme.scss | 712 - .../components/themes/default/default.scss | 926 -- .../fonts/roboto-v15-latin-regular.eot | Bin 16227 -> 0 bytes .../fonts/roboto-v15-latin-regular.svg | 308 - .../fonts/roboto-v15-latin-regular.ttf | Bin 32652 -> 0 bytes .../fonts/roboto-v15-latin-regular.woff | Bin 18520 -> 0 bytes .../fonts/roboto-v15-latin-regular.woff2 | Bin 14584 -> 0 bytes .../themes/default/images/icons_16.png | Bin 4020 -> 0 bytes .../themes/default/images/slider_handles.png | Bin 1945 -> 0 bytes .../default/images/slider_handles@2x.png | Bin 3603 -> 0 bytes .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 180 -> 0 bytes .../images/ui-bg_flat_75_ffffff_40x100.png | Bin 178 -> 0 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 120 -> 0 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 105 -> 0 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 111 -> 0 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 110 -> 0 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 119 -> 0 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 101 -> 0 bytes .../images/ui-icons_222222_256x240.png | Bin 4369 -> 0 bytes .../images/ui-icons_2e83ff_256x240.png | Bin 5355 -> 0 bytes .../images/ui-icons_454545_256x240.png | Bin 4369 -> 0 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 4369 -> 0 bytes .../images/ui-icons_ffffff_256x240.png | Bin 4369 -> 0 bytes .../src/environments/environment.prod.ts | 3 - dashboard/src/environments/environment.ts | 8 - dashboard/src/index.html | 17 - dashboard/src/main.ts | 11 - dashboard/src/polyfills.ts | 73 - dashboard/src/styles.scss | 3 - dashboard/src/test.ts | 32 - dashboard/src/tsconfig.app.json | 13 - dashboard/src/tsconfig.spec.json | 20 - dashboard/src/typings.d.ts | 8 - dashboard/src/upload.php | 1 - dashboard/tsconfig-aot.json | 24 - dashboard/tsconfig-release.json | 24 - dashboard/tsconfig.json | 20 - dashboard/tslint.json | 142 - 664 files changed, 1 insertion(+), 63395 deletions(-) delete mode 100644 dashboard/.angular-cli.json delete mode 100644 dashboard/.editorconfig delete mode 100644 dashboard/.gitignore delete mode 100644 dashboard/.npmignore delete mode 100644 dashboard/.travis.yml delete mode 100644 dashboard/Dockerfile delete mode 100644 dashboard/LICENSE.md delete mode 100644 dashboard/Makefile delete mode 100644 dashboard/README.md delete mode 100644 dashboard/e2e/accordion.e2e-spec.ts delete mode 100644 dashboard/e2e/app.e2e-spec.ts delete mode 100644 dashboard/e2e/app.po.ts delete mode 100644 dashboard/e2e/fieldset.e2e-spec.ts delete mode 100644 dashboard/e2e/inputtext.e2e-spec.ts delete mode 100644 dashboard/e2e/panel.e2e-spec.ts delete mode 100644 dashboard/e2e/tabview.e2e-spec.ts delete mode 100644 dashboard/e2e/tsconfig.e2e.json delete mode 100644 dashboard/exports/accordion.d.ts delete mode 100644 dashboard/exports/accordion.js delete mode 100644 dashboard/exports/api.d.ts delete mode 100644 dashboard/exports/api.js delete mode 100644 dashboard/exports/autocomplete.d.ts delete mode 100644 dashboard/exports/autocomplete.js delete mode 100644 dashboard/exports/blockui.d.ts delete mode 100644 dashboard/exports/blockui.js delete mode 100644 dashboard/exports/breadcrumb.d.ts delete mode 100644 dashboard/exports/breadcrumb.js delete mode 100644 dashboard/exports/button.d.ts delete mode 100644 dashboard/exports/button.js delete mode 100644 dashboard/exports/calendar.d.ts delete mode 100644 dashboard/exports/calendar.js delete mode 100644 dashboard/exports/captcha.d.ts delete mode 100644 dashboard/exports/captcha.js delete mode 100644 dashboard/exports/card.d.ts delete mode 100644 dashboard/exports/card.js delete mode 100644 dashboard/exports/carousel.d.ts delete mode 100644 dashboard/exports/carousel.js delete mode 100644 dashboard/exports/chart.d.ts delete mode 100644 dashboard/exports/chart.js delete mode 100644 dashboard/exports/checkbox.d.ts delete mode 100644 dashboard/exports/checkbox.js delete mode 100644 dashboard/exports/chips.d.ts delete mode 100644 dashboard/exports/chips.js delete mode 100644 dashboard/exports/codehighlighter.d.ts delete mode 100644 dashboard/exports/codehighlighter.js delete mode 100644 dashboard/exports/colorpicker.d.ts delete mode 100644 dashboard/exports/colorpicker.js delete mode 100644 dashboard/exports/confirmdialog.d.ts delete mode 100644 dashboard/exports/confirmdialog.js delete mode 100644 dashboard/exports/contextmenu.d.ts delete mode 100644 dashboard/exports/contextmenu.js delete mode 100644 dashboard/exports/datagrid.d.ts delete mode 100644 dashboard/exports/datagrid.js delete mode 100644 dashboard/exports/datalist.d.ts delete mode 100644 dashboard/exports/datalist.js delete mode 100644 dashboard/exports/datascroller.d.ts delete mode 100644 dashboard/exports/datascroller.js delete mode 100644 dashboard/exports/datatable.d.ts delete mode 100644 dashboard/exports/datatable.js delete mode 100644 dashboard/exports/dataview.d.ts delete mode 100644 dashboard/exports/dataview.js delete mode 100644 dashboard/exports/defer.d.ts delete mode 100644 dashboard/exports/defer.js delete mode 100644 dashboard/exports/dialog.d.ts delete mode 100644 dashboard/exports/dialog.js delete mode 100644 dashboard/exports/dragdrop.d.ts delete mode 100644 dashboard/exports/dragdrop.js delete mode 100644 dashboard/exports/dropdown.d.ts delete mode 100644 dashboard/exports/dropdown.js delete mode 100644 dashboard/exports/editor.d.ts delete mode 100644 dashboard/exports/editor.js delete mode 100644 dashboard/exports/fieldset.d.ts delete mode 100644 dashboard/exports/fieldset.js delete mode 100644 dashboard/exports/fileupload.d.ts delete mode 100644 dashboard/exports/fileupload.js delete mode 100644 dashboard/exports/galleria.d.ts delete mode 100644 dashboard/exports/galleria.js delete mode 100644 dashboard/exports/gmap.d.ts delete mode 100644 dashboard/exports/gmap.js delete mode 100644 dashboard/exports/growl.d.ts delete mode 100644 dashboard/exports/growl.js delete mode 100644 dashboard/exports/inplace.d.ts delete mode 100644 dashboard/exports/inplace.js delete mode 100644 dashboard/exports/inputmask.d.ts delete mode 100644 dashboard/exports/inputmask.js delete mode 100644 dashboard/exports/inputswitch.d.ts delete mode 100644 dashboard/exports/inputswitch.js delete mode 100644 dashboard/exports/inputtext.d.ts delete mode 100644 dashboard/exports/inputtext.js delete mode 100644 dashboard/exports/inputtextarea.d.ts delete mode 100644 dashboard/exports/inputtextarea.js delete mode 100644 dashboard/exports/keyfilter.d.ts delete mode 100644 dashboard/exports/keyfilter.js delete mode 100644 dashboard/exports/lightbox.d.ts delete mode 100644 dashboard/exports/lightbox.js delete mode 100644 dashboard/exports/listbox.d.ts delete mode 100644 dashboard/exports/listbox.js delete mode 100644 dashboard/exports/megamenu.d.ts delete mode 100644 dashboard/exports/megamenu.js delete mode 100644 dashboard/exports/menu.d.ts delete mode 100644 dashboard/exports/menu.js delete mode 100644 dashboard/exports/menubar.d.ts delete mode 100644 dashboard/exports/menubar.js delete mode 100644 dashboard/exports/message.d.ts delete mode 100644 dashboard/exports/message.js delete mode 100644 dashboard/exports/messages.d.ts delete mode 100644 dashboard/exports/messages.js delete mode 100644 dashboard/exports/multiselect.d.ts delete mode 100644 dashboard/exports/multiselect.js delete mode 100644 dashboard/exports/orderlist.d.ts delete mode 100644 dashboard/exports/orderlist.js delete mode 100644 dashboard/exports/organizationchart.d.ts delete mode 100644 dashboard/exports/organizationchart.js delete mode 100644 dashboard/exports/overlaypanel.d.ts delete mode 100644 dashboard/exports/overlaypanel.js delete mode 100644 dashboard/exports/paginator.d.ts delete mode 100644 dashboard/exports/paginator.js delete mode 100644 dashboard/exports/panel.d.ts delete mode 100644 dashboard/exports/panel.js delete mode 100644 dashboard/exports/panelmenu.d.ts delete mode 100644 dashboard/exports/panelmenu.js delete mode 100644 dashboard/exports/password.d.ts delete mode 100644 dashboard/exports/password.js delete mode 100644 dashboard/exports/picklist.d.ts delete mode 100644 dashboard/exports/picklist.js delete mode 100644 dashboard/exports/progressbar.d.ts delete mode 100644 dashboard/exports/progressbar.js delete mode 100644 dashboard/exports/progressspinner.d.ts delete mode 100644 dashboard/exports/progressspinner.js delete mode 100644 dashboard/exports/radiobutton.d.ts delete mode 100644 dashboard/exports/radiobutton.js delete mode 100644 dashboard/exports/rating.d.ts delete mode 100644 dashboard/exports/rating.js delete mode 100644 dashboard/exports/schedule.d.ts delete mode 100644 dashboard/exports/schedule.js delete mode 100644 dashboard/exports/scrollpanel.d.ts delete mode 100644 dashboard/exports/scrollpanel.js delete mode 100644 dashboard/exports/selectbutton.d.ts delete mode 100644 dashboard/exports/selectbutton.js delete mode 100644 dashboard/exports/shared.d.ts delete mode 100644 dashboard/exports/shared.js delete mode 100644 dashboard/exports/sidebar.d.ts delete mode 100644 dashboard/exports/sidebar.js delete mode 100644 dashboard/exports/slidemenu.d.ts delete mode 100644 dashboard/exports/slidemenu.js delete mode 100644 dashboard/exports/slider.d.ts delete mode 100644 dashboard/exports/slider.js delete mode 100644 dashboard/exports/spinner.d.ts delete mode 100644 dashboard/exports/spinner.js delete mode 100644 dashboard/exports/splitbutton.d.ts delete mode 100644 dashboard/exports/splitbutton.js delete mode 100644 dashboard/exports/steps.d.ts delete mode 100644 dashboard/exports/steps.js delete mode 100644 dashboard/exports/table.d.ts delete mode 100644 dashboard/exports/table.js delete mode 100644 dashboard/exports/tabmenu.d.ts delete mode 100644 dashboard/exports/tabmenu.js delete mode 100644 dashboard/exports/tabview.d.ts delete mode 100644 dashboard/exports/tabview.js delete mode 100644 dashboard/exports/terminal.d.ts delete mode 100644 dashboard/exports/terminal.js delete mode 100644 dashboard/exports/tieredmenu.d.ts delete mode 100644 dashboard/exports/tieredmenu.js delete mode 100644 dashboard/exports/togglebutton.d.ts delete mode 100644 dashboard/exports/togglebutton.js delete mode 100644 dashboard/exports/toolbar.d.ts delete mode 100644 dashboard/exports/toolbar.js delete mode 100644 dashboard/exports/tooltip.d.ts delete mode 100644 dashboard/exports/tooltip.js delete mode 100644 dashboard/exports/tree.d.ts delete mode 100644 dashboard/exports/tree.js delete mode 100644 dashboard/exports/treetable.d.ts delete mode 100644 dashboard/exports/treetable.js delete mode 100644 dashboard/exports/tristatecheckbox.d.ts delete mode 100644 dashboard/exports/tristatecheckbox.js delete mode 100644 dashboard/gulpfile.js delete mode 100644 dashboard/image_builder.sh delete mode 100644 dashboard/karma.conf.js delete mode 100644 dashboard/package-lock.json delete mode 100644 dashboard/package.json delete mode 100644 dashboard/protractor.conf.js delete mode 100644 dashboard/proxy.conf.json delete mode 100644 dashboard/src/app/app-routing.module.ts delete mode 100644 dashboard/src/app/app.component.html delete mode 100644 dashboard/src/app/app.component.ts delete mode 100644 dashboard/src/app/app.module.ts delete mode 100644 dashboard/src/app/app.service.ts delete mode 100644 dashboard/src/app/business/block/block.component.ts delete mode 100644 dashboard/src/app/business/block/block.html delete mode 100644 dashboard/src/app/business/block/block.module.ts delete mode 100644 dashboard/src/app/business/block/create-volume-group/create-volume-group.component.html delete mode 100644 dashboard/src/app/business/block/create-volume-group/create-volume-group.component.ts delete mode 100644 dashboard/src/app/business/block/create-volume/create-volume.component.html delete mode 100644 dashboard/src/app/business/block/create-volume/create-volume.component.ts delete mode 100644 dashboard/src/app/business/block/create-volume/create-volume.module.ts delete mode 100644 dashboard/src/app/business/block/create-volume/replication-group/replication-group.component.html delete mode 100644 dashboard/src/app/business/block/create-volume/replication-group/replication-group.component.ts delete mode 100644 dashboard/src/app/business/block/volume-detail/replication-list/replication-list.component.html delete mode 100644 dashboard/src/app/business/block/volume-detail/replication-list/replication-list.component.ts delete mode 100644 dashboard/src/app/business/block/volume-detail/snapshot-list/snapshot-list.component.html delete mode 100644 dashboard/src/app/business/block/volume-detail/snapshot-list/snapshot-list.component.ts delete mode 100644 dashboard/src/app/business/block/volume-detail/volume-detail.component.html delete mode 100644 dashboard/src/app/business/block/volume-detail/volume-detail.component.ts delete mode 100644 dashboard/src/app/business/block/volume-detail/volume-detail.module.ts delete mode 100644 dashboard/src/app/business/block/volume-group-detail/volume-group-detail.component.html delete mode 100644 dashboard/src/app/business/block/volume-group-detail/volume-group-detail.component.ts delete mode 100644 dashboard/src/app/business/block/volume-group-detail/volume-group-detail.module.ts delete mode 100644 dashboard/src/app/business/block/volume.service.ts delete mode 100644 dashboard/src/app/business/block/volumeGroup.component.ts delete mode 100644 dashboard/src/app/business/block/volumeGroup.html delete mode 100644 dashboard/src/app/business/block/volumeGroup.module.ts delete mode 100644 dashboard/src/app/business/block/volumeList.component.ts delete mode 100644 dashboard/src/app/business/block/volumeList.html delete mode 100644 dashboard/src/app/business/block/volumeList.module.ts delete mode 100644 dashboard/src/app/business/cloud/cloud-service-item/cloud-service-item.component.html delete mode 100644 dashboard/src/app/business/cloud/cloud-service-item/cloud-service-item.component.scss delete mode 100644 dashboard/src/app/business/cloud/cloud-service-item/cloud-service-item.component.spec.ts delete mode 100644 dashboard/src/app/business/cloud/cloud-service-item/cloud-service-item.component.ts delete mode 100644 dashboard/src/app/business/cloud/cloud.component.html delete mode 100644 dashboard/src/app/business/cloud/cloud.component.scss delete mode 100644 dashboard/src/app/business/cloud/cloud.component.ts delete mode 100644 dashboard/src/app/business/cloud/cloud.module.ts delete mode 100644 dashboard/src/app/business/cloud/migration/migration.component.html delete mode 100644 dashboard/src/app/business/cloud/migration/migration.component.scss delete mode 100644 dashboard/src/app/business/cloud/migration/migration.component.ts delete mode 100644 dashboard/src/app/business/cloud/registry/registry.component.html delete mode 100644 dashboard/src/app/business/cloud/registry/registry.component.scss delete mode 100644 dashboard/src/app/business/cloud/registry/registry.component.ts delete mode 100644 dashboard/src/app/business/cloud/replication/replication.component.html delete mode 100644 dashboard/src/app/business/cloud/replication/replication.component.scss delete mode 100644 dashboard/src/app/business/cloud/replication/replication.component.ts delete mode 100644 dashboard/src/app/business/home/home.component.html delete mode 100644 dashboard/src/app/business/home/home.component.scss delete mode 100644 dashboard/src/app/business/home/home.component.ts delete mode 100644 dashboard/src/app/business/home/home.module.ts delete mode 100644 dashboard/src/app/business/home/imgItem.component/imgItem.component.html delete mode 100644 dashboard/src/app/business/home/imgItem.component/imgItem.component.scss delete mode 100644 dashboard/src/app/business/home/imgItem.component/imgItem.component.ts delete mode 100644 dashboard/src/app/business/identity/identity.component.ts delete mode 100644 dashboard/src/app/business/identity/identity.html delete mode 100644 dashboard/src/app/business/identity/identity.module.ts delete mode 100644 dashboard/src/app/business/identity/tenantDetail/tenantDetail.component.ts delete mode 100644 dashboard/src/app/business/identity/tenantDetail/tenantDetail.html delete mode 100644 dashboard/src/app/business/identity/tenantDetail/tenantDetail.module.ts delete mode 100644 dashboard/src/app/business/identity/tenantDetail/tenantDetail.scss delete mode 100644 dashboard/src/app/business/identity/tenantList.component.ts delete mode 100644 dashboard/src/app/business/identity/tenantList.html delete mode 100644 dashboard/src/app/business/identity/tenantList.module.ts delete mode 100644 dashboard/src/app/business/identity/userDetail/userDetail.component.ts delete mode 100644 dashboard/src/app/business/identity/userDetail/userDetail.html delete mode 100644 dashboard/src/app/business/identity/userDetail/userDetail.module.ts delete mode 100644 dashboard/src/app/business/identity/userDetail/userDetail.scss delete mode 100644 dashboard/src/app/business/identity/userList.component.ts delete mode 100644 dashboard/src/app/business/identity/userList.html delete mode 100644 dashboard/src/app/business/identity/userList.module.ts delete mode 100644 dashboard/src/app/business/profile/createProfile/createProfile.component.html delete mode 100644 dashboard/src/app/business/profile/createProfile/createProfile.component.ts delete mode 100644 dashboard/src/app/business/profile/createProfile/createProfile.module.ts delete mode 100644 dashboard/src/app/business/profile/modifyProfile/modifyProfile.component.html delete mode 100644 dashboard/src/app/business/profile/modifyProfile/modifyProfile.component.ts delete mode 100644 dashboard/src/app/business/profile/modifyProfile/modifyProfile.module.ts delete mode 100644 dashboard/src/app/business/profile/profile.component.html delete mode 100644 dashboard/src/app/business/profile/profile.component.ts delete mode 100644 dashboard/src/app/business/profile/profile.module.ts delete mode 100644 dashboard/src/app/business/profile/profile.service.ts delete mode 100644 dashboard/src/app/business/profile/profileCard/profile-card.component.html delete mode 100644 dashboard/src/app/business/profile/profileCard/profile-card.component.ts delete mode 100644 dashboard/src/app/business/profile/profileCard/suspension-frame/suspension-frame.component.html delete mode 100644 dashboard/src/app/business/profile/profileCard/suspension-frame/suspension-frame.component.ts delete mode 100644 dashboard/src/app/business/profile/storage-pools-table/storage-pools-table.component.html delete mode 100644 dashboard/src/app/business/profile/storage-pools-table/storage-pools-table.component.ts delete mode 100644 dashboard/src/app/business/profile/storage-pools-table/storage-pools-table.module.ts delete mode 100644 dashboard/src/app/business/resource/region/region.component.ts delete mode 100644 dashboard/src/app/business/resource/region/region.html delete mode 100644 dashboard/src/app/business/resource/region/region.module.ts delete mode 100644 dashboard/src/app/business/resource/resource.component.ts delete mode 100644 dashboard/src/app/business/resource/resource.html delete mode 100644 dashboard/src/app/business/resource/resource.module.ts delete mode 100644 dashboard/src/app/business/resource/resource.service.ts delete mode 100644 dashboard/src/app/business/resource/storage/storage.component.ts delete mode 100644 dashboard/src/app/business/resource/storage/storage.html delete mode 100644 dashboard/src/app/business/resource/storage/storage.module.ts delete mode 100644 dashboard/src/app/business/resource/zone/zone.component.ts delete mode 100644 dashboard/src/app/business/resource/zone/zone.html delete mode 100644 dashboard/src/app/business/resource/zone/zone.module.ts delete mode 100644 dashboard/src/app/business/scss-variable.scss delete mode 100644 dashboard/src/app/business/service/service.component.html delete mode 100644 dashboard/src/app/business/service/service.component.ts delete mode 100644 dashboard/src/app/business/service/service.module.ts delete mode 100644 dashboard/src/app/components/accordion/accordion.css delete mode 100644 dashboard/src/app/components/accordion/accordion.spec.ts delete mode 100644 dashboard/src/app/components/accordion/accordion.ts delete mode 100644 dashboard/src/app/components/autocomplete/autocomplete.css delete mode 100644 dashboard/src/app/components/autocomplete/autocomplete.spec.ts delete mode 100644 dashboard/src/app/components/autocomplete/autocomplete.ts delete mode 100644 dashboard/src/app/components/badge/badge.scss delete mode 100644 dashboard/src/app/components/badge/badge.ts delete mode 100644 dashboard/src/app/components/blockui/blockui.css delete mode 100644 dashboard/src/app/components/blockui/blockui.spec.ts delete mode 100644 dashboard/src/app/components/blockui/blockui.ts delete mode 100644 dashboard/src/app/components/breadcrumb/breadcrumb.css delete mode 100644 dashboard/src/app/components/breadcrumb/breadcrumb.spec.ts delete mode 100644 dashboard/src/app/components/breadcrumb/breadcrumb.ts delete mode 100644 dashboard/src/app/components/button/button.scss delete mode 100644 dashboard/src/app/components/button/button.spec.ts delete mode 100644 dashboard/src/app/components/button/button.ts delete mode 100644 dashboard/src/app/components/calendar/calendar.css delete mode 100644 dashboard/src/app/components/calendar/calendar.spec.ts delete mode 100644 dashboard/src/app/components/calendar/calendar.ts delete mode 100644 dashboard/src/app/components/captcha/captcha.spec.ts delete mode 100644 dashboard/src/app/components/captcha/captcha.ts delete mode 100644 dashboard/src/app/components/card/card.css delete mode 100644 dashboard/src/app/components/card/card.spec.ts delete mode 100644 dashboard/src/app/components/card/card.ts delete mode 100644 dashboard/src/app/components/carousel/carousel.css delete mode 100644 dashboard/src/app/components/carousel/carousel.spec.ts delete mode 100644 dashboard/src/app/components/carousel/carousel.ts delete mode 100644 dashboard/src/app/components/chart/chart.spec.ts delete mode 100644 dashboard/src/app/components/chart/chart.ts delete mode 100644 dashboard/src/app/components/checkbox/checkbox.css delete mode 100644 dashboard/src/app/components/checkbox/checkbox.spec.ts delete mode 100644 dashboard/src/app/components/checkbox/checkbox.ts delete mode 100644 dashboard/src/app/components/chips/chips.css delete mode 100644 dashboard/src/app/components/chips/chips.spec.ts delete mode 100644 dashboard/src/app/components/chips/chips.ts delete mode 100644 dashboard/src/app/components/codehighlighter/codehighlighter.spec.ts delete mode 100644 dashboard/src/app/components/codehighlighter/codehighlighter.ts delete mode 100644 dashboard/src/app/components/colorpicker/colorpicker.css delete mode 100644 dashboard/src/app/components/colorpicker/colorpicker.spec.ts delete mode 100644 dashboard/src/app/components/colorpicker/colorpicker.ts delete mode 100644 dashboard/src/app/components/colorpicker/images/color.png delete mode 100644 dashboard/src/app/components/colorpicker/images/hue.png delete mode 100644 dashboard/src/app/components/common/I18N.ts delete mode 100644 dashboard/src/app/components/common/api.ts delete mode 100644 dashboard/src/app/components/common/blockableui.ts delete mode 100644 dashboard/src/app/components/common/common.scss delete mode 100644 dashboard/src/app/components/common/confirmation.ts delete mode 100644 dashboard/src/app/components/common/confirmationservice.ts delete mode 100644 dashboard/src/app/components/common/filtermetadata.ts delete mode 100644 dashboard/src/app/components/common/keys.pipe.ts delete mode 100644 dashboard/src/app/components/common/lazyloadevent.ts delete mode 100644 dashboard/src/app/components/common/menuitem.ts delete mode 100644 dashboard/src/app/components/common/message.ts delete mode 100644 dashboard/src/app/components/common/messageservice.ts delete mode 100644 dashboard/src/app/components/common/selectitem.ts delete mode 100644 dashboard/src/app/components/common/selectitemgroup.ts delete mode 100644 dashboard/src/app/components/common/shared.ts delete mode 100644 dashboard/src/app/components/common/sortevent.ts delete mode 100644 dashboard/src/app/components/common/sortmeta.ts delete mode 100644 dashboard/src/app/components/common/treedragdropservice.ts delete mode 100644 dashboard/src/app/components/common/treenode.ts delete mode 100644 dashboard/src/app/components/common/treenodedragevent.ts delete mode 100644 dashboard/src/app/components/confirmdialog/confirmdialog.spec.ts delete mode 100644 dashboard/src/app/components/confirmdialog/confirmdialog.ts delete mode 100644 dashboard/src/app/components/contextmenu/contextmenu.css delete mode 100644 dashboard/src/app/components/contextmenu/contextmenu.spec.ts delete mode 100644 dashboard/src/app/components/contextmenu/contextmenu.ts delete mode 100644 dashboard/src/app/components/datagrid/datagrid.css delete mode 100644 dashboard/src/app/components/datagrid/datagrid.spec.ts delete mode 100644 dashboard/src/app/components/datagrid/datagrid.ts delete mode 100644 dashboard/src/app/components/datalist/datalist.css delete mode 100644 dashboard/src/app/components/datalist/datalist.spec.ts delete mode 100644 dashboard/src/app/components/datalist/datalist.ts delete mode 100644 dashboard/src/app/components/datascroller/datascroller.css delete mode 100644 dashboard/src/app/components/datascroller/datascroller.spec.ts delete mode 100644 dashboard/src/app/components/datascroller/datascroller.ts delete mode 100644 dashboard/src/app/components/datatable/datatable.scss delete mode 100644 dashboard/src/app/components/datatable/datatable.spec.ts delete mode 100644 dashboard/src/app/components/datatable/datatable.ts delete mode 100644 dashboard/src/app/components/dataview/dataview.css delete mode 100644 dashboard/src/app/components/dataview/dataview.ts delete mode 100644 dashboard/src/app/components/defer/defer.ts delete mode 100644 dashboard/src/app/components/dialog/dialog.scss delete mode 100644 dashboard/src/app/components/dialog/dialog.spec.ts delete mode 100644 dashboard/src/app/components/dialog/dialog.ts delete mode 100644 dashboard/src/app/components/dom/domhandler.ts delete mode 100644 dashboard/src/app/components/dragdrop/dragdrop.spec.ts delete mode 100644 dashboard/src/app/components/dragdrop/dragdrop.ts delete mode 100644 dashboard/src/app/components/dropdown/dropdown.scss delete mode 100644 dashboard/src/app/components/dropdown/dropdown.spec.ts delete mode 100644 dashboard/src/app/components/dropdown/dropdown.ts delete mode 100644 dashboard/src/app/components/dropmenu/dropmenu.scss delete mode 100644 dashboard/src/app/components/dropmenu/dropmenu.ts delete mode 100644 dashboard/src/app/components/editor/editor.spec.ts delete mode 100644 dashboard/src/app/components/editor/editor.ts delete mode 100644 dashboard/src/app/components/fieldset/fieldset.css delete mode 100644 dashboard/src/app/components/fieldset/fieldset.spec.ts delete mode 100644 dashboard/src/app/components/fieldset/fieldset.ts delete mode 100644 dashboard/src/app/components/fileupload/fileupload.css delete mode 100644 dashboard/src/app/components/fileupload/fileupload.spec.ts delete mode 100644 dashboard/src/app/components/fileupload/fileupload.ts delete mode 100644 dashboard/src/app/components/form/form.scss delete mode 100644 dashboard/src/app/components/form/form.ts delete mode 100644 dashboard/src/app/components/galleria/galleria.css delete mode 100644 dashboard/src/app/components/galleria/galleria.spec.ts delete mode 100644 dashboard/src/app/components/galleria/galleria.ts delete mode 100644 dashboard/src/app/components/gmap/gmap.spec.ts delete mode 100644 dashboard/src/app/components/gmap/gmap.ts delete mode 100644 dashboard/src/app/components/grid/grid.css delete mode 100644 dashboard/src/app/components/growl/growl.css delete mode 100644 dashboard/src/app/components/growl/growl.spec.ts delete mode 100644 dashboard/src/app/components/growl/growl.ts delete mode 100644 dashboard/src/app/components/inplace/inplace.css delete mode 100644 dashboard/src/app/components/inplace/inplace.spec.ts delete mode 100644 dashboard/src/app/components/inplace/inplace.ts delete mode 100644 dashboard/src/app/components/inputmask/inputmask.spec.ts delete mode 100644 dashboard/src/app/components/inputmask/inputmask.ts delete mode 100644 dashboard/src/app/components/inputswitch/inputswitch.css delete mode 100644 dashboard/src/app/components/inputswitch/inputswitch.spec.ts delete mode 100644 dashboard/src/app/components/inputswitch/inputswitch.ts delete mode 100644 dashboard/src/app/components/inputtext/inputtext.scss delete mode 100644 dashboard/src/app/components/inputtext/inputtext.spec.ts delete mode 100644 dashboard/src/app/components/inputtext/inputtext.ts delete mode 100644 dashboard/src/app/components/inputtextarea/inputtextarea.css delete mode 100644 dashboard/src/app/components/inputtextarea/inputtextarea.spec.ts delete mode 100644 dashboard/src/app/components/inputtextarea/inputtextarea.ts delete mode 100644 dashboard/src/app/components/keyfilter/keyfilter.spec.ts delete mode 100644 dashboard/src/app/components/keyfilter/keyfilter.ts delete mode 100644 dashboard/src/app/components/lightbox/images/loading.gif delete mode 100644 dashboard/src/app/components/lightbox/lightbox.css delete mode 100644 dashboard/src/app/components/lightbox/lightbox.spec.ts delete mode 100644 dashboard/src/app/components/lightbox/lightbox.ts delete mode 100644 dashboard/src/app/components/listbox/listbox.css delete mode 100644 dashboard/src/app/components/listbox/listbox.spec.ts delete mode 100644 dashboard/src/app/components/listbox/listbox.ts delete mode 100644 dashboard/src/app/components/megamenu/megamenu.css delete mode 100644 dashboard/src/app/components/megamenu/megamenu.spec.ts delete mode 100644 dashboard/src/app/components/megamenu/megamenu.ts delete mode 100644 dashboard/src/app/components/menu/menu.css delete mode 100644 dashboard/src/app/components/menu/menu.spec.ts delete mode 100644 dashboard/src/app/components/menu/menu.ts delete mode 100644 dashboard/src/app/components/menubar/menubar.css delete mode 100644 dashboard/src/app/components/menubar/menubar.spec.ts delete mode 100644 dashboard/src/app/components/menubar/menubar.ts delete mode 100644 dashboard/src/app/components/message/message.css delete mode 100644 dashboard/src/app/components/message/message.spec.ts delete mode 100644 dashboard/src/app/components/message/message.ts delete mode 100644 dashboard/src/app/components/messages/messages.css delete mode 100644 dashboard/src/app/components/messages/messages.spec.ts delete mode 100644 dashboard/src/app/components/messages/messages.ts delete mode 100644 dashboard/src/app/components/msgbox/msgbox.ts delete mode 100644 dashboard/src/app/components/multiselect/multiselect.css delete mode 100644 dashboard/src/app/components/multiselect/multiselect.spec.ts delete mode 100644 dashboard/src/app/components/multiselect/multiselect.ts delete mode 100644 dashboard/src/app/components/orderlist/orderlist.css delete mode 100644 dashboard/src/app/components/orderlist/orderlist.spec.ts delete mode 100644 dashboard/src/app/components/orderlist/orderlist.ts delete mode 100644 dashboard/src/app/components/organizationchart/organizationchart.css delete mode 100644 dashboard/src/app/components/organizationchart/organizationchart.spec.ts delete mode 100644 dashboard/src/app/components/organizationchart/organizationchart.ts delete mode 100644 dashboard/src/app/components/overlaypanel/overlaypanel.css delete mode 100644 dashboard/src/app/components/overlaypanel/overlaypanel.spec.ts delete mode 100644 dashboard/src/app/components/overlaypanel/overlaypanel.ts delete mode 100644 dashboard/src/app/components/paginator/paginator.scss delete mode 100644 dashboard/src/app/components/paginator/paginator.spec.ts delete mode 100644 dashboard/src/app/components/paginator/paginator.ts delete mode 100644 dashboard/src/app/components/panel/panel.css delete mode 100644 dashboard/src/app/components/panel/panel.spec.ts delete mode 100644 dashboard/src/app/components/panel/panel.ts delete mode 100644 dashboard/src/app/components/panelmenu/panelmenu.css delete mode 100644 dashboard/src/app/components/panelmenu/panelmenu.spec.ts delete mode 100644 dashboard/src/app/components/panelmenu/panelmenu.ts delete mode 100644 dashboard/src/app/components/password/images/password-meter.png delete mode 100644 dashboard/src/app/components/password/password.css delete mode 100644 dashboard/src/app/components/password/password.spec.ts delete mode 100644 dashboard/src/app/components/password/password.ts delete mode 100644 dashboard/src/app/components/picklist/picklist.css delete mode 100644 dashboard/src/app/components/picklist/picklist.spec.ts delete mode 100644 dashboard/src/app/components/picklist/picklist.ts delete mode 100644 dashboard/src/app/components/progressbar/progressbar.css delete mode 100644 dashboard/src/app/components/progressbar/progressbar.spec.ts delete mode 100644 dashboard/src/app/components/progressbar/progressbar.ts delete mode 100644 dashboard/src/app/components/progressspinner/progressspinner.css delete mode 100644 dashboard/src/app/components/progressspinner/progressspinner.spec.ts delete mode 100644 dashboard/src/app/components/progressspinner/progressspinner.ts delete mode 100644 dashboard/src/app/components/radiobutton/radiobutton.css delete mode 100644 dashboard/src/app/components/radiobutton/radiobutton.spec.ts delete mode 100644 dashboard/src/app/components/radiobutton/radiobutton.ts delete mode 100644 dashboard/src/app/components/rating/rating.spec.ts delete mode 100644 dashboard/src/app/components/rating/rating.ts delete mode 100644 dashboard/src/app/components/schedule/schedule.css delete mode 100644 dashboard/src/app/components/schedule/schedule.spec.ts delete mode 100644 dashboard/src/app/components/schedule/schedule.ts delete mode 100644 dashboard/src/app/components/scrollpanel/scrollpanel.css delete mode 100644 dashboard/src/app/components/scrollpanel/scrollpanel.spec.ts delete mode 100644 dashboard/src/app/components/scrollpanel/scrollpanel.ts delete mode 100644 dashboard/src/app/components/selectbutton/selectbutton.css delete mode 100644 dashboard/src/app/components/selectbutton/selectbutton.spec.ts delete mode 100644 dashboard/src/app/components/selectbutton/selectbutton.ts delete mode 100644 dashboard/src/app/components/sidebar/sidebar.css delete mode 100644 dashboard/src/app/components/sidebar/sidebar.spec.ts delete mode 100644 dashboard/src/app/components/sidebar/sidebar.ts delete mode 100644 dashboard/src/app/components/slidemenu/slidemenu.css delete mode 100644 dashboard/src/app/components/slidemenu/slidemenu.spec.ts delete mode 100644 dashboard/src/app/components/slidemenu/slidemenu.ts delete mode 100644 dashboard/src/app/components/slider/slider.css delete mode 100644 dashboard/src/app/components/slider/slider.spec.ts delete mode 100644 dashboard/src/app/components/slider/slider.ts delete mode 100644 dashboard/src/app/components/spinner/spinner.css delete mode 100644 dashboard/src/app/components/spinner/spinner.spec.ts delete mode 100644 dashboard/src/app/components/spinner/spinner.ts delete mode 100644 dashboard/src/app/components/splitbutton/splitbutton.css delete mode 100644 dashboard/src/app/components/splitbutton/splitbutton.spec.ts delete mode 100644 dashboard/src/app/components/splitbutton/splitbutton.ts delete mode 100644 dashboard/src/app/components/steps/steps.css delete mode 100644 dashboard/src/app/components/steps/steps.spec.ts delete mode 100644 dashboard/src/app/components/steps/steps.ts delete mode 100644 dashboard/src/app/components/table/table.css delete mode 100644 dashboard/src/app/components/table/table.ts delete mode 100644 dashboard/src/app/components/tabmenu/tabmenu.css delete mode 100644 dashboard/src/app/components/tabmenu/tabmenu.spec.ts delete mode 100644 dashboard/src/app/components/tabmenu/tabmenu.ts delete mode 100644 dashboard/src/app/components/tabview/tabview.scss delete mode 100644 dashboard/src/app/components/tabview/tabview.spec.ts delete mode 100644 dashboard/src/app/components/tabview/tabview.ts delete mode 100644 dashboard/src/app/components/terminal/terminal.css delete mode 100644 dashboard/src/app/components/terminal/terminal.spec.ts delete mode 100644 dashboard/src/app/components/terminal/terminal.ts delete mode 100644 dashboard/src/app/components/terminal/terminalservice.ts delete mode 100644 dashboard/src/app/components/tieredmenu/tieredmenu.css delete mode 100644 dashboard/src/app/components/tieredmenu/tieredmenu.spec.ts delete mode 100644 dashboard/src/app/components/tieredmenu/tieredmenu.ts delete mode 100644 dashboard/src/app/components/togglebutton/togglebutton.spec.ts delete mode 100644 dashboard/src/app/components/togglebutton/togglebutton.ts delete mode 100644 dashboard/src/app/components/toolbar/toolbar.css delete mode 100644 dashboard/src/app/components/toolbar/toolbar.spec.ts delete mode 100644 dashboard/src/app/components/toolbar/toolbar.ts delete mode 100644 dashboard/src/app/components/tooltip/tooltip.css delete mode 100644 dashboard/src/app/components/tooltip/tooltip.spec.ts delete mode 100644 dashboard/src/app/components/tooltip/tooltip.ts delete mode 100644 dashboard/src/app/components/tree/images/line.gif delete mode 100644 dashboard/src/app/components/tree/tree.css delete mode 100644 dashboard/src/app/components/tree/tree.spec.ts delete mode 100644 dashboard/src/app/components/tree/tree.ts delete mode 100644 dashboard/src/app/components/treetable/treetable.css delete mode 100644 dashboard/src/app/components/treetable/treetable.spec.ts delete mode 100644 dashboard/src/app/components/treetable/treetable.ts delete mode 100644 dashboard/src/app/components/tristatecheckbox/tristatecheckbox.spec.ts delete mode 100644 dashboard/src/app/components/tristatecheckbox/tristatecheckbox.ts delete mode 100644 dashboard/src/app/components/utils/objectutils.spec.ts delete mode 100644 dashboard/src/app/components/utils/objectutils.ts delete mode 100644 dashboard/src/app/i18n/en/exception.json delete mode 100644 dashboard/src/app/i18n/en/keyID.json delete mode 100644 dashboard/src/app/i18n/en/widgetsKeyID.json delete mode 100644 dashboard/src/app/i18n/zh/exception.json delete mode 100644 dashboard/src/app/i18n/zh/keyID.json delete mode 100644 dashboard/src/app/i18n/zh/widgetsKeyID.json delete mode 100644 dashboard/src/app/shared/api.ts delete mode 100644 dashboard/src/app/shared/service/Exception.service.ts delete mode 100644 dashboard/src/app/shared/service/Http.service.ts delete mode 100644 dashboard/src/app/shared/service/I18N.service.ts delete mode 100644 dashboard/src/app/shared/service/MsgBox.service.ts delete mode 100644 dashboard/src/app/shared/service/ParamStor.service.ts delete mode 100644 dashboard/src/app/shared/service/api.ts delete mode 100644 dashboard/src/app/shared/shared.config.ts delete mode 100644 dashboard/src/app/shared/shared.module.ts delete mode 100644 dashboard/src/app/shared/utils/consts.ts delete mode 100644 dashboard/src/app/shared/utils/mask.ts delete mode 100644 dashboard/src/app/shared/utils/utils.ts delete mode 100644 dashboard/src/assets/.gitkeep delete mode 100644 dashboard/src/assets/business/css/primeng.scss delete mode 100644 dashboard/src/assets/business/css/site.scss delete mode 100644 dashboard/src/assets/business/favicon/favicon.ico delete mode 100644 dashboard/src/assets/business/fonts/roboto-v15-latin-regular.eot delete mode 100644 dashboard/src/assets/business/fonts/roboto-v15-latin-regular.svg delete mode 100644 dashboard/src/assets/business/fonts/roboto-v15-latin-regular.ttf delete mode 100644 dashboard/src/assets/business/fonts/roboto-v15-latin-regular.woff delete mode 100644 dashboard/src/assets/business/fonts/roboto-v15-latin-regular.woff2 delete mode 100644 dashboard/src/assets/business/images/cloud_service/AWS S3.png delete mode 100644 dashboard/src/assets/business/images/cloud_service/Huawei OBS.png delete mode 100644 dashboard/src/assets/business/images/cloud_service/Microsoft Azure Blob Storage.png delete mode 100644 dashboard/src/assets/business/images/cloud_service/u2309.png delete mode 100644 dashboard/src/assets/business/images/home_admin/Block Storages.png delete mode 100644 dashboard/src/assets/business/images/home_admin/Cross-Region Migrations.png delete mode 100644 dashboard/src/assets/business/images/home_admin/Cross-Region Replications.png delete mode 100644 dashboard/src/assets/business/images/home_admin/Storage Pools.png delete mode 100644 dashboard/src/assets/business/images/home_admin/Tenants.png delete mode 100644 dashboard/src/assets/business/images/home_admin/Users.png delete mode 100644 dashboard/src/assets/business/images/home_admin/Volume Replications.png delete mode 100644 dashboard/src/assets/business/images/home_admin/Volume Snapshots.png delete mode 100644 dashboard/src/assets/business/images/home_admin/Volumes.png delete mode 100644 dashboard/src/assets/business/images/home_admin/u199.png delete mode 100644 dashboard/src/assets/business/images/home_admin/u236.png delete mode 100644 dashboard/src/assets/business/images/icons/button-active.svg delete mode 100644 dashboard/src/assets/business/images/icons/button.svg delete mode 100644 dashboard/src/assets/business/images/icons/charts-active.svg delete mode 100644 dashboard/src/assets/business/images/icons/charts.svg delete mode 100644 dashboard/src/assets/business/images/icons/data-active.svg delete mode 100644 dashboard/src/assets/business/images/icons/data.svg delete mode 100644 dashboard/src/assets/business/images/icons/dragdrop-active.svg delete mode 100644 dashboard/src/assets/business/images/icons/dragdrop.svg delete mode 100644 dashboard/src/assets/business/images/icons/file-active.svg delete mode 100644 dashboard/src/assets/business/images/icons/file.svg delete mode 100644 dashboard/src/assets/business/images/icons/input-active.svg delete mode 100644 dashboard/src/assets/business/images/icons/input.svg delete mode 100644 dashboard/src/assets/business/images/icons/menu-active.svg delete mode 100644 dashboard/src/assets/business/images/icons/menu.svg delete mode 100644 dashboard/src/assets/business/images/icons/message-active.svg delete mode 100644 dashboard/src/assets/business/images/icons/message.svg delete mode 100644 dashboard/src/assets/business/images/icons/misc-active.svg delete mode 100644 dashboard/src/assets/business/images/icons/misc.svg delete mode 100644 dashboard/src/assets/business/images/icons/multimedia-active.svg delete mode 100644 dashboard/src/assets/business/images/icons/multimedia.svg delete mode 100644 dashboard/src/assets/business/images/icons/overlay-active.svg delete mode 100644 dashboard/src/assets/business/images/icons/overlay.svg delete mode 100644 dashboard/src/assets/business/images/icons/panel-active.svg delete mode 100644 dashboard/src/assets/business/images/icons/panel.svg delete mode 100644 dashboard/src/assets/business/images/login-bg.png delete mode 100644 dashboard/src/assets/business/images/logo-white.png delete mode 100644 dashboard/src/assets/business/images/logo.png delete mode 100644 dashboard/src/assets/business/images/menu-bg.png delete mode 100644 dashboard/src/assets/business/images/profile/u1065.png delete mode 100644 dashboard/src/assets/business/images/profile/u1985.png delete mode 100644 dashboard/src/assets/business/images/profile/u2861.png delete mode 100644 dashboard/src/assets/business/images/profile/u2987.png delete mode 100644 dashboard/src/assets/business/images/volume/u436.png delete mode 100644 dashboard/src/assets/business/images/volume/u583.png delete mode 100644 dashboard/src/assets/business/images/volume/u585.png delete mode 100644 dashboard/src/assets/business/images/volume/u740p000.png delete mode 100644 dashboard/src/assets/business/images/volume/u740p002.png delete mode 100644 dashboard/src/assets/business/images/volume/u760p000.png delete mode 100644 dashboard/src/assets/business/images/volume/u937.png delete mode 100644 dashboard/src/assets/components/images/line.gif delete mode 100644 dashboard/src/assets/components/images/loading.gif delete mode 100644 dashboard/src/assets/components/images/password-meter.png delete mode 100644 dashboard/src/assets/components/themes/_theme.scss delete mode 100644 dashboard/src/assets/components/themes/default/default.scss delete mode 100644 dashboard/src/assets/components/themes/default/fonts/roboto-v15-latin-regular.eot delete mode 100644 dashboard/src/assets/components/themes/default/fonts/roboto-v15-latin-regular.svg delete mode 100644 dashboard/src/assets/components/themes/default/fonts/roboto-v15-latin-regular.ttf delete mode 100644 dashboard/src/assets/components/themes/default/fonts/roboto-v15-latin-regular.woff delete mode 100644 dashboard/src/assets/components/themes/default/fonts/roboto-v15-latin-regular.woff2 delete mode 100644 dashboard/src/assets/components/themes/default/images/icons_16.png delete mode 100644 dashboard/src/assets/components/themes/default/images/slider_handles.png delete mode 100644 dashboard/src/assets/components/themes/default/images/slider_handles@2x.png delete mode 100644 dashboard/src/assets/components/themes/default/images/ui-bg_flat_0_aaaaaa_40x100.png delete mode 100644 dashboard/src/assets/components/themes/default/images/ui-bg_flat_75_ffffff_40x100.png delete mode 100644 dashboard/src/assets/components/themes/default/images/ui-bg_glass_55_fbf9ee_1x400.png delete mode 100644 dashboard/src/assets/components/themes/default/images/ui-bg_glass_65_ffffff_1x400.png delete mode 100644 dashboard/src/assets/components/themes/default/images/ui-bg_glass_75_dadada_1x400.png delete mode 100644 dashboard/src/assets/components/themes/default/images/ui-bg_glass_75_e6e6e6_1x400.png delete mode 100644 dashboard/src/assets/components/themes/default/images/ui-bg_glass_95_fef1ec_1x400.png delete mode 100644 dashboard/src/assets/components/themes/default/images/ui-bg_highlight-soft_75_cccccc_1x100.png delete mode 100644 dashboard/src/assets/components/themes/default/images/ui-icons_222222_256x240.png delete mode 100644 dashboard/src/assets/components/themes/default/images/ui-icons_2e83ff_256x240.png delete mode 100644 dashboard/src/assets/components/themes/default/images/ui-icons_454545_256x240.png delete mode 100644 dashboard/src/assets/components/themes/default/images/ui-icons_cd0a0a_256x240.png delete mode 100644 dashboard/src/assets/components/themes/default/images/ui-icons_ffffff_256x240.png delete mode 100644 dashboard/src/environments/environment.prod.ts delete mode 100644 dashboard/src/environments/environment.ts delete mode 100644 dashboard/src/index.html delete mode 100644 dashboard/src/main.ts delete mode 100644 dashboard/src/polyfills.ts delete mode 100644 dashboard/src/styles.scss delete mode 100644 dashboard/src/test.ts delete mode 100644 dashboard/src/tsconfig.app.json delete mode 100644 dashboard/src/tsconfig.spec.json delete mode 100644 dashboard/src/typings.d.ts delete mode 100644 dashboard/src/upload.php delete mode 100644 dashboard/tsconfig-aot.json delete mode 100644 dashboard/tsconfig-release.json delete mode 100644 dashboard/tsconfig.json delete mode 100644 dashboard/tslint.json diff --git a/.travis.yml b/.travis.yml index e6c9d4ba4..5fd1ac82c 100755 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,7 @@ go_import_path: github.com/opensds/opensds go: - 1.9.x + - 1.11.x - tip env: diff --git a/dashboard/.angular-cli.json b/dashboard/.angular-cli.json deleted file mode 100644 index df63f8d03..000000000 --- a/dashboard/.angular-cli.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "$schema": "./node_modules/@angular/cli/lib/config/schema.json", - "project": { - "name": "primeng" - }, - "apps": [ - { - "root": "src", - "outDir": "dist", - "assets": [ - "assets", - "upload.php", - "favicon.png", - { "glob": "**/**", "input": "./assets", "output": "./assets/"}, - { "glob": "**/**", "input": "./app/i18n", "output": "./src/app/i18n/"} - ], - "index": "index.html", - "main": "main.ts", - "polyfills": "polyfills.ts", - "test": "test.ts", - "tsconfig": "tsconfig.app.json", - "testTsconfig": "tsconfig.spec.json", - "prefix": "app", - "styles": [ - "../node_modules/fullcalendar/dist/fullcalendar.min.css", - "../node_modules/quill/dist/quill.snow.css", - "../node_modules/font-awesome/css/font-awesome.min.css", - "styles.scss" - ], - "scripts": [ - "../node_modules/jquery/dist/jquery.js", - "../node_modules/moment/moment.js", - "../node_modules/chart.js/dist/Chart.js", - "../node_modules/fullcalendar/dist/fullcalendar.js", - "../node_modules/quill/dist/quill.js", - "../node_modules/prismjs/prism.js", - "../node_modules/prismjs/components/prism-typescript.js" - ], - "environmentSource": "environments/environment.ts", - "environments": { - "dev": "environments/environment.ts", - "prod": "environments/environment.prod.ts" - } - } - ], - "e2e": { - "protractor": { - "config": "./protractor.conf.js" - } - }, - "lint": [ - { - "project": "src/tsconfig.app.json" - }, - { - "project": "src/tsconfig.spec.json" - }, - { - "project": "e2e/tsconfig.e2e.json" - } - ], - "test": { - "karma": { - "config": "./karma.conf.js" - } - }, - "defaults": { - "styleExt": "css", - "component": {} - } -} diff --git a/dashboard/.editorconfig b/dashboard/.editorconfig deleted file mode 100644 index 9b7352176..000000000 --- a/dashboard/.editorconfig +++ /dev/null @@ -1,13 +0,0 @@ -# Editor configuration, see http://editorconfig.org -root = true - -[*] -charset = utf-8 -indent_style = space -indent_size = 4 -insert_final_newline = true -trim_trailing_whitespace = true - -[*.md] -max_line_length = off -trim_trailing_whitespace = false diff --git a/dashboard/.gitignore b/dashboard/.gitignore deleted file mode 100644 index 825c75d0a..000000000 --- a/dashboard/.gitignore +++ /dev/null @@ -1,50 +0,0 @@ -# See http://help.github.com/ignore-files/ for more about ignoring files. - -# compiled output -/dist -/tmp -/out-tsc -/components -/resources -/aot - -# dependencies -/node_modules - -# IDEs and editors -/.idea -.project -.classpath -.c9/ -*.launch -.settings/ -*.sublime-workspace - -# IDE - VSCode -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json - -# misc -/.sass-cache -/connect.lock -/coverage -/libpeerconnection.log -npm-debug.log -testem.log -/typings - -# themes -/src/assets/components/themes/**/*.css -/src/assets/components/themes/**/*.map -!/src/assets/components/themes/bootstrap/theme.css - -# e2e -/e2e/*.js -/e2e/*.map - -# System Files -.DS_Store -Thumbs.db diff --git a/dashboard/.npmignore b/dashboard/.npmignore deleted file mode 100644 index 98f95cfdc..000000000 --- a/dashboard/.npmignore +++ /dev/null @@ -1,67 +0,0 @@ -# compiled output -/dist -/tmp -/out-tsc -/aot - -# source -src - -# test -e2e -karma.conf.js -protractor.conf.js -*.spec.d.ts -*.spec.js -*.spec.js.map -*.spec.metadata.json -*.spec.ngsummary.json - -# dependencies -node_modules - -# IDEs and editors -/.idea -.project -.classpath -.c9/ -*.launch -.settings/ -*.sublime-workspace -.editor-config - -# IDE - VSCode -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json - -# misc -/.sass-cache -/connect.lock -/coverage -/libpeerconnection.log -npm-debug.log -testem.log -/typings -.gitignore -exports - -# config -.angular-cli.json -tsconfig.json -tsconfig-release.json -tsconfig-aot.json -tslint.json -gulpfile.js -.github - -# System Files -.DS_Store -Thumbs.db - -# aot -*.ngfactory.js -*.ngfactory.js.map -*.ngsummary.json \ No newline at end of file diff --git a/dashboard/.travis.yml b/dashboard/.travis.yml deleted file mode 100644 index 7cbe366e4..000000000 --- a/dashboard/.travis.yml +++ /dev/null @@ -1,23 +0,0 @@ -language: node_js -sudo: required -node_js: - - node - -before_script: - - "sudo chown root /opt/google/chrome/chrome-sandbox" - - "sudo chmod 4755 /opt/google/chrome/chrome-sandbox" - -before_install: - - export CHROME_BIN=chromium-browser - - export DISPLAY=:99.0 - - sh -e /etc/init.d/xvfb start - -script: # the build step - - node_modules/.bin/ng test --colors=false --progress=false --single-run - - -cache: - yarn: true - directories: - - ./node_modules - - ./.chrome/chromium \ No newline at end of file diff --git a/dashboard/Dockerfile b/dashboard/Dockerfile deleted file mode 100644 index cb51b0043..000000000 --- a/dashboard/Dockerfile +++ /dev/null @@ -1,35 +0,0 @@ -# Docker build usage: -# docker build . -t opensdsio/dashboard:latest -# Docker run usage: -# docker run -d -p 8088:8088 opensdsio/dashboard:latest - -FROM ubuntu:16.04 -MAINTAINER Leon Wang - -ARG DEBIAN_FRONTEND=noninteractive - -# Download and install some packages. -RUN apt-get update && apt-get install -y --no-install-recommends \ - sudo \ - wget \ - make \ - g++ \ - nginx \ - && rm -rf /var/lib/apt/lists/* \ - && apt-get clean -RUN wget --no-check-certificate https://deb.nodesource.com/setup_8.x \ - && chmod +x setup_8.x && ./setup_8.x \ - && apt-get install -y nodejs - -# Current directory is always /opt/dashboard. -WORKDIR /opt/dashboard - -# Copy dashboard source code into container before running command. -COPY ./ ./ - -RUN chmod 755 ./image_builder.sh \ - && sudo ./image_builder.sh -RUN sudo ./image_builder.sh --rebuild - -# Define default command. -CMD /usr/sbin/nginx -g "daemon off;" diff --git a/dashboard/LICENSE.md b/dashboard/LICENSE.md deleted file mode 100644 index 02647baee..000000000 --- a/dashboard/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016-2017 PrimeTek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/dashboard/Makefile b/dashboard/Makefile deleted file mode 100644 index 9601d10fb..000000000 --- a/dashboard/Makefile +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2018 Huawei Technologies Co., Ltd. All Rights Reserved. -# -# Licensed 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. - -IMAGE = opensdsio/dashboard -VERSION := latest - -all:build -.PHONY: all - -build:dashboard -.PHONY: build - -dashboard:package - chmod +x ./image_builder.sh \ - && ./image_builder.sh -.PHONY: dashboard - -package: - apt-get update && apt-get install -y --no-install-recommends \ - wget \ - make \ - g++ \ - nginx \ - && rm -rf /var/lib/apt/lists/* \ - && apt-get clean - wget --no-check-certificate https://deb.nodesource.com/setup_8.x \ - && chmod +x setup_8.x && ./setup_8.x \ - && apt-get install -y nodejs -.PHONY: package - -docker: - docker build . -t $(IMAGE):$(VERSION) -.PHONY: docker - -clean: - service nginx stop - rm -rf /etc/nginx/sites-available/default /var/www/html/* ./dist warn=False - npm uninstall --unsafe-perm - npm uninstall --unsafe-perm -g @angular/cli@1.7.4 - apt-get --purge remove -y nodejs nginx \ - && rm -rf ./setup_8.x warn=False -.PHONY: clean diff --git a/dashboard/README.md b/dashboard/README.md deleted file mode 100644 index 2e26c0f97..000000000 --- a/dashboard/README.md +++ /dev/null @@ -1,77 +0,0 @@ -# Summary -OpenSDS dashboard uses the front-end development framework Angular5 (https://angular.io/) -and relies on PrimeNG UI Components (https://www.primefaces.org/primeng/). Regardless of -deployment or two development, prepare the corresponding environment. - -# Prerequisite - -### 1. Ubuntu -* Version information -```shell -root@proxy:~# cat /etc/issue -Ubuntu 16.04.2 LTS \n \l -``` - -### 2. Nginx installation -```shell -sudo apt-get install nginx -``` - -### 3. NodeJS installation, NPM will be installed with nodejs. -```shell -curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - -sudo apt-get install -y nodejs -``` - -### 4. Angular CLI installation -Specify the version[1.7.4] of angular5 suitable for installation. -```shell -sudo npm install -g @angular/cli@1.7.4 -``` - - -# Build & Start -### 1. Git clone dashboard code. -```shell -git clone https://github.com/opensds/opensds.git -``` - -### 2. Build opensds dashboard. -After the build work finished, the files in the `dist` folder should be copied to the folder ` /var/www/html/`. -```shell -cd opensds/dashboard -sudo npm install -sudo ng build --prod -``` - -```shell -cp -R opensds/dashboard/dist/* /var/www/html/ -``` - -### 3. Set nginx default config. -```shell -vi /etc/nginx/sites-available/default -``` -Configure proxy, points to the resource server and the authentication server respectively. -Such as: -* Keystone server `http://1.1.1.0:5000` -* Resource server `http://1.1.1.0:50040` -```shell -location /v3/ { - proxy_pass http://1.1.1.0:5000/v3/; -} - -location /v1beta/ { - proxy_pass http://1.1.1.0:50040/v1beta/; -} -``` - -### 4. Restart nginx -```shell -service nginx restart -``` - -### 5. Access dashboard in browser. -```shell -http://localhost/ -``` diff --git a/dashboard/e2e/accordion.e2e-spec.ts b/dashboard/e2e/accordion.e2e-spec.ts deleted file mode 100644 index 5476c373d..000000000 --- a/dashboard/e2e/accordion.e2e-spec.ts +++ /dev/null @@ -1,20 +0,0 @@ -import {browser, by, element, ElementArrayFinder} from 'protractor'; - -describe('Accordion', () => { - let accordionHeaders: ElementArrayFinder; - let accordionContents: ElementArrayFinder; - - describe('Header Click', () => { - beforeEach(() => { - browser.get('#/accordion'); - accordionContents = element.all(by.css('.ui-accordion-content-wrapper')); - accordionHeaders = element.all(by.css('.ui-accordion-header')); - }); - - it('should close active content', () => { - accordionHeaders.get(0).click(); - expect(accordionContents.get(0).getCssValue('overflow')).toBe('hidden'); - }); - - }); -}); \ No newline at end of file diff --git a/dashboard/e2e/app.e2e-spec.ts b/dashboard/e2e/app.e2e-spec.ts deleted file mode 100644 index 83f61bb6a..000000000 --- a/dashboard/e2e/app.e2e-spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { PrimengPage } from './app.po'; - -describe('primeng App', () => { - let page: PrimengPage; - - beforeEach(() => { - page = new PrimengPage(); - }); - - it('should display welcome message', done => { - page.navigateTo(); - page.getPROText() - .then(msg => expect(msg).toEqual('PrimeNG PRO Support')) - .then(done, done.fail); - }); -}); diff --git a/dashboard/e2e/app.po.ts b/dashboard/e2e/app.po.ts deleted file mode 100644 index 7b1a2d7ee..000000000 --- a/dashboard/e2e/app.po.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { browser, by, element } from 'protractor'; - -export class PrimengPage { - navigateTo() { - return browser.get('/'); - } - - getPROText() { - return element(by.css('.pro-title')).getText(); - } -} diff --git a/dashboard/e2e/fieldset.e2e-spec.ts b/dashboard/e2e/fieldset.e2e-spec.ts deleted file mode 100644 index 4b417a44d..000000000 --- a/dashboard/e2e/fieldset.e2e-spec.ts +++ /dev/null @@ -1,27 +0,0 @@ -import {browser, by, element, ElementFinder, ElementArrayFinder} from 'protractor'; - -describe('Fieldset', () => { - let legend: ElementFinder; - let contentWrapper: ElementArrayFinder; - - describe('Toggle Icon Click', () => { - beforeEach(() => { - browser.get('#/fieldset'); - legend = element(by.css('.ui-fieldset-toggleable .ui-fieldset-legend')); - contentWrapper = element.all(by.css('.ui-fieldset-content-wrapper')); - }); - - it('should close active content', () => { - legend.click(); - expect(contentWrapper.get(1).getCssValue('overflow')).toBe('hidden'); - }); - - it('should toggle content', () => { - legend.click(); - browser.sleep(1000); - legend.click(); - expect(contentWrapper.get(1).getCssValue('height')).not.toBe('0'); - }); - - }); -}); \ No newline at end of file diff --git a/dashboard/e2e/inputtext.e2e-spec.ts b/dashboard/e2e/inputtext.e2e-spec.ts deleted file mode 100644 index 6022bcbb3..000000000 --- a/dashboard/e2e/inputtext.e2e-spec.ts +++ /dev/null @@ -1,34 +0,0 @@ -import {browser, by, element} from 'protractor'; - -describe('InputText', () => { - describe('Attribute Value', () => { - let inputEl = element(by.id('input')); - let spanEl = element(by.id('text')); - - beforeEach(() => { - browser.get('#/inputtext'); - }); - - it('should be displayed in the span element', () => { - inputEl.sendKeys('PrimeNG Rocks'); - expect(spanEl.getText()).toBe('PrimeNG Rocks'); - }); - }); - - describe('Disabled property', () => { - let disabledInput = element(by.id('disabled-input')); - let disableBtn = element(by.id('disabled-btn')); - - beforeEach(() => { - browser.get('#/inputtext'); - }); - - it('should prevent click handlers from executing when disabled', () => { - expect(disabledInput.isEnabled()).toBe(false); - }); - it('should become enabled with button click', () => { - disableBtn.click(); - expect(disabledInput.isEnabled()).toBe(true); - }); - }); -}); \ No newline at end of file diff --git a/dashboard/e2e/panel.e2e-spec.ts b/dashboard/e2e/panel.e2e-spec.ts deleted file mode 100644 index 299b0af9d..000000000 --- a/dashboard/e2e/panel.e2e-spec.ts +++ /dev/null @@ -1,27 +0,0 @@ -import {browser, by, element, ElementFinder, ElementArrayFinder} from 'protractor'; - -describe('Panel', () => { - let toggleIcon: ElementFinder; - let contentWrapper: ElementArrayFinder; - - describe('Toggle Icon Click', () => { - beforeEach(() => { - browser.get('#/panel'); - toggleIcon = element(by.css('.ui-panel-titlebar-icon')); - contentWrapper = element.all(by.css('.ui-panel-content-wrapper')); - }); - - it('should close active content', () => { - toggleIcon.click(); - expect(contentWrapper.get(0).getCssValue('overflow')).toBe('hidden'); - }); - - it('should toggle content', () => { - toggleIcon.click(); - browser.sleep(1000); - toggleIcon.click(); - expect(contentWrapper.get(0).getCssValue('height')).not.toBe('0'); - }); - - }); -}); \ No newline at end of file diff --git a/dashboard/e2e/tabview.e2e-spec.ts b/dashboard/e2e/tabview.e2e-spec.ts deleted file mode 100644 index ba717e9be..000000000 --- a/dashboard/e2e/tabview.e2e-spec.ts +++ /dev/null @@ -1,49 +0,0 @@ -import {browser, by, element, ElementArrayFinder} from 'protractor'; - -describe('TabView', () => { - let tabPanels: ElementArrayFinder; - let tabElements: ElementArrayFinder; - let closeIcons: ElementArrayFinder; - let closableTabPanels: ElementArrayFinder; - let closableTabElements: ElementArrayFinder; - - describe('Tab Click', () => { - beforeEach(() => { - browser.get('#/tabview'); - tabPanels = element.all(by.css('.ui-tabview-panel')); - tabElements = element.all(by.css('.ui-tabview-nav li')); - }); - - it('should switch panels', () => { - tabElements.get(1).click(); - expect(tabPanels.get(1).getCssValue('display')).toBe('block'); - }); - - }); - describe('Close Icon Click', () => { - beforeEach(() => { - browser.get('#/tabview'); - closableTabElements = element.all(by.css('#closableTabView .ui-tabview-nav li')); - closeIcons = element.all(by.css('#closableTabView .ui-tabview-nav li .ui-tabview-close')); - }); - - it('should delete closed panel', () => { - closeIcons.get(0).click(); - expect(closableTabElements.count()).toBe(2); - }); - }); - describe('Close Icon Click on an active tab', () => { - beforeEach(() => { - browser.get('#/tabview'); - closableTabPanels = element.all(by.css('#closableTabView .ui-tabview-panel')); - closableTabElements = element.all(by.css('#closableTabView .ui-tabview-nav li')); - closeIcons = element.all(by.css('#closableTabView .ui-tabview-nav li .ui-tabview-close')); - }); - - it('should close that panel and first tab should be active', () => { - closableTabElements.get(2).click(); - closeIcons.get(1).click(); - expect(closableTabPanels.get(0).getCssValue('display')).toBe('block'); - }); - }); -}); \ No newline at end of file diff --git a/dashboard/e2e/tsconfig.e2e.json b/dashboard/e2e/tsconfig.e2e.json deleted file mode 100644 index e2a9a2fc7..000000000 --- a/dashboard/e2e/tsconfig.e2e.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "outDir": "../out-tsc/e2e", - "module": "commonjs", - "target": "es5", - "types": [ - "jasmine", - "node" - ] - } -} diff --git a/dashboard/exports/accordion.d.ts b/dashboard/exports/accordion.d.ts deleted file mode 100644 index 452bb1c17..000000000 --- a/dashboard/exports/accordion.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/accordion/accordion'; \ No newline at end of file diff --git a/dashboard/exports/accordion.js b/dashboard/exports/accordion.js deleted file mode 100644 index 01ce630d8..000000000 --- a/dashboard/exports/accordion.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/accordion/accordion")); \ No newline at end of file diff --git a/dashboard/exports/api.d.ts b/dashboard/exports/api.d.ts deleted file mode 100644 index 719f575ac..000000000 --- a/dashboard/exports/api.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/common/api'; \ No newline at end of file diff --git a/dashboard/exports/api.js b/dashboard/exports/api.js deleted file mode 100644 index 0a03470e5..000000000 --- a/dashboard/exports/api.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/common/api")); \ No newline at end of file diff --git a/dashboard/exports/autocomplete.d.ts b/dashboard/exports/autocomplete.d.ts deleted file mode 100644 index 1ac0ce8cd..000000000 --- a/dashboard/exports/autocomplete.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/autocomplete/autocomplete'; \ No newline at end of file diff --git a/dashboard/exports/autocomplete.js b/dashboard/exports/autocomplete.js deleted file mode 100644 index 8d1ad87ff..000000000 --- a/dashboard/exports/autocomplete.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/autocomplete/autocomplete")); \ No newline at end of file diff --git a/dashboard/exports/blockui.d.ts b/dashboard/exports/blockui.d.ts deleted file mode 100644 index 64124130b..000000000 --- a/dashboard/exports/blockui.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/blockui/blockui'; \ No newline at end of file diff --git a/dashboard/exports/blockui.js b/dashboard/exports/blockui.js deleted file mode 100644 index 06926523c..000000000 --- a/dashboard/exports/blockui.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/blockui/blockui")); \ No newline at end of file diff --git a/dashboard/exports/breadcrumb.d.ts b/dashboard/exports/breadcrumb.d.ts deleted file mode 100644 index b81a3729d..000000000 --- a/dashboard/exports/breadcrumb.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/breadcrumb/breadcrumb'; \ No newline at end of file diff --git a/dashboard/exports/breadcrumb.js b/dashboard/exports/breadcrumb.js deleted file mode 100644 index f4ed86279..000000000 --- a/dashboard/exports/breadcrumb.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/breadcrumb/breadcrumb")); \ No newline at end of file diff --git a/dashboard/exports/button.d.ts b/dashboard/exports/button.d.ts deleted file mode 100644 index 945534232..000000000 --- a/dashboard/exports/button.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/button/button'; \ No newline at end of file diff --git a/dashboard/exports/button.js b/dashboard/exports/button.js deleted file mode 100644 index 9b5036483..000000000 --- a/dashboard/exports/button.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/button/button")); \ No newline at end of file diff --git a/dashboard/exports/calendar.d.ts b/dashboard/exports/calendar.d.ts deleted file mode 100644 index eadf99239..000000000 --- a/dashboard/exports/calendar.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/calendar/calendar'; \ No newline at end of file diff --git a/dashboard/exports/calendar.js b/dashboard/exports/calendar.js deleted file mode 100644 index f048d89eb..000000000 --- a/dashboard/exports/calendar.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/calendar/calendar")); \ No newline at end of file diff --git a/dashboard/exports/captcha.d.ts b/dashboard/exports/captcha.d.ts deleted file mode 100644 index 8116f2ba7..000000000 --- a/dashboard/exports/captcha.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/captcha/captcha'; \ No newline at end of file diff --git a/dashboard/exports/captcha.js b/dashboard/exports/captcha.js deleted file mode 100644 index 5ad37eb5f..000000000 --- a/dashboard/exports/captcha.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/captcha/captcha")); \ No newline at end of file diff --git a/dashboard/exports/card.d.ts b/dashboard/exports/card.d.ts deleted file mode 100644 index c4e0d1f51..000000000 --- a/dashboard/exports/card.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/card/card'; \ No newline at end of file diff --git a/dashboard/exports/card.js b/dashboard/exports/card.js deleted file mode 100644 index fe72ed2f9..000000000 --- a/dashboard/exports/card.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/card/card")); \ No newline at end of file diff --git a/dashboard/exports/carousel.d.ts b/dashboard/exports/carousel.d.ts deleted file mode 100644 index 2fdb7c0f7..000000000 --- a/dashboard/exports/carousel.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/carousel/carousel'; \ No newline at end of file diff --git a/dashboard/exports/carousel.js b/dashboard/exports/carousel.js deleted file mode 100644 index 7a093b101..000000000 --- a/dashboard/exports/carousel.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/carousel/carousel")); \ No newline at end of file diff --git a/dashboard/exports/chart.d.ts b/dashboard/exports/chart.d.ts deleted file mode 100644 index 32e069313..000000000 --- a/dashboard/exports/chart.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/chart/chart'; \ No newline at end of file diff --git a/dashboard/exports/chart.js b/dashboard/exports/chart.js deleted file mode 100644 index 5a822b266..000000000 --- a/dashboard/exports/chart.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/chart/chart")); \ No newline at end of file diff --git a/dashboard/exports/checkbox.d.ts b/dashboard/exports/checkbox.d.ts deleted file mode 100644 index 6e455b294..000000000 --- a/dashboard/exports/checkbox.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/checkbox/checkbox'; \ No newline at end of file diff --git a/dashboard/exports/checkbox.js b/dashboard/exports/checkbox.js deleted file mode 100644 index 81c5fd123..000000000 --- a/dashboard/exports/checkbox.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/checkbox/checkbox")); \ No newline at end of file diff --git a/dashboard/exports/chips.d.ts b/dashboard/exports/chips.d.ts deleted file mode 100644 index 8f55793e4..000000000 --- a/dashboard/exports/chips.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/chips/chips'; \ No newline at end of file diff --git a/dashboard/exports/chips.js b/dashboard/exports/chips.js deleted file mode 100644 index 436f3913c..000000000 --- a/dashboard/exports/chips.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/chips/chips")); \ No newline at end of file diff --git a/dashboard/exports/codehighlighter.d.ts b/dashboard/exports/codehighlighter.d.ts deleted file mode 100644 index c8d5f58d9..000000000 --- a/dashboard/exports/codehighlighter.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/codehighlighter/codehighlighter'; \ No newline at end of file diff --git a/dashboard/exports/codehighlighter.js b/dashboard/exports/codehighlighter.js deleted file mode 100644 index d137e15ec..000000000 --- a/dashboard/exports/codehighlighter.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/codehighlighter/codehighlighter")); \ No newline at end of file diff --git a/dashboard/exports/colorpicker.d.ts b/dashboard/exports/colorpicker.d.ts deleted file mode 100644 index 552c7d866..000000000 --- a/dashboard/exports/colorpicker.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/colorpicker/colorpicker'; \ No newline at end of file diff --git a/dashboard/exports/colorpicker.js b/dashboard/exports/colorpicker.js deleted file mode 100644 index 2dde45ecf..000000000 --- a/dashboard/exports/colorpicker.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/colorpicker/colorpicker")); \ No newline at end of file diff --git a/dashboard/exports/confirmdialog.d.ts b/dashboard/exports/confirmdialog.d.ts deleted file mode 100644 index 23e6bfcc6..000000000 --- a/dashboard/exports/confirmdialog.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/confirmdialog/confirmdialog'; \ No newline at end of file diff --git a/dashboard/exports/confirmdialog.js b/dashboard/exports/confirmdialog.js deleted file mode 100644 index 02cf7970d..000000000 --- a/dashboard/exports/confirmdialog.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/confirmdialog/confirmdialog")); \ No newline at end of file diff --git a/dashboard/exports/contextmenu.d.ts b/dashboard/exports/contextmenu.d.ts deleted file mode 100644 index 6f6f7add3..000000000 --- a/dashboard/exports/contextmenu.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/contextmenu/contextmenu'; \ No newline at end of file diff --git a/dashboard/exports/contextmenu.js b/dashboard/exports/contextmenu.js deleted file mode 100644 index e2eaf2350..000000000 --- a/dashboard/exports/contextmenu.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/contextmenu/contextmenu")); \ No newline at end of file diff --git a/dashboard/exports/datagrid.d.ts b/dashboard/exports/datagrid.d.ts deleted file mode 100644 index ccbe60863..000000000 --- a/dashboard/exports/datagrid.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/datagrid/datagrid'; \ No newline at end of file diff --git a/dashboard/exports/datagrid.js b/dashboard/exports/datagrid.js deleted file mode 100644 index 012a164ee..000000000 --- a/dashboard/exports/datagrid.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/datagrid/datagrid")); \ No newline at end of file diff --git a/dashboard/exports/datalist.d.ts b/dashboard/exports/datalist.d.ts deleted file mode 100644 index 1a2433b09..000000000 --- a/dashboard/exports/datalist.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/datalist/datalist'; \ No newline at end of file diff --git a/dashboard/exports/datalist.js b/dashboard/exports/datalist.js deleted file mode 100644 index 2e41aaa52..000000000 --- a/dashboard/exports/datalist.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/datalist/datalist")); \ No newline at end of file diff --git a/dashboard/exports/datascroller.d.ts b/dashboard/exports/datascroller.d.ts deleted file mode 100644 index a2ac4baad..000000000 --- a/dashboard/exports/datascroller.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/datascroller/datascroller'; \ No newline at end of file diff --git a/dashboard/exports/datascroller.js b/dashboard/exports/datascroller.js deleted file mode 100644 index 4b5f82c5f..000000000 --- a/dashboard/exports/datascroller.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/datascroller/datascroller")); \ No newline at end of file diff --git a/dashboard/exports/datatable.d.ts b/dashboard/exports/datatable.d.ts deleted file mode 100644 index cc9a4d1e2..000000000 --- a/dashboard/exports/datatable.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/datatable/datatable'; \ No newline at end of file diff --git a/dashboard/exports/datatable.js b/dashboard/exports/datatable.js deleted file mode 100644 index bab7d0f3e..000000000 --- a/dashboard/exports/datatable.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/datatable/datatable")); \ No newline at end of file diff --git a/dashboard/exports/dataview.d.ts b/dashboard/exports/dataview.d.ts deleted file mode 100644 index 595fa964e..000000000 --- a/dashboard/exports/dataview.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/dataview/dataview'; \ No newline at end of file diff --git a/dashboard/exports/dataview.js b/dashboard/exports/dataview.js deleted file mode 100644 index ed0c29d23..000000000 --- a/dashboard/exports/dataview.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/dataview/dataview")); \ No newline at end of file diff --git a/dashboard/exports/defer.d.ts b/dashboard/exports/defer.d.ts deleted file mode 100644 index 295dc29e1..000000000 --- a/dashboard/exports/defer.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/defer/defer'; \ No newline at end of file diff --git a/dashboard/exports/defer.js b/dashboard/exports/defer.js deleted file mode 100644 index 587cd4a05..000000000 --- a/dashboard/exports/defer.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/defer/defer")); \ No newline at end of file diff --git a/dashboard/exports/dialog.d.ts b/dashboard/exports/dialog.d.ts deleted file mode 100644 index 319213f8a..000000000 --- a/dashboard/exports/dialog.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/dialog/dialog'; \ No newline at end of file diff --git a/dashboard/exports/dialog.js b/dashboard/exports/dialog.js deleted file mode 100644 index c618248a6..000000000 --- a/dashboard/exports/dialog.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/dialog/dialog")); \ No newline at end of file diff --git a/dashboard/exports/dragdrop.d.ts b/dashboard/exports/dragdrop.d.ts deleted file mode 100644 index 42002ad67..000000000 --- a/dashboard/exports/dragdrop.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/dragdrop/dragdrop'; \ No newline at end of file diff --git a/dashboard/exports/dragdrop.js b/dashboard/exports/dragdrop.js deleted file mode 100644 index 6cf00b128..000000000 --- a/dashboard/exports/dragdrop.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/dragdrop/dragdrop")); \ No newline at end of file diff --git a/dashboard/exports/dropdown.d.ts b/dashboard/exports/dropdown.d.ts deleted file mode 100644 index 59a9b3a7f..000000000 --- a/dashboard/exports/dropdown.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/dropdown/dropdown'; \ No newline at end of file diff --git a/dashboard/exports/dropdown.js b/dashboard/exports/dropdown.js deleted file mode 100644 index c9df1e3fe..000000000 --- a/dashboard/exports/dropdown.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/dropdown/dropdown")); \ No newline at end of file diff --git a/dashboard/exports/editor.d.ts b/dashboard/exports/editor.d.ts deleted file mode 100644 index 8a147719b..000000000 --- a/dashboard/exports/editor.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/editor/editor'; \ No newline at end of file diff --git a/dashboard/exports/editor.js b/dashboard/exports/editor.js deleted file mode 100644 index ee153ec23..000000000 --- a/dashboard/exports/editor.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/editor/editor")); \ No newline at end of file diff --git a/dashboard/exports/fieldset.d.ts b/dashboard/exports/fieldset.d.ts deleted file mode 100644 index c7e44238a..000000000 --- a/dashboard/exports/fieldset.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/fieldset/fieldset'; \ No newline at end of file diff --git a/dashboard/exports/fieldset.js b/dashboard/exports/fieldset.js deleted file mode 100644 index be4397a07..000000000 --- a/dashboard/exports/fieldset.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/fieldset/fieldset")); \ No newline at end of file diff --git a/dashboard/exports/fileupload.d.ts b/dashboard/exports/fileupload.d.ts deleted file mode 100644 index 2c5b61d27..000000000 --- a/dashboard/exports/fileupload.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/fileupload/fileupload'; \ No newline at end of file diff --git a/dashboard/exports/fileupload.js b/dashboard/exports/fileupload.js deleted file mode 100644 index f6d989a36..000000000 --- a/dashboard/exports/fileupload.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/fileupload/fileupload")); \ No newline at end of file diff --git a/dashboard/exports/galleria.d.ts b/dashboard/exports/galleria.d.ts deleted file mode 100644 index 5355b48d8..000000000 --- a/dashboard/exports/galleria.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/galleria/galleria'; \ No newline at end of file diff --git a/dashboard/exports/galleria.js b/dashboard/exports/galleria.js deleted file mode 100644 index 0dbf04949..000000000 --- a/dashboard/exports/galleria.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/galleria/galleria")); \ No newline at end of file diff --git a/dashboard/exports/gmap.d.ts b/dashboard/exports/gmap.d.ts deleted file mode 100644 index 11cba6531..000000000 --- a/dashboard/exports/gmap.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/gmap/gmap'; \ No newline at end of file diff --git a/dashboard/exports/gmap.js b/dashboard/exports/gmap.js deleted file mode 100644 index b89a2c90e..000000000 --- a/dashboard/exports/gmap.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/gmap/gmap")); \ No newline at end of file diff --git a/dashboard/exports/growl.d.ts b/dashboard/exports/growl.d.ts deleted file mode 100644 index 0892d8792..000000000 --- a/dashboard/exports/growl.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/growl/growl'; \ No newline at end of file diff --git a/dashboard/exports/growl.js b/dashboard/exports/growl.js deleted file mode 100644 index dca7b5e94..000000000 --- a/dashboard/exports/growl.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/growl/growl")); \ No newline at end of file diff --git a/dashboard/exports/inplace.d.ts b/dashboard/exports/inplace.d.ts deleted file mode 100644 index 1b1b4c02a..000000000 --- a/dashboard/exports/inplace.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/inplace/inplace'; \ No newline at end of file diff --git a/dashboard/exports/inplace.js b/dashboard/exports/inplace.js deleted file mode 100644 index c5c6847e5..000000000 --- a/dashboard/exports/inplace.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/inplace/inplace")); \ No newline at end of file diff --git a/dashboard/exports/inputmask.d.ts b/dashboard/exports/inputmask.d.ts deleted file mode 100644 index 05a587e78..000000000 --- a/dashboard/exports/inputmask.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/inputmask/inputmask'; \ No newline at end of file diff --git a/dashboard/exports/inputmask.js b/dashboard/exports/inputmask.js deleted file mode 100644 index 14864e4c1..000000000 --- a/dashboard/exports/inputmask.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/inputmask/inputmask")); \ No newline at end of file diff --git a/dashboard/exports/inputswitch.d.ts b/dashboard/exports/inputswitch.d.ts deleted file mode 100644 index 4ff45dfbb..000000000 --- a/dashboard/exports/inputswitch.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/inputswitch/inputswitch'; \ No newline at end of file diff --git a/dashboard/exports/inputswitch.js b/dashboard/exports/inputswitch.js deleted file mode 100644 index 61301252c..000000000 --- a/dashboard/exports/inputswitch.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/inputswitch/inputswitch")); \ No newline at end of file diff --git a/dashboard/exports/inputtext.d.ts b/dashboard/exports/inputtext.d.ts deleted file mode 100644 index 3359c9c70..000000000 --- a/dashboard/exports/inputtext.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/inputtext/inputtext'; \ No newline at end of file diff --git a/dashboard/exports/inputtext.js b/dashboard/exports/inputtext.js deleted file mode 100644 index 84752274d..000000000 --- a/dashboard/exports/inputtext.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/inputtext/inputtext")); \ No newline at end of file diff --git a/dashboard/exports/inputtextarea.d.ts b/dashboard/exports/inputtextarea.d.ts deleted file mode 100644 index 76331c7e0..000000000 --- a/dashboard/exports/inputtextarea.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/inputtextarea/inputtextarea'; \ No newline at end of file diff --git a/dashboard/exports/inputtextarea.js b/dashboard/exports/inputtextarea.js deleted file mode 100644 index 99ade804c..000000000 --- a/dashboard/exports/inputtextarea.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/inputtextarea/inputtextarea")); \ No newline at end of file diff --git a/dashboard/exports/keyfilter.d.ts b/dashboard/exports/keyfilter.d.ts deleted file mode 100644 index c45db1f27..000000000 --- a/dashboard/exports/keyfilter.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/keyfilter/keyfilter'; \ No newline at end of file diff --git a/dashboard/exports/keyfilter.js b/dashboard/exports/keyfilter.js deleted file mode 100644 index f974d6867..000000000 --- a/dashboard/exports/keyfilter.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/keyfilter/keyfilter")); \ No newline at end of file diff --git a/dashboard/exports/lightbox.d.ts b/dashboard/exports/lightbox.d.ts deleted file mode 100644 index 4fecd3bba..000000000 --- a/dashboard/exports/lightbox.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/lightbox/lightbox'; \ No newline at end of file diff --git a/dashboard/exports/lightbox.js b/dashboard/exports/lightbox.js deleted file mode 100644 index c81b75360..000000000 --- a/dashboard/exports/lightbox.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/lightbox/lightbox")); \ No newline at end of file diff --git a/dashboard/exports/listbox.d.ts b/dashboard/exports/listbox.d.ts deleted file mode 100644 index b7519c1d2..000000000 --- a/dashboard/exports/listbox.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/listbox/listbox'; \ No newline at end of file diff --git a/dashboard/exports/listbox.js b/dashboard/exports/listbox.js deleted file mode 100644 index de5ff0317..000000000 --- a/dashboard/exports/listbox.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/listbox/listbox")); \ No newline at end of file diff --git a/dashboard/exports/megamenu.d.ts b/dashboard/exports/megamenu.d.ts deleted file mode 100644 index 56b7dc67c..000000000 --- a/dashboard/exports/megamenu.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/megamenu/megamenu'; \ No newline at end of file diff --git a/dashboard/exports/megamenu.js b/dashboard/exports/megamenu.js deleted file mode 100644 index 9c93b4cee..000000000 --- a/dashboard/exports/megamenu.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/megamenu/megamenu")); \ No newline at end of file diff --git a/dashboard/exports/menu.d.ts b/dashboard/exports/menu.d.ts deleted file mode 100644 index 2098c7a80..000000000 --- a/dashboard/exports/menu.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/menu/menu'; \ No newline at end of file diff --git a/dashboard/exports/menu.js b/dashboard/exports/menu.js deleted file mode 100644 index ccb487dca..000000000 --- a/dashboard/exports/menu.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/menu/menu")); \ No newline at end of file diff --git a/dashboard/exports/menubar.d.ts b/dashboard/exports/menubar.d.ts deleted file mode 100644 index c841483f2..000000000 --- a/dashboard/exports/menubar.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/menubar/menubar'; \ No newline at end of file diff --git a/dashboard/exports/menubar.js b/dashboard/exports/menubar.js deleted file mode 100644 index 6fb64bb2c..000000000 --- a/dashboard/exports/menubar.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/menubar/menubar")); \ No newline at end of file diff --git a/dashboard/exports/message.d.ts b/dashboard/exports/message.d.ts deleted file mode 100644 index 530a8bc60..000000000 --- a/dashboard/exports/message.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/message/message'; \ No newline at end of file diff --git a/dashboard/exports/message.js b/dashboard/exports/message.js deleted file mode 100644 index cfdc590ea..000000000 --- a/dashboard/exports/message.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/message/message")); \ No newline at end of file diff --git a/dashboard/exports/messages.d.ts b/dashboard/exports/messages.d.ts deleted file mode 100644 index 4c034ca49..000000000 --- a/dashboard/exports/messages.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/messages/messages'; \ No newline at end of file diff --git a/dashboard/exports/messages.js b/dashboard/exports/messages.js deleted file mode 100644 index e7cdbf25f..000000000 --- a/dashboard/exports/messages.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/messages/messages")); \ No newline at end of file diff --git a/dashboard/exports/multiselect.d.ts b/dashboard/exports/multiselect.d.ts deleted file mode 100644 index 7bda86c6b..000000000 --- a/dashboard/exports/multiselect.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/multiselect/multiselect'; \ No newline at end of file diff --git a/dashboard/exports/multiselect.js b/dashboard/exports/multiselect.js deleted file mode 100644 index c0ad550f3..000000000 --- a/dashboard/exports/multiselect.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/multiselect/multiselect")); \ No newline at end of file diff --git a/dashboard/exports/orderlist.d.ts b/dashboard/exports/orderlist.d.ts deleted file mode 100644 index 90edacb80..000000000 --- a/dashboard/exports/orderlist.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/orderlist/orderlist'; \ No newline at end of file diff --git a/dashboard/exports/orderlist.js b/dashboard/exports/orderlist.js deleted file mode 100644 index dc34b4daf..000000000 --- a/dashboard/exports/orderlist.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/orderlist/orderlist")); \ No newline at end of file diff --git a/dashboard/exports/organizationchart.d.ts b/dashboard/exports/organizationchart.d.ts deleted file mode 100644 index 6ea484fbd..000000000 --- a/dashboard/exports/organizationchart.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/organizationchart/organizationchart'; \ No newline at end of file diff --git a/dashboard/exports/organizationchart.js b/dashboard/exports/organizationchart.js deleted file mode 100644 index 707856b17..000000000 --- a/dashboard/exports/organizationchart.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/organizationchart/organizationchart")); \ No newline at end of file diff --git a/dashboard/exports/overlaypanel.d.ts b/dashboard/exports/overlaypanel.d.ts deleted file mode 100644 index b024ecb06..000000000 --- a/dashboard/exports/overlaypanel.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/overlaypanel/overlaypanel'; \ No newline at end of file diff --git a/dashboard/exports/overlaypanel.js b/dashboard/exports/overlaypanel.js deleted file mode 100644 index 9270ed15b..000000000 --- a/dashboard/exports/overlaypanel.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/overlaypanel/overlaypanel")); \ No newline at end of file diff --git a/dashboard/exports/paginator.d.ts b/dashboard/exports/paginator.d.ts deleted file mode 100644 index 786177c39..000000000 --- a/dashboard/exports/paginator.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/paginator/paginator'; \ No newline at end of file diff --git a/dashboard/exports/paginator.js b/dashboard/exports/paginator.js deleted file mode 100644 index f81ca12ae..000000000 --- a/dashboard/exports/paginator.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/paginator/paginator")); \ No newline at end of file diff --git a/dashboard/exports/panel.d.ts b/dashboard/exports/panel.d.ts deleted file mode 100644 index 2d97c4f7a..000000000 --- a/dashboard/exports/panel.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/panel/panel'; \ No newline at end of file diff --git a/dashboard/exports/panel.js b/dashboard/exports/panel.js deleted file mode 100644 index a0ea4b6cb..000000000 --- a/dashboard/exports/panel.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/panel/panel")); \ No newline at end of file diff --git a/dashboard/exports/panelmenu.d.ts b/dashboard/exports/panelmenu.d.ts deleted file mode 100644 index 2fda895ee..000000000 --- a/dashboard/exports/panelmenu.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/panelmenu/panelmenu'; \ No newline at end of file diff --git a/dashboard/exports/panelmenu.js b/dashboard/exports/panelmenu.js deleted file mode 100644 index 4f11922e8..000000000 --- a/dashboard/exports/panelmenu.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/panelmenu/panelmenu")); \ No newline at end of file diff --git a/dashboard/exports/password.d.ts b/dashboard/exports/password.d.ts deleted file mode 100644 index 14befa5e3..000000000 --- a/dashboard/exports/password.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/password/password'; \ No newline at end of file diff --git a/dashboard/exports/password.js b/dashboard/exports/password.js deleted file mode 100644 index f6f08f053..000000000 --- a/dashboard/exports/password.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/password/password")); \ No newline at end of file diff --git a/dashboard/exports/picklist.d.ts b/dashboard/exports/picklist.d.ts deleted file mode 100644 index 00d26f555..000000000 --- a/dashboard/exports/picklist.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/picklist/picklist'; \ No newline at end of file diff --git a/dashboard/exports/picklist.js b/dashboard/exports/picklist.js deleted file mode 100644 index ccb03f180..000000000 --- a/dashboard/exports/picklist.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/picklist/picklist")); \ No newline at end of file diff --git a/dashboard/exports/progressbar.d.ts b/dashboard/exports/progressbar.d.ts deleted file mode 100644 index ec5a777e3..000000000 --- a/dashboard/exports/progressbar.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/progressbar/progressbar'; \ No newline at end of file diff --git a/dashboard/exports/progressbar.js b/dashboard/exports/progressbar.js deleted file mode 100644 index e21a9299f..000000000 --- a/dashboard/exports/progressbar.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/progressbar/progressbar")); \ No newline at end of file diff --git a/dashboard/exports/progressspinner.d.ts b/dashboard/exports/progressspinner.d.ts deleted file mode 100644 index 857379f33..000000000 --- a/dashboard/exports/progressspinner.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/progressspinner/progressspinner'; \ No newline at end of file diff --git a/dashboard/exports/progressspinner.js b/dashboard/exports/progressspinner.js deleted file mode 100644 index 523742c94..000000000 --- a/dashboard/exports/progressspinner.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/progressspinner/progressspinner")); \ No newline at end of file diff --git a/dashboard/exports/radiobutton.d.ts b/dashboard/exports/radiobutton.d.ts deleted file mode 100644 index 8969af7db..000000000 --- a/dashboard/exports/radiobutton.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/radiobutton/radiobutton'; \ No newline at end of file diff --git a/dashboard/exports/radiobutton.js b/dashboard/exports/radiobutton.js deleted file mode 100644 index f99063786..000000000 --- a/dashboard/exports/radiobutton.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/radiobutton/radiobutton")); \ No newline at end of file diff --git a/dashboard/exports/rating.d.ts b/dashboard/exports/rating.d.ts deleted file mode 100644 index 8f352d26b..000000000 --- a/dashboard/exports/rating.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/rating/rating'; \ No newline at end of file diff --git a/dashboard/exports/rating.js b/dashboard/exports/rating.js deleted file mode 100644 index 89a99275f..000000000 --- a/dashboard/exports/rating.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/rating/rating")); \ No newline at end of file diff --git a/dashboard/exports/schedule.d.ts b/dashboard/exports/schedule.d.ts deleted file mode 100644 index 6af565faf..000000000 --- a/dashboard/exports/schedule.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/schedule/schedule'; \ No newline at end of file diff --git a/dashboard/exports/schedule.js b/dashboard/exports/schedule.js deleted file mode 100644 index eaadb03e9..000000000 --- a/dashboard/exports/schedule.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/schedule/schedule")); \ No newline at end of file diff --git a/dashboard/exports/scrollpanel.d.ts b/dashboard/exports/scrollpanel.d.ts deleted file mode 100644 index edb73e68a..000000000 --- a/dashboard/exports/scrollpanel.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/scrollpanel/scrollpanel'; \ No newline at end of file diff --git a/dashboard/exports/scrollpanel.js b/dashboard/exports/scrollpanel.js deleted file mode 100644 index 41986a4b4..000000000 --- a/dashboard/exports/scrollpanel.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/scrollpanel/scrollpanel")); \ No newline at end of file diff --git a/dashboard/exports/selectbutton.d.ts b/dashboard/exports/selectbutton.d.ts deleted file mode 100644 index 2f3e809af..000000000 --- a/dashboard/exports/selectbutton.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/selectbutton/selectbutton'; \ No newline at end of file diff --git a/dashboard/exports/selectbutton.js b/dashboard/exports/selectbutton.js deleted file mode 100644 index 30524f893..000000000 --- a/dashboard/exports/selectbutton.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/selectbutton/selectbutton")); \ No newline at end of file diff --git a/dashboard/exports/shared.d.ts b/dashboard/exports/shared.d.ts deleted file mode 100644 index 80786466f..000000000 --- a/dashboard/exports/shared.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/common/shared'; \ No newline at end of file diff --git a/dashboard/exports/shared.js b/dashboard/exports/shared.js deleted file mode 100644 index 4ae5ca2e6..000000000 --- a/dashboard/exports/shared.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/common/shared")); \ No newline at end of file diff --git a/dashboard/exports/sidebar.d.ts b/dashboard/exports/sidebar.d.ts deleted file mode 100644 index 28aa57888..000000000 --- a/dashboard/exports/sidebar.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/sidebar/sidebar'; \ No newline at end of file diff --git a/dashboard/exports/sidebar.js b/dashboard/exports/sidebar.js deleted file mode 100644 index 65e1457d8..000000000 --- a/dashboard/exports/sidebar.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/sidebar/sidebar")); \ No newline at end of file diff --git a/dashboard/exports/slidemenu.d.ts b/dashboard/exports/slidemenu.d.ts deleted file mode 100644 index 8337e345a..000000000 --- a/dashboard/exports/slidemenu.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/slidemenu/slidemenu'; \ No newline at end of file diff --git a/dashboard/exports/slidemenu.js b/dashboard/exports/slidemenu.js deleted file mode 100644 index 1640a183a..000000000 --- a/dashboard/exports/slidemenu.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/slidemenu/slidemenu")); \ No newline at end of file diff --git a/dashboard/exports/slider.d.ts b/dashboard/exports/slider.d.ts deleted file mode 100644 index daa647ed1..000000000 --- a/dashboard/exports/slider.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/slider/slider'; \ No newline at end of file diff --git a/dashboard/exports/slider.js b/dashboard/exports/slider.js deleted file mode 100644 index 76d0b2629..000000000 --- a/dashboard/exports/slider.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/slider/slider")); \ No newline at end of file diff --git a/dashboard/exports/spinner.d.ts b/dashboard/exports/spinner.d.ts deleted file mode 100644 index ef0c15147..000000000 --- a/dashboard/exports/spinner.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/spinner/spinner'; \ No newline at end of file diff --git a/dashboard/exports/spinner.js b/dashboard/exports/spinner.js deleted file mode 100644 index 5feafe33b..000000000 --- a/dashboard/exports/spinner.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/spinner/spinner")); \ No newline at end of file diff --git a/dashboard/exports/splitbutton.d.ts b/dashboard/exports/splitbutton.d.ts deleted file mode 100644 index 1c84d1712..000000000 --- a/dashboard/exports/splitbutton.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/splitbutton/splitbutton'; \ No newline at end of file diff --git a/dashboard/exports/splitbutton.js b/dashboard/exports/splitbutton.js deleted file mode 100644 index 343d9cc50..000000000 --- a/dashboard/exports/splitbutton.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/splitbutton/splitbutton")); \ No newline at end of file diff --git a/dashboard/exports/steps.d.ts b/dashboard/exports/steps.d.ts deleted file mode 100644 index 2f4735fa7..000000000 --- a/dashboard/exports/steps.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/steps/steps'; \ No newline at end of file diff --git a/dashboard/exports/steps.js b/dashboard/exports/steps.js deleted file mode 100644 index 7119f35d2..000000000 --- a/dashboard/exports/steps.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/steps/steps")); \ No newline at end of file diff --git a/dashboard/exports/table.d.ts b/dashboard/exports/table.d.ts deleted file mode 100644 index c171708f7..000000000 --- a/dashboard/exports/table.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/table/table'; \ No newline at end of file diff --git a/dashboard/exports/table.js b/dashboard/exports/table.js deleted file mode 100644 index cbd8e99ca..000000000 --- a/dashboard/exports/table.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/table/table")); \ No newline at end of file diff --git a/dashboard/exports/tabmenu.d.ts b/dashboard/exports/tabmenu.d.ts deleted file mode 100644 index 3c519f064..000000000 --- a/dashboard/exports/tabmenu.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/tabmenu/tabmenu'; \ No newline at end of file diff --git a/dashboard/exports/tabmenu.js b/dashboard/exports/tabmenu.js deleted file mode 100644 index a76ba2be9..000000000 --- a/dashboard/exports/tabmenu.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/tabmenu/tabmenu")); \ No newline at end of file diff --git a/dashboard/exports/tabview.d.ts b/dashboard/exports/tabview.d.ts deleted file mode 100644 index 7e74bf4f8..000000000 --- a/dashboard/exports/tabview.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/tabview/tabview'; \ No newline at end of file diff --git a/dashboard/exports/tabview.js b/dashboard/exports/tabview.js deleted file mode 100644 index ce6daf5df..000000000 --- a/dashboard/exports/tabview.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/tabview/tabview")); \ No newline at end of file diff --git a/dashboard/exports/terminal.d.ts b/dashboard/exports/terminal.d.ts deleted file mode 100644 index b597ebde8..000000000 --- a/dashboard/exports/terminal.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/terminal/terminal'; \ No newline at end of file diff --git a/dashboard/exports/terminal.js b/dashboard/exports/terminal.js deleted file mode 100644 index 1f5049d3d..000000000 --- a/dashboard/exports/terminal.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/terminal/terminal")); \ No newline at end of file diff --git a/dashboard/exports/tieredmenu.d.ts b/dashboard/exports/tieredmenu.d.ts deleted file mode 100644 index 8781fdda4..000000000 --- a/dashboard/exports/tieredmenu.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/tieredmenu/tieredmenu'; \ No newline at end of file diff --git a/dashboard/exports/tieredmenu.js b/dashboard/exports/tieredmenu.js deleted file mode 100644 index c2920695b..000000000 --- a/dashboard/exports/tieredmenu.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/tieredmenu/tieredmenu")); \ No newline at end of file diff --git a/dashboard/exports/togglebutton.d.ts b/dashboard/exports/togglebutton.d.ts deleted file mode 100644 index eec3875eb..000000000 --- a/dashboard/exports/togglebutton.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/togglebutton/togglebutton'; \ No newline at end of file diff --git a/dashboard/exports/togglebutton.js b/dashboard/exports/togglebutton.js deleted file mode 100644 index 78f25a189..000000000 --- a/dashboard/exports/togglebutton.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/togglebutton/togglebutton")); \ No newline at end of file diff --git a/dashboard/exports/toolbar.d.ts b/dashboard/exports/toolbar.d.ts deleted file mode 100644 index 35b9790fd..000000000 --- a/dashboard/exports/toolbar.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/toolbar/toolbar'; \ No newline at end of file diff --git a/dashboard/exports/toolbar.js b/dashboard/exports/toolbar.js deleted file mode 100644 index 88b5112fa..000000000 --- a/dashboard/exports/toolbar.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/toolbar/toolbar")); \ No newline at end of file diff --git a/dashboard/exports/tooltip.d.ts b/dashboard/exports/tooltip.d.ts deleted file mode 100644 index b188f0d2d..000000000 --- a/dashboard/exports/tooltip.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/tooltip/tooltip'; \ No newline at end of file diff --git a/dashboard/exports/tooltip.js b/dashboard/exports/tooltip.js deleted file mode 100644 index 270701079..000000000 --- a/dashboard/exports/tooltip.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/tooltip/tooltip")); \ No newline at end of file diff --git a/dashboard/exports/tree.d.ts b/dashboard/exports/tree.d.ts deleted file mode 100644 index c6c79854d..000000000 --- a/dashboard/exports/tree.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/tree/tree'; \ No newline at end of file diff --git a/dashboard/exports/tree.js b/dashboard/exports/tree.js deleted file mode 100644 index 2f111e9ab..000000000 --- a/dashboard/exports/tree.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/tree/tree")); \ No newline at end of file diff --git a/dashboard/exports/treetable.d.ts b/dashboard/exports/treetable.d.ts deleted file mode 100644 index 3e3ce3e46..000000000 --- a/dashboard/exports/treetable.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/treetable/treetable'; \ No newline at end of file diff --git a/dashboard/exports/treetable.js b/dashboard/exports/treetable.js deleted file mode 100644 index c1eb56bba..000000000 --- a/dashboard/exports/treetable.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/treetable/treetable")); \ No newline at end of file diff --git a/dashboard/exports/tristatecheckbox.d.ts b/dashboard/exports/tristatecheckbox.d.ts deleted file mode 100644 index 70e6e5065..000000000 --- a/dashboard/exports/tristatecheckbox.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './components/tristatecheckbox/tristatecheckbox'; \ No newline at end of file diff --git a/dashboard/exports/tristatecheckbox.js b/dashboard/exports/tristatecheckbox.js deleted file mode 100644 index 68ec104a4..000000000 --- a/dashboard/exports/tristatecheckbox.js +++ /dev/null @@ -1,7 +0,0 @@ -/* Shorthand */ -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -__export(require("./components/tristatecheckbox/tristatecheckbox")); \ No newline at end of file diff --git a/dashboard/gulpfile.js b/dashboard/gulpfile.js deleted file mode 100644 index a2eb160dd..000000000 --- a/dashboard/gulpfile.js +++ /dev/null @@ -1,62 +0,0 @@ -'use strict'; - -var gulp = require('gulp'), - concat = require('gulp-concat'), - uglifycss = require('gulp-uglifycss'), - rename = require('gulp-rename'), - del = require('del'), - flatten = require('gulp-flatten'); - -gulp.task('build-css', function() { - gulp.src([ - 'src/app/components/common/common.scss', - 'src/app/components/**/*.css' - ]) - .pipe(concat('primeng.css')) - .pipe(gulp.dest('resources')); -}); - -gulp.task('build-css-prod', function() { - gulp.src([ - 'src/app/components/common/common.scss', - 'src/app/components/**/*.css' - ]) - .pipe(concat('primeng.css')) - .pipe(gulp.dest('resources')) - .pipe(uglifycss({"uglyComments": true})) - .pipe(rename('primeng.min.css')) - .pipe(gulp.dest('resources')); -}); - -gulp.task('copy-component-css', function () { - gulp.src([ - 'src/app/components/**/*.css' - ]) - .pipe(gulp.dest('resources/components')); -}); - -gulp.task('images', function() { - return gulp.src(['src/app/components/**/images/*.png', 'src/app/components/**/images/*.gif']) - .pipe(flatten()) - .pipe(gulp.dest('resources/images')); -}); - -gulp.task('themes', function() { - return gulp.src(['src/assets/components/themes/**/*']) - .pipe(gulp.dest('resources/themes')); -}); - -gulp.task('build-exports', function() { - return gulp.src(['exports/*.js','exports/*.d.ts']) - .pipe(gulp.dest('./')); -}); - -//Cleaning previous gulp tasks from project -gulp.task('clean', function() { - del(['resources']); -}); - -//Building project with run sequence -gulp.task('build-assets', ['clean','copy-component-css', 'build-css-prod', 'images', 'themes']); - - \ No newline at end of file diff --git a/dashboard/image_builder.sh b/dashboard/image_builder.sh deleted file mode 100644 index d7b2b9acb..000000000 --- a/dashboard/image_builder.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2018 Huawei Technologies Co., Ltd. All Rights Reserved. -# -# Licensed 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. - -if [[ "X$1" == "X--rebuild" ]]; then - npm rebuild node-sass --force -fi - -npm install --unsafe-perm -g @angular/cli@1.7.4 -npm install --unsafe-perm -ng build --prod - -cp -R ./dist/* /var/www/html/ - -cat > /etc/nginx/sites-available/default < - - - - - -
-
- - - - - -
- -
-
- -
-
-
\ No newline at end of file diff --git a/dashboard/src/app/app.component.ts b/dashboard/src/app/app.component.ts deleted file mode 100644 index 42a8b561b..000000000 --- a/dashboard/src/app/app.component.ts +++ /dev/null @@ -1,445 +0,0 @@ -import { Component, OnInit, ViewContainerRef, ViewChild, Directive, ElementRef, HostBinding, HostListener, AfterViewInit } from '@angular/core'; -import { Http } from '@angular/http'; -import { Router } from '@angular/router'; -import { I18NService, Consts, ParamStorService } from 'app/shared/api'; -// import { AppService } from 'app/app.service'; -import { I18nPluralPipe } from '@angular/common'; -import { MenuItem, SelectItem } from './components/common/api'; - -@Component({ - selector: 'app-root', - templateUrl: './app.component.html', - styleUrls: [] -}) -export class AppComponent implements OnInit, AfterViewInit{ - chromeBrowser: boolean = false; - - isLogin: boolean; - - hideLoginForm: boolean = false; - - linkUrl = ""; - - username: string; - - password: string; - - dropMenuItems: MenuItem[]; - - currentTenant: string=""; - - showLoginAnimation: boolean=false; - - showLogoutAnimation: boolean=false; - currentTime=new Date().getTime(); - lastTime=new Date().getTime(); - minExpireTime = 2 * 60 * 1000; - advanceRefreshTime = 1*60*1000; - defaultExpireTime = 10*60*1000; - interval:any; - intervalRefreshToken:any; - showErrorMsg:boolean=false; - errorMsg:string=""; - - tenantItems = []; - - menuItems = []; - - menuItems_tenant = [ - { - "title": "Home", - "description": "Resources statistics", - "routerLink": "/home" - }, - { - "title": "Volume", - "description": "Block storage resources", - "routerLink": "/block" - } - ] - - menuItems_admin = [ - { - "title": "Home", - "description": "Resources statistics", - "routerLink": "/home" - }, - { - "title": "Volume", - "description": "Block storage resources", - "routerLink": "/block" - }, - // { - // "title": "Multi-Cloud Service", - // "description": "5 replications, 1 migrations", - // "routerLink": "/cloud" - // }, - { - "title": "Profile", - "description": "Block profiles", - "routerLink": "/profile" - }, - { - "title": "Resource", - "description": "Regions, availability zones and storages", - "routerLink": "/resource" - }, - { - "title": "Identity", - "description": "Managing tenants and users", - "routerLink": "/identity" - } - ]; - - activeItem: any; - - private msgs: any = [{ severity: 'warn', summary: 'Warn Message', detail: 'There are unsaved changes'}]; - - constructor( - private el: ElementRef, - private viewContainerRef: ViewContainerRef, - private http: Http, - private router: Router, - private paramStor: ParamStorService, - public I18N: I18NService - ){} - - ngOnInit() { - let currentUserInfo = this.paramStor.CURRENT_USER(); - if(currentUserInfo != undefined && currentUserInfo != ""){ - this.hideLoginForm = true; - - let [username, userid, tenantname, tenantid] = [ - this.paramStor.CURRENT_USER().split("|")[0], - this.paramStor.CURRENT_USER().split("|")[1], - this.paramStor.CURRENT_TENANT().split("|")[0], - this.paramStor.CURRENT_TENANT().split("|")[1] ]; - this.AuthWithTokenScoped({'name': username, 'id': userid}); - }else{ - this.isLogin = false; - this.hideLoginForm = false; - } - } - checkTimeOut(){ - this.currentTime = new Date().getTime(); //update current time - let timeout = this.paramStor.TOKEN_PERIOD() ? this.paramStor.TOKEN_PERIOD() : this.defaultExpireTime; - if(this.currentTime - this.lastTime > timeout){ //check time out - this.logout(); - } - } - refreshLastTime(){ - this.lastTime = new Date().getTime(); - } - /** - * this function must be called after AuthWithTokenScoped succeed ,because it need username and password - */ - refreshToken(){ - let request: any = { auth: {} }; - request.auth = { - "identity": { - "methods": [ - "password" - ], - "password":{ - "user": { - "name": this.paramStor.CURRENT_USER().split("|")[0], - "domain": { - "name": "Default" - }, - "password": this.paramStor.PASSWORD() - } - } - } - } - - this.http.post("/v3/auth/tokens", request).subscribe((res)=>{ - let token_id = res.headers.get('x-subject-token'); - let projectName = this.paramStor.CURRENT_TENANT().split("|")[0]; - let req: any = { auth: {} }; - req.auth = { - "identity": { - "methods": [ - "token" - ], - "token": { - "id": token_id - } - }, - "scope": { - "project": { - "name": projectName, - "domain": { "id": "default" } - } - } - } - - this.http.post("/v3/auth/tokens", req).subscribe((r)=>{ - this.paramStor.AUTH_TOKEN( r.headers.get('x-subject-token') ); - }); - }, - error=>{ - console.log("Username or password incorrect.") - }); - } - ngAfterViewInit(){ - this.loginBgAnimation(); - } - - loginBgAnimation(){ - let obj =this.el.nativeElement.querySelector(".login-bg"); - if(obj){ - let obj_w = obj.clientWidth; - let obj_h = obj.clientHeight; - let dis = 50; - obj.addEventListener("mousemove", (e)=>{ - let MX = e.clientX; - let MY = e.clientY; - let offsetX = (obj_w - 2258)*0.5 + (obj_w-MX)*dis / obj_w; - let offsetY = (obj_h - 1363)*0.5 + (obj_h-MY)*dis / obj_h; - obj.style.backgroundPositionX = offsetX +"px"; - obj.style.backgroundPositionY = offsetY +"px"; - }) - } - } - - login() { - let request: any = { auth: {} }; - request.auth = { - "identity": { - "methods": [ - "password" - ], - "password":{ - "user": { - "name": this.username, - "domain": { - "name": "Default" - }, - "password": this.password - } - } - } - } - - this.http.post("/v3/auth/tokens", request).subscribe((res)=>{ - //set token period start - let token = res.json().token; - let expires_at = token.expires_at; - let issued_at = token.issued_at; - let tokenPeriod = Date.parse(expires_at) - Date.parse(issued_at); - if(tokenPeriod >= this.minExpireTime){ - this.paramStor.TOKEN_PERIOD(tokenPeriod); - } - //set token period end - this.paramStor.AUTH_TOKEN(res.headers.get('x-subject-token')); - this.paramStor.PASSWORD(this.password); - let user = res.json().token.user; - this.AuthWithTokenScoped(user); - this.showErrorMsg = false; - }, - error=>{ - switch(error.status){ - case 401: - this.errorMsg = this.I18N.keyID['sds_login_error_msg_401']; - break; - case 503: - this.errorMsg = this.I18N.keyID['sds_login_error_msg_503']; - break; - default: - this.errorMsg = this.I18N.keyID['sds_login_error_msg_default']; - } - this.showErrorMsg = true; - }); - } - - AuthWithTokenScoped(user, tenant?){ - if(this.interval){ - clearInterval(this.interval); - } - this.lastTime=new Date().getTime(); - this.interval = window.setInterval(()=>{ - this.checkTimeOut() - }, 10000); - // Get user owned tenants - let reqUser: any = { params:{} }; - this.http.get("/v3/users/"+ user.id +"/projects", reqUser).subscribe((objRES) => { - let projects = objRES.json().projects; - let defaultProject = user.name != 'admin' ? projects[0] : projects.filter((project) => { return project.name == 'admin'})[0]; - let project = tenant===undefined ? defaultProject : tenant; - - this.tenantItems = []; - projects.map(item => { - let tenantItemObj = {}; - tenantItemObj["label"] = item.name; - tenantItemObj["command"] = ()=>{ - let username = this.paramStor.CURRENT_USER().split("|")[0]; - let userid = this.paramStor.CURRENT_USER().split("|")[1]; - this.AuthWithTokenScoped({'name': username, 'id': userid}, item); - }; - this.tenantItems.push(tenantItemObj); - }) - - // Get token authentication with scoped - let token_id = this.paramStor.AUTH_TOKEN(); - let req: any = { auth: {} }; - req.auth = { - "identity": { - "methods": [ - "token" - ], - "token": { - "id": token_id - } - }, - "scope": { - "project": { - "name": project.name, - "domain": { "id": "default" } - } - } - } - - this.http.post("/v3/auth/tokens", req).subscribe((r)=>{ - this.paramStor.AUTH_TOKEN( r.headers.get('x-subject-token') ); - this.paramStor.CURRENT_TENANT(project.name + "|" + project.id); - this.paramStor.CURRENT_USER(user.name + "|"+ user.id); - - this.username = this.paramStor.CURRENT_USER().split("|")[0]; - this.currentTenant = this.paramStor.CURRENT_TENANT().split("|")[0]; - - if(this.username == "admin"){ - this.menuItems = this.menuItems_admin; - this.dropMenuItems = [ - { - label: "Switch Region", - items: [{ label: "default_region", command:()=>{} }] - }, - { - label: "Logout", - command:()=>{ this.logout() } - } - ]; - }else{ - this.menuItems = this.menuItems_tenant; - this.dropMenuItems = [ - { - label: "Switch Region", - items: [{ label: "default_region", command:()=>{} }] - }, - { - label: "Switch Tenant", - items: this.tenantItems - }, - { - label: "Logout", - command:()=>{ this.logout() } - } - ]; - } - - this.isLogin = true; - this.router.navigateByUrl("home"); - this.activeItem = this.menuItems[0]; - - // annimation for after login - this.showLoginAnimation = true; - setTimeout(() => { - this.showLoginAnimation = false; - this.hideLoginForm = true; - }, 500); - if(this.intervalRefreshToken){ - clearInterval(this.intervalRefreshToken); - } - let tokenPeriod = this.paramStor.TOKEN_PERIOD(); - let refreshTime = tokenPeriod ? (Number(tokenPeriod) - this.advanceRefreshTime) : this.defaultExpireTime; - this.intervalRefreshToken = window.setInterval(()=>{ - this.refreshToken() - },refreshTime); - }) - }, - error => { - this.logout(); - }) - } - - logout() { - this.paramStor.AUTH_TOKEN(""); - this.paramStor.CURRENT_USER(""); - this.paramStor.CURRENT_TENANT(""); - this.paramStor.PASSWORD(""); - this.paramStor.TOKEN_PERIOD(""); - if(this.interval){ - clearInterval(this.interval); - } - if(this.intervalRefreshToken){ - clearInterval(this.intervalRefreshToken); - } - // annimation for after logout - this.hideLoginForm = false; - this.showLogoutAnimation = true; - setTimeout(() => { - this.showLogoutAnimation = false; - this.username = ""; - this.password = ""; - this.isLogin = false; - }, 500); - - } - - onKeyDown(e) { - let keycode = window.event ? e.keyCode : e.which; - if(keycode == 13){ - this.login(); - } - } - - menuItemClick(event, item) { - this.activeItem = item; - } - - supportCurrentBrowser(){ - let ie, - firefox, - safari, - chrome, - cIE = 11, - cFirefox = 40, - cChrome = 40; - let ua = navigator.userAgent.toLowerCase(); - let isLinux = (ua.indexOf('linux') >= 0); - - if(this.isIE()) { - if(ua.indexOf('msie') >= 0) { - ie = this.getSys(ua.match(/msie ([\d]+)/)); - } else { - ie = this.getSys(ua.match(/trident.*rv:([\d]+)/)); - } - }else if(navigator.userAgent.indexOf("Firefox") > 0){ - firefox = this.getSys(ua.match(/firefox\/([\d]+)/)); - }else if(ua.indexOf("safari") != -1 && !(ua.indexOf("chrome") != -1)) { - safari = this.getSys(ua.match(/version\/([\d]+)/)); - }else if(ua.indexOf("chrome") != -1) { - chrome = this.getSys(ua.match(/chrome\/([\d]+)/)); - } - - if ((firefox) / 1 < cFirefox || (chrome) / 1 < cChrome || (ie) / 1 < cIE) { - return true; - } - - return false; - } - - isIE() { - return navigator.userAgent.toLowerCase().indexOf('trident') >= 0; - } - - getSys (browserVersionArr) { - if( !browserVersionArr) { - return 0; - } else if( browserVersionArr.length < 2) { - return 0; - } else { - return browserVersionArr[1]; - } - } -} diff --git a/dashboard/src/app/app.module.ts b/dashboard/src/app/app.module.ts deleted file mode 100644 index 058c62394..000000000 --- a/dashboard/src/app/app.module.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { BrowserModule } from '@angular/platform-browser'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { CommonModule } from '@angular/common'; -import { NgModule, APP_INITIALIZER } from '@angular/core'; -import { HttpModule } from "@angular/http"; -import { AppRoutingModule } from './app-routing.module'; -import { AppComponent } from './app.component'; -import { SharedModule } from './shared/shared.module'; -import { DropMenuModule, SelectButtonModule, ButtonModule, InputTextModule } from './components/common/api'; -// import { AppService } from './app.service'; -import { LocationStrategy, HashLocationStrategy } from '@angular/common'; - -import { MessagesModule } from './components/messages/messages'; - -@NgModule({ - declarations: [ - AppComponent - ], - imports: [ - BrowserModule, - CommonModule, - AppRoutingModule, - MessagesModule, - HttpModule, - BrowserAnimationsModule, - SharedModule.forRoot(), - DropMenuModule, - SelectButtonModule, - ButtonModule, - InputTextModule - ], - providers: [ - // AppService, - { provide: LocationStrategy, useClass: HashLocationStrategy } - ], - bootstrap: [AppComponent] -}) -export class AppModule { } \ No newline at end of file diff --git a/dashboard/src/app/app.service.ts b/dashboard/src/app/app.service.ts deleted file mode 100644 index 886b4f82e..000000000 --- a/dashboard/src/app/app.service.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Injectable, Output, EventEmitter } from '@angular/core'; -import { Http } from '@angular/http'; - -@Injectable() -export class AppService { - constructor(private http: Http){} - - @Output() onHeaderTitleChange = new EventEmitter(); - - changeHeaderTitle(){ - this.onHeaderTitleChange.emit(); - } - - logOut(){ - // return this.http.get("v1/portal/logout"); - } - -} \ No newline at end of file diff --git a/dashboard/src/app/business/block/block.component.ts b/dashboard/src/app/business/block/block.component.ts deleted file mode 100644 index ad96bc7c9..000000000 --- a/dashboard/src/app/business/block/block.component.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Router,ActivatedRoute } from '@angular/router'; -import { Component, OnInit, ViewContainerRef, ViewChild, Directive, ElementRef, HostBinding, HostListener } from '@angular/core'; -import { I18NService } from 'app/shared/api'; -import { AppService } from 'app/app.service'; -import { trigger, state, style, transition, animate} from '@angular/animations'; -import { I18nPluralPipe } from '@angular/common'; - -@Component({ - templateUrl: './block.html', - styleUrls: [], - animations: [ - trigger('overlayState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]), - - trigger('notificationTopbar', [ - state('hidden', style({ - height: '0', - opacity: 0 - })), - state('visible', style({ - height: '*', - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]) - ] -}) -export class BlockComponent implements OnInit{ - fromGroup:boolean=false; - constructor( - public I18N: I18NService, - private router: Router, - private ActivatedRoute:ActivatedRoute - ){} - - ngOnInit() { - this.ActivatedRoute.params.subscribe( - (params) => this.fromGroup = !!params.fromRoute - ); - } - -} diff --git a/dashboard/src/app/business/block/block.html b/dashboard/src/app/business/block/block.html deleted file mode 100644 index 95616263b..000000000 --- a/dashboard/src/app/business/block/block.html +++ /dev/null @@ -1,14 +0,0 @@ - - -
-

{{I18N.keyID['sds_block_volumes_descrip']}}

-
- -
- -
-

{{I18N.keyID['sds_block_volumesGroup_descrip']}}

-
- -
-
diff --git a/dashboard/src/app/business/block/block.module.ts b/dashboard/src/app/business/block/block.module.ts deleted file mode 100644 index 9a52e7f0f..000000000 --- a/dashboard/src/app/business/block/block.module.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { NgModule, APP_INITIALIZER } from '@angular/core'; -import { BlockComponent } from './block.component'; -import { RouterModule } from '@angular/router'; -import { TabViewModule, ButtonModule } from '../../components/common/api'; -import { VolumeListModule } from './volumeList.module'; -import { VolumeGroupModule } from './volumeGroup.module'; -import { CreateVolumeGroupComponent } from './create-volume-group/create-volume-group.component'; - -let routers = [{ - path: '', - component: BlockComponent -}] - -@NgModule({ - declarations: [ - BlockComponent, - CreateVolumeGroupComponent - ], - imports: [ - RouterModule.forChild(routers), - VolumeListModule, - VolumeGroupModule, - TabViewModule, - ButtonModule - ], - providers: [] -}) -export class BlockModule { } \ No newline at end of file diff --git a/dashboard/src/app/business/block/create-volume-group/create-volume-group.component.html b/dashboard/src/app/business/block/create-volume-group/create-volume-group.component.html deleted file mode 100644 index 86859275d..000000000 --- a/dashboard/src/app/business/block/create-volume-group/create-volume-group.component.html +++ /dev/null @@ -1,3 +0,0 @@ -

- create-volume-group works! -

diff --git a/dashboard/src/app/business/block/create-volume-group/create-volume-group.component.ts b/dashboard/src/app/business/block/create-volume-group/create-volume-group.component.ts deleted file mode 100644 index 0c714bf6f..000000000 --- a/dashboard/src/app/business/block/create-volume-group/create-volume-group.component.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Component, OnInit } from '@angular/core'; - -@Component({ - selector: 'app-create-volume-group', - templateUrl: './create-volume-group.component.html', - styleUrls: [ - - ] -}) -export class CreateVolumeGroupComponent implements OnInit { - - constructor() { } - - ngOnInit() { - } - -} diff --git a/dashboard/src/app/business/block/create-volume/create-volume.component.html b/dashboard/src/app/business/block/create-volume/create-volume.component.html deleted file mode 100644 index 784ac2f46..000000000 --- a/dashboard/src/app/business/block/create-volume/create-volume.component.html +++ /dev/null @@ -1,92 +0,0 @@ -
-

{{i18n.keyID['sds_block_volume_createVol']}}

-

{{i18n.keyID['sds_block_volume_createVol_desc']}}

-
- -
- - - - -
-
-
- *{{label.name}}: -
-
- *{{label.profile}}: -
-
- *{{label.capacity}}: -
-
- {{label.quantity}}: -
-
- -
-
- -
-
- - - {{getErrorMessage(volumeform.controls['name'+i],"name")}} - -
-
-
-
- -
-
- - - {{getErrorMessage(volumeform.controls['profileId'+i],"profile")}} - -
-
-
-
-
- - -
-
-
- - - {{getErrorMessage(volumeform.controls['size'+i],"Capacity")}} - -
-
-
-
- -
-
- -
-
- - - -
- -
- -
- -
-
-
- - - -
-
diff --git a/dashboard/src/app/business/block/create-volume/create-volume.component.ts b/dashboard/src/app/business/block/create-volume/create-volume.component.ts deleted file mode 100644 index 39e5363e0..000000000 --- a/dashboard/src/app/business/block/create-volume/create-volume.component.ts +++ /dev/null @@ -1,274 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { Router } from '@angular/router'; -import { trigger, state, style, transition, animate } from '@angular/animations'; -import { Validators, FormControl, FormGroup, FormBuilder } from '@angular/forms'; - -import { Message, SelectItem } from './../../../components/common/api'; - -import { VolumeService ,ReplicationService} from './../volume.service'; -import { ProfileService } from './../../profile/profile.service'; -import { AvailabilityZonesService } from './../../resource/resource.service'; -import { I18NService,Utils } from 'app/shared/api'; - -@Component({ - selector: 'app-create-volume', - templateUrl: './create-volume.component.html', - styleUrls: [ - - ], - animations: [ - trigger('overlayState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]), - - trigger('notificationTopbar', [ - state('hidden', style({ - height: '0', - opacity: 0 - })), - state('visible', style({ - height: '*', - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]) - ] -}) -export class CreateVolumeComponent implements OnInit { - - label = { - zone: this.i18n.keyID["sds_block_volume_az"], - name: this.i18n.keyID["sds_block_volume_name"], - profile: this.i18n.keyID["sds_block_volume_profile"], - capacity: this.i18n.keyID["sds_home_capacity"], - quantity: this.i18n.keyID["sds_block_volume_quantity"] - }; - availabilityZones = []; - volumeform; - volumeItems = [0]; - capacityUnit = []; - profileOptions = []; - capacity = 'GB'; - createVolumes = []; - value: boolean; - showReplicationConf = false; - errorMessage = { - "zone": { required: "Zone is required."} - }; - validRule= { - 'name':'^[a-zA-Z]{1}([a-zA-Z0-9]|[_]){0,127}$' - }; - defaultProfile = { - label: null, - value: {id:null,profileName:null} - }; - constructor( - private router: Router, - private fb: FormBuilder, - private ProfileService: ProfileService, - private VolumeService: VolumeService, - private replicationService:ReplicationService, - private availabilityZonesService:AvailabilityZonesService, - public i18n:I18NService - ) {} - - ngOnInit() { - this.getAZ(); - this.getProfiles(); - - this.capacityUnit = [ - { - label: 'GB', value: 'GB' - }, - { - label: 'TB', value: 'TB' - } - ]; - this.volumeform = this.fb.group({ - 'zone': new FormControl('', Validators.required), - 'name0': new FormControl('', {validators:[Validators.required,Validators.pattern(this.validRule.name)]}), - 'profileId0': new FormControl(this.defaultProfile, {validators:[Validators.required,this.checkProfile]}), - 'size0': new FormControl(1, Validators.required), - 'capacity0': new FormControl(''), - 'quantity0': new FormControl(1) - }); - this.volumeform.valueChanges.subscribe( - (value:string)=>{ - this.createVolumes = this.getVolumesDataArray(this.volumeform.value); - this.setRepForm(); - } - ); - this.createVolumes = this.getVolumesDataArray(this.volumeform.value); - this.setRepForm(); - } - - addVolumeItem() { - this.volumeItems.push( - this.volumeItems[this.volumeItems.length-1] + 1 - ); - this.volumeItems.forEach(index => { - if(index !== 0){ - this.volumeform.addControl('name'+index, this.fb.control('', Validators.required)); - this.volumeform.addControl('profileId'+index, this.fb.control(this.defaultProfile,Validators.required)); - this.volumeform.addControl('size'+index, this.fb.control(1, Validators.required)); - this.volumeform.addControl('capacity'+index, this.fb.control('GB', Validators.required)); - this.volumeform.addControl('quantity'+index, this.fb.control(1)); - } - }); - } - getAZ(){ - this.availabilityZonesService.getAZ().subscribe((azRes) => { - let AZs=azRes.json(); - let azArr = []; - if(AZs && AZs.length !== 0){ - AZs.forEach(item =>{ - let obj = {label: item, value: item}; - azArr.push(obj); - }) - } - this.availabilityZones = azArr; - }) - } - getProfiles() { - this.ProfileService.getProfiles().subscribe((res) => { - let profiles = res.json(); - profiles.forEach(profile => { - this.profileOptions.push({ - label: profile.name, - value: {id:profile.id,profileName:profile.name} - }); - }); - }); - } - - deleteVolumeItem(index) { - this.volumeItems.splice(index, 1); - this.volumeform.removeControl('name'+index); - this.volumeform.removeControl('profileId'+index); - this.volumeform.removeControl('size'+index); - this.volumeform.removeControl('capacity'+index); - this.volumeform.removeControl('quantity'+index); - } - - createVolume(param){ - this.VolumeService.createVolume(param).subscribe((res) => { - this.router.navigate(['/block']); - }); - } - createVolumeAndReplication(volParam,repParam){ - this.VolumeService.createVolume(volParam).subscribe((res2) => { - this.VolumeService.createVolume(repParam).subscribe((res) => { - let param = { - "name":res.json().name , - "primaryVolumeId": res2.json().id, - "availabilityZone": res.json().availabilityZone, - "profileId": res.json().profileId, - "replicationMode":"async", - "replicationPeriod":this.createVolumes["formGroup"].value.period, - "secondaryVolumeId":res.json().id - } - this.replicationService.createReplication(param).subscribe((res) => {}); - this.router.navigate(['/block']); - }); - }); - } - onSubmit(value) { - if(!this.volumeform.valid){ - for(let i in this.volumeform.controls){ - this.volumeform.controls[i].markAsTouched(); - } - return; - } - if(this.showReplicationConf && !this.createVolumes["formGroup"].valid){ - for(let i in this.createVolumes["formGroup"].controls){ - this.createVolumes["formGroup"].controls[i].markAsTouched(); - } - return; - } - let dataArr = this.getVolumesDataArray(value); - let volumeData = []; - dataArr.forEach(item => { - volumeData.push({ - name: item.name, - size: item.size, - availabilityZone: item.availabilityZone, - profileId: item.profile.id - }); - }); - for(let i in volumeData){ - if(this.showReplicationConf){ - let repVolume = { - name:null, - profileId:null, - availabilityZone: null - }; - Object.assign(repVolume,volumeData[i]); - repVolume.name = this.createVolumes["formGroup"].value["name"+i]; - repVolume.profileId = this.createVolumes["formGroup"].value["profileId"+i]; - repVolume.availabilityZone = "secondary"; - this.createVolumeAndReplication(volumeData[i],repVolume); - }else{ - this.createVolume(volumeData[i]); - } - } - } - getVolumesDataArray(value){ - let dataArr = []; - this.volumeItems.forEach(index => { - if(!value['capacity'+index]){ - value['capacity'+index]='GB'; - } - let unit = value['capacity'+index]==='GB' ? 1 : 1024; - let qunantity = value['quantity'+index]; - if(qunantity && qunantity !== 1){ - for(let i=0;i - -
- {{I18N.keyID['sds_block_volume_rep_pair']}} -
-
-
-
-
-
-
-
-
-
- -
- - {{volumes.length!=0 ? volumes[0].availabilityZone:''}} -
-
-
-
-
-
- -
-
- -
-
- -
-
-
-
-
-
-
-
- {{I18N.keyID['sds_profile_rep_period']}} - = - - {{I18N.keyID['sds_profile_unit_minutes']}} -
- -
-
-
-
- -
-
-
-
-
-
-
-
- -
- - - -
-
-
-
-
-
- -
-
- -
-
- - ProfileId is required -
-
-
-
-
-
-
-
-
-
- diff --git a/dashboard/src/app/business/block/create-volume/replication-group/replication-group.component.ts b/dashboard/src/app/business/block/create-volume/replication-group/replication-group.component.ts deleted file mode 100644 index 3cc275e04..000000000 --- a/dashboard/src/app/business/block/create-volume/replication-group/replication-group.component.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { Component, OnInit,Input,Output,EventEmitter} from '@angular/core'; -import { trigger, state, style, transition, animate } from '@angular/animations'; - -import { ProfileService } from './../../../profile/profile.service'; -import {FormBuilder, FormControl, Validators} from "@angular/forms"; -import { I18NService,Utils } from 'app/shared/api'; - -@Component({ - selector: 'app-replication-group', - templateUrl: './replication-group.component.html', - styleUrls: [ - - ], - animations: [ - trigger('overlayState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]), - - trigger('notificationTopbar', [ - state('hidden', style({ - height: '0', - opacity: 0 - })), - state('visible', style({ - height: '*', - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]) - ] -}) -export class ReplicationGroupComponent implements OnInit { - groupOptions = []; - createOrExist = 'createGroup'; - existingGroupLists = []; - replicationEnable:boolean; - @Input() volumes:any; - @Output() checkParam = new EventEmitter(); - period = 60; - selectedProfile; - availabilityZone=[]; - profileOptions = [ - { - label: 'Select Profile', - value: null - } - ]; - - constructor( - private ProfileService: ProfileService, - private fb: FormBuilder, - public I18N:I18NService - ) { } - - ngOnInit() { - this.groupOptions = [ - { - label: 'Create Group', - value: 'createGroup' - }, - { - label: 'Add to Existing Group', - value: 'existingGroup' - } - ]; - this.availabilityZone = [ - { - label: 'Secondary', value: 'secondary' - } - ]; - this.getProfiles(); - } - - getReplicationGroup(){ - if(this.createOrExist==='existingGroup'){ - this.existingGroupLists = [ - { - label: 'group_for_REP', - value: 'group_for_REP_id1' - }, - { - label: 'group_for_REP', - value: 'group_for_REP_id2' - } - ] - } - } - - getProfiles() { - this.ProfileService.getProfiles().subscribe((res) => { - let profiles = res.json(); - profiles.forEach(profile => { - this.profileOptions.push({ - label: profile.name, - value: profile.id - }); - }); - }); - } - checkParamSubmit(){ - this.checkParam.emit(false); - } -} diff --git a/dashboard/src/app/business/block/volume-detail/replication-list/replication-list.component.html b/dashboard/src/app/business/block/volume-detail/replication-list/replication-list.component.html deleted file mode 100644 index e19f19af8..000000000 --- a/dashboard/src/app/business/block/volume-detail/replication-list/replication-list.component.html +++ /dev/null @@ -1,71 +0,0 @@ -
-
-
- - - - -
-
-
-
-
-
-
-
-
- -
-
-
{{volume.name}}
-
-
- - default -
-
-
-
-
-
-
-
-
- {{I18N.keyID['sds_profile_rep_period']}} - = - - {{periodControl.value}} - {{I18N.keyID['sds_profile_unit_minutes']}} - -
-
-
{{replication['replicationStatus']}}
-
-
-
-
-
-
-
-
-
- -
-
-
{{replication.name}}
-
-
- - secondary -
-
-
-
-
-
-
-
-
- no data available -
- diff --git a/dashboard/src/app/business/block/volume-detail/replication-list/replication-list.component.ts b/dashboard/src/app/business/block/volume-detail/replication-list/replication-list.component.ts deleted file mode 100644 index 6cb0c20b5..000000000 --- a/dashboard/src/app/business/block/volume-detail/replication-list/replication-list.component.ts +++ /dev/null @@ -1,241 +0,0 @@ -import {Component, Input, OnInit} from '@angular/core'; -import { I18NService } from 'app/shared/api'; -import { VolumeService ,ReplicationService} from './../../volume.service'; -import { ConfirmationService,ConfirmDialogModule} from '../../../../components/common/api'; -import { FormControl, FormGroup, FormBuilder, Validators, ValidatorFn, AbstractControl } from '@angular/forms'; - -@Component({ - selector: 'app-replication-list', - templateUrl: './replication-list.component.html', - providers: [ConfirmationService], - styleUrls: [ - - ] -}) -export class ReplicationListComponent implements OnInit { - - @Input() volumeId; - volume={ - name:"" - }; - replication ={ - name:"replication", - replicationPeriod:30, - id:"" - }; - arrowEnable = true; - showReplication:boolean=false; - editReplicationDisable :boolean=true; - periodControl:FormControl; - //[0]:status:enble;[1]:status:disabled;[2]:status:failover;[3]:status:other - swichMode = [ - { - disableBtnDisplay:true, - disableBtnDisabled:false, - enableBtnDisplay:false, - enableBtnDisabled:true, - failoverBtnDisabled:false, - }, - { - disableBtnDisplay:false, - disableBtnDisabled:true, - enableBtnDisplay:true, - enableBtnDisabled:false, - failoverBtnDisabled:false, - }, - { - disableBtnDisplay:false, - disableBtnDisabled:true, - enableBtnDisplay:true, - enableBtnDisabled:false, - failoverBtnDisabled:true, - }, - { - disableBtnDisplay:true, - disableBtnDisabled:true, - enableBtnDisplay:false, - enableBtnDisabled:true, - failoverBtnDisabled:true, - } - ]; - operationStatus:any; - constructor( - public I18N:I18NService, - private VolumeService:VolumeService, - private replicationService:ReplicationService, - private confirmationService:ConfirmationService - ) { } - - ngOnInit() { - this.operationStatus = this.swichMode[3]; - this.periodControl = new FormControl("1"); - this.getAllReplicationsDetail(); - this.periodControl.valueChanges.subscribe( - (value)=>{ - if(Number(value) < 1){ - this.periodControl.setValue("1"); - } - } - ); - } - getAllReplicationsDetail(){ - this.replicationService.getAllReplicationsDetail().subscribe((resRep)=>{ - let replications = resRep.json(); - replications.forEach(element => { - if(element.primaryVolumeId == this.volumeId){ - this.getVolumeById(this.volumeId); - this.replication = element; - this.periodControl.setValue(this.replication.replicationPeriod); - //ReplicationStatus - switch(this.replication['replicationStatus']){ - case "enabled": - this.operationStatus = this.swichMode[0]; - this.arrowEnable = true; - break; - case "disabled": - this.operationStatus = this.swichMode[1]; - this.arrowEnable = false; - break; - case "failed_over": - this.operationStatus = this.swichMode[2]; - this.arrowEnable = false; - break; - default: - this.operationStatus = this.swichMode[3]; - this.arrowEnable = false; - } - this.showReplication = true; - } - if(element.secondaryVolumeId == this.volumeId){ - this.replication = element; - this.periodControl.setValue(this.replication.replicationPeriod); - //ReplicationStatus - switch(this.replication['replicationStatus']){ - case "enabled": - this.operationStatus = this.swichMode[0]; - this.arrowEnable = true; - break; - case "disabled": - this.operationStatus = this.swichMode[1]; - this.arrowEnable = false; - break; - case "failed_over": - this.operationStatus = this.swichMode[2]; - this.arrowEnable = false; - break; - default: - this.operationStatus = this.swichMode[3]; - this.arrowEnable = false; - } - this.getVolumeById(element.primaryVolumeId); - this.showReplication = true; - } - }); - }); - } - getVolumeById(volumeId){ - this.VolumeService.getVolumeById(volumeId).subscribe((res) => { - this.volume = res.json(); - }); - } - getReplicationByVolumeId = function(volumeId){ - let param = { - "key": "PrimaryVolumeId", - "value":volumeId - } - this.replicationService.getReplicationDetailByVolumeId(param).subscribe((res) => { - var data = res.json(); - if(data.length !== 0){ - this.replication = data[0]; - this.showReplication = true; - }else{ - this.showReplication = false; - } - }); - } - disableReplication(){ - let msg = "
Are you sure you want to disable the Replication?

[ "+ this.replication.name +" ]

"; - let header ="Disable Replication"; - let acceptLabel = "Disable"; - let warming = false; - this.confirmDialog([msg,header,acceptLabel,warming,"disable"]) - } - enableReplication(){ - let msg = "
Are you sure you want to enable the Replication?

[ "+ this.replication.name +" ]

"; - let header ="Enable Replication"; - let acceptLabel = "Enable"; - let warming = false; - this.confirmDialog([msg,header,acceptLabel,warming,"enable"]) - } - failoverReplication(){ - let msg = "
Are you sure you want to failover the Replication?

[ "+ this.replication.name +" ]

"; - let header ="Failover Replication"; - let acceptLabel = "Failover"; - let warming = true; - this.confirmDialog([msg,header,acceptLabel,warming,"failover"]) - } - deleteReplication(){ - let msg = "
Are you sure you want to delete the Replication?

[ "+ this.replication.name +" ]

"; - let header ="Delete Replication"; - let acceptLabel = "Delete"; - let warming = true; - this.confirmDialog([msg,header,acceptLabel,warming,"delete"]) - } - editReplicationPriod(){ - if(!this.editReplicationDisable){ - //wait interface modify period ,icon color:#40bcec - if(this.replication.replicationPeriod != this.periodControl.value){ - let param = { - name:this.replication.name, - replicationPeriod:this.periodControl.value - }; - this.replicationService.modifyReplication(this.replication.id,param).subscribe((res)=>{ - this.getAllReplicationsDetail(); - }); - } - } - this.editReplicationDisable = !this.editReplicationDisable; - - } - confirmDialog([msg,header,acceptLabel,warming=true,func]){ - this.confirmationService.confirm({ - message: msg, - header: header, - acceptLabel: acceptLabel, - isWarning: warming, - accept: ()=>{ - try { - switch(func){ - case "disable": - this.replicationService.disableReplication(this.replication.id).subscribe((res)=>{ - this.getAllReplicationsDetail(); - }); - break; - case "delete": - this.replicationService.deleteReplication(this.replication.id).subscribe((res)=>{ - this.getAllReplicationsDetail(); - }); - break; - case "failover": - this.replicationService.failoverReplication(this.replication.id).subscribe((res)=>{ - this.getAllReplicationsDetail(); - }); - break; - case "enable": - this.replicationService.enableReplication(this.replication.id).subscribe((res)=>{ - this.getAllReplicationsDetail(); - }); - break; - } - } - catch (e) { - console.log(e); - } - finally { - this.getAllReplicationsDetail(); - } - }, - reject:()=>{} - }) - } -} diff --git a/dashboard/src/app/business/block/volume-detail/snapshot-list/snapshot-list.component.html b/dashboard/src/app/business/block/volume-detail/snapshot-list/snapshot-list.component.html deleted file mode 100644 index d5205626a..000000000 --- a/dashboard/src/app/business/block/volume-detail/snapshot-list/snapshot-list.component.html +++ /dev/null @@ -1,71 +0,0 @@ -
-
-
- - -
-
-
- - -
- -
-
- - - - - - - - - - - {{I18N.keyID['sds_block_volume_createVol']}} - {{I18N.keyID['sds_block_volume_modify']}} - {{I18N.keyID['sds_block_volume_delete']}} - - - - - - -
- - {{volume.name}} - - - - - - - - - -
- - - - - -
- - -
- - - - - - - -
- - - - - -
-
- diff --git a/dashboard/src/app/business/block/volume-detail/snapshot-list/snapshot-list.component.ts b/dashboard/src/app/business/block/volume-detail/snapshot-list/snapshot-list.component.ts deleted file mode 100644 index 40f9604e4..000000000 --- a/dashboard/src/app/business/block/volume-detail/snapshot-list/snapshot-list.component.ts +++ /dev/null @@ -1,221 +0,0 @@ -import { Component, OnInit, Input } from '@angular/core'; -import { FormControl, FormGroup, FormBuilder, Validators, ValidatorFn, AbstractControl } from '@angular/forms'; -import { VolumeService,SnapshotService } from './../../volume.service'; -import { ConfirmationService,ConfirmDialogModule} from '../../../../components/common/api'; -import { I18NService, MsgBoxService, Utils } from 'app/shared/api'; - -@Component({ - selector: 'app-snapshot-list', - templateUrl: './snapshot-list.component.html', - providers: [ConfirmationService], - styleUrls: [ - - ] -}) -export class SnapshotListComponent implements OnInit { - - @Input() volumeId; - volume; - label; - selectedSnapshotId; - selectedSnapshots = []; - snapshots; - snapshotfilter; - snapshotPropertyDisplay = false; - snapshotFormGroup; - createVolumeFormGroup; - createVolumeDisplay: boolean = false; - - isCreate = false; - isModify = false; - snapshotProperty = { - name: '', - description: '' - } - okBtnDisabled = false; - - errorMessage = { - "name": { required: "Name is required." }, - "description": { maxlength: "Max. length is 200." } - }; - param = { - key: 'VolumeId', - value: null - } - constructor( - private VolumeService: VolumeService, - private SnapshotService: SnapshotService, - private fb: FormBuilder, - private confirmationService:ConfirmationService, - public I18N:I18NService, - private msg: MsgBoxService - ) { - this.snapshotFormGroup = this.fb.group({ - "name": ["", Validators.required], - "description": ["", Validators.maxLength(200)] - }); - - this.createVolumeFormGroup = this.fb.group({ - "name": ["", Validators.required], - "description": ["", Validators.maxLength(200)] - }); - } - - ngOnInit() { - this.getVolumeById(this.volumeId); - this.label = { - name: this.I18N.keyID['sds_block_volume_name'], - volume: this.I18N.keyID['sds_block_volume_title'], - description: this.I18N.keyID['sds_block_volume_descri'] - } - this.param={ - key: 'VolumeId', - value: this.volumeId - }; - this.getSnapshots(this.param); - } - - getVolumeById(volumeId){ - this.VolumeService.getVolumeById(volumeId).subscribe((res) => { - this.volume = res.json(); - }); - } - - createSnapshot() { - let param = { - name: this.snapshotFormGroup.value.name, - volumeId: this.volumeId, - description: this.snapshotFormGroup.value.description - } - this.SnapshotService.createSnapshot(param).subscribe((res) => { - this.getSnapshots( - { - key: 'VolumeId', - value: this.volumeId - } - ); - }); - } - - batchDeleteSnapshot(param) { - if (param) { - let msg; - if(param.length>1){ - - msg = "
Are you sure you want to delete the selected Snapshots?

[ "+ param.length +" Snapshots ]

"; - }else{ - msg = "
Are you sure you want to delete the Snapshot?

[ "+ param[0].name +" ]

"; - } - - this.confirmationService.confirm({ - message: msg, - header: this.I18N.keyID['sds_block_volume_del_sna'], - acceptLabel: this.I18N.keyID['sds_block_volume_delete'], - isWarning: true, - accept: ()=>{ - param.forEach(snapshot => { - this.deleteSnapshot(snapshot.id); - - }); - }, - reject:()=>{} - }) - } - } - - deleteSnapshot(id) { - this.SnapshotService.deleteSnapshot(id).subscribe((res) => { - Utils.arrayRemoveOneElement(this.selectedSnapshots,id,function(value,index,arr){ - return value.id === id; - }); - this.getSnapshots( - { - key: 'VolumeId', - value: this.volumeId - } - ); - }); - } - - getSnapshots(filter?) { - this.SnapshotService.getSnapshots(filter).subscribe((res) => { - this.snapshots = res.json(); - this.snapshotPropertyDisplay = false; - - this.snapshots.map((item, index, arr)=>{ - item.size = Utils.getDisplayGBCapacity(item.size); - }) - }); - } - - modifySnapshot(){ - let param = { - name: this.snapshotFormGroup.value.name, - description: this.snapshotFormGroup.value.description - } - this.SnapshotService.modifySnapshot(this.selectedSnapshotId,param).subscribe((res) => { - this.getSnapshots( - { - key: 'VolumeId', - value: this.volumeId - } - ); - }); - } - - showSnapshotPropertyDialog(method,selectedSnapshot?){ - this.snapshotPropertyDisplay = true; - if(method === 'create'){ - this.isCreate = true; - this.isModify = false; - this.snapshotProperty.name = ''; - this.snapshotProperty.description = ''; - }else if(method === 'modify'){ - this.isCreate = false; - this.isModify = true; - this.snapshotProperty.name = selectedSnapshot.name; - this.snapshotProperty.description = selectedSnapshot.description; - } - if(selectedSnapshot && selectedSnapshot.id){ - this.selectedSnapshotId = selectedSnapshot.id; - } - } - - snapshotModifyOrCreate(){ - if(this.isModify){ - this.modifySnapshot(); - }else{ - this.createSnapshot(); - } - - } - - showCreateVolumeBasedonSnapshot(snapshot){ - this.createVolumeDisplay = true; - this.selectedSnapshotId = snapshot.id; - } - - createVolumeBasedonSnapshot(snapshot) { - let param = { - name: this.createVolumeFormGroup.value.name, - description: this.createVolumeFormGroup.value.description, - size: this.volume.size, - availabilityZone: this.volume.availabilityZone, - profileId: this.volume.profileId, - snapshotId: this.selectedSnapshotId - } - - if(this.createVolumeFormGroup.status == "VALID"){ - this.VolumeService.createVolume(param).subscribe((res) => { - this.createVolumeDisplay = false; - this.msg.info("The volume is being created, please go to the volume list and check it."); - }); - }else{ - // validate - for(let i in this.createVolumeFormGroup.controls){ - this.createVolumeFormGroup.controls[i].markAsTouched(); - } - } - } - -} diff --git a/dashboard/src/app/business/block/volume-detail/volume-detail.component.html b/dashboard/src/app/business/block/volume-detail/volume-detail.component.html deleted file mode 100644 index a07de63e0..000000000 --- a/dashboard/src/app/business/block/volume-detail/volume-detail.component.html +++ /dev/null @@ -1,64 +0,0 @@ -
-
- - {{item.label}} - > - -
-
-

{{i18n.keyID['sds_block_volume_base_info']}}

-

{{ volumeSource }}

-
-
-
- {{label.Name}}: -
-
- {{volume.name}} -
-
- {{label.Profile}}: -
-
- {{volume.profileName}} -
-
- {{label.Status}}: -
-
- {{volume.status}} -
-
-
-
- {{label.Capacity}}: -
-
- {{volume.size}} -
-
- {{label.VolumeID}}: -
-
- {{volume.id}} -
-
- {{label.CreatedAt}}: -
-
- {{volume.createdAt}} -
-
-
-
-
- - - - - - - - -
-
diff --git a/dashboard/src/app/business/block/volume-detail/volume-detail.component.ts b/dashboard/src/app/business/block/volume-detail/volume-detail.component.ts deleted file mode 100644 index f9a36cd9b..000000000 --- a/dashboard/src/app/business/block/volume-detail/volume-detail.component.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { Router,ActivatedRoute} from '@angular/router'; - -import { VolumeService } from './../volume.service'; -import { ProfileService } from './../../profile/profile.service'; -import { I18NService, Utils } from 'app/shared/api'; - -@Component({ - selector: 'app-volume-detail', - templateUrl: './volume-detail.component.html', - styleUrls: [ - - ] -}) -export class VolumeDetailComponent implements OnInit { - items; - label; - volume; - volumeId; - showVolumeSource: boolean = false; - volumeSource: string = ""; - - constructor( - private VolumeService: VolumeService, - private ActivatedRoute: ActivatedRoute, - private ProfileService: ProfileService, - public i18n:I18NService - ) { } - - ngOnInit() { - this.ActivatedRoute.params.subscribe((params) => this.volumeId = params.volumeId); - - this.items = [ - { label: this.i18n.keyID["sds_block_volume_title"], url: '/block' }, - { label: this.i18n.keyID["sds_block_volume_detail"], url: '/volumeDetail' } - ]; - - this.label = { - Name: this.i18n.keyID["sds_block_volume_name"], - Profile: this.i18n.keyID["sds_block_volume_profile"], - Status: this.i18n.keyID["sds_block_volume_status"], - VolumeID: this.i18n.keyID["sds_block_volume_id"], - Capacity: this.i18n.keyID["sds_home_capacity"], - CreatedAt: this.i18n.keyID["sds_block_volume_createat"] - }; - - this.getVolume(this.volumeId); - } - - getVolume(id){ - this.VolumeService.getVolumeById(id).subscribe((res) => { - this.volume = res.json(); - this.volume.size = Utils.getDisplayGBCapacity(res.json().size); - this.ProfileService.getProfileById(this.volume.profileId).subscribe((res)=>{ - this.volume.profileName = res.json().name; - }) - - if(this.volume.snapshotId != ""){ - this.showVolumeSource = true; - this.volumeSource = this.i18n.keyID['sds_block_volume_source'].replace("{{}}", this.volume.snapshotId); - } - }); - } - -} diff --git a/dashboard/src/app/business/block/volume-detail/volume-detail.module.ts b/dashboard/src/app/business/block/volume-detail/volume-detail.module.ts deleted file mode 100644 index 38f551aec..000000000 --- a/dashboard/src/app/business/block/volume-detail/volume-detail.module.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { ReactiveFormsModule, FormsModule } from '@angular/forms'; -import { RouterModule } from '@angular/router'; -import { VolumeDetailComponent } from './volume-detail.component'; - -import { TabViewModule,ButtonModule, DataTableModule, DropMenuModule, DialogModule, FormModule, InputTextModule, InputTextareaModule, ConfirmDialogModule ,ConfirmationService} from './../../../components/common/api'; -import { HttpService } from './../../../shared/service/Http.service'; -import { VolumeService,SnapshotService ,ReplicationService} from './../volume.service'; -import { SnapshotListComponent } from './snapshot-list/snapshot-list.component'; -import { ReplicationListComponent } from './replication-list/replication-list.component'; -import { ProfileService } from './../../profile/profile.service'; - -let routers = [{ - path: '', - component: VolumeDetailComponent -}] - -@NgModule({ - imports: [ - CommonModule, - ReactiveFormsModule, - FormsModule, - InputTextModule, - InputTextareaModule, - RouterModule.forChild(routers), - TabViewModule, - ButtonModule, - DataTableModule, - DialogModule, - FormModule, - ConfirmDialogModule - ], - declarations: [ - VolumeDetailComponent, - SnapshotListComponent, - ReplicationListComponent - ], - providers: [ - HttpService, - VolumeService, - SnapshotService, - ConfirmationService, - ProfileService, - ReplicationService - ] -}) -export class VolumeDetailModule { } diff --git a/dashboard/src/app/business/block/volume-group-detail/volume-group-detail.component.html b/dashboard/src/app/business/block/volume-group-detail/volume-group-detail.component.html deleted file mode 100644 index 15877e379..000000000 --- a/dashboard/src/app/business/block/volume-group-detail/volume-group-detail.component.html +++ /dev/null @@ -1,84 +0,0 @@ -
-
- - {{item.label}} - > - -
-
-

{{I18N.keyID['sds_block_volume_base_info']}}

-
-
-
- {{label.Name}}: -
-
- {{volumeGroup.name}} -
-
- {{label.description}}: -
-
- {{volumeGroup.description}} -
-
- {{label.Status}}: -
-
- {{volumeGroup.status}} -
-
-
-
- {{label.Profile}}: -
-
- {{volumeGroup.profileName}} -
-
- {{label.groupId}}: -
-
- {{volumeGroup.id}} -
-
- {{label.CreatedAt}}: -
-
- {{volumeGroup.createdAt}} -
-
-
-
-
- -
-
- - - - - - - - - {{I18N.keyID['sds_block_volume_group_remove']}} - - - -
-
- - - - - - - - - - - - - - \ No newline at end of file diff --git a/dashboard/src/app/business/block/volume-group-detail/volume-group-detail.component.ts b/dashboard/src/app/business/block/volume-group-detail/volume-group-detail.component.ts deleted file mode 100644 index 5d18a700c..000000000 --- a/dashboard/src/app/business/block/volume-group-detail/volume-group-detail.component.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { Router,ActivatedRoute} from '@angular/router'; -import { VolumeService ,VolumeGroupService} from './../volume.service'; -import { ProfileService } from './../../profile/profile.service'; -import { I18NService, Utils } from 'app/shared/api'; -import { TabViewModule,ButtonModule, DataTableModule, DropMenuModule, DialogModule, FormModule, InputTextModule, InputTextareaModule, ConfirmDialogModule ,ConfirmationService} from './../../../components/common/api'; - -@Component({ - selector: 'app-volume-group-detail', - templateUrl: './volume-group-detail.component.html', - providers: [ConfirmationService], - styleUrls: [] -}) -export class VolumeGroupDetailComponent implements OnInit { - items = []; - volumeGroupId:string; - volumeGroup:any; - label:any; - profileJson = {}; - volumes=[]; - allOptionalVolumes = []; - selectedVolumes = []; - showAddVolumes:boolean=false; - constructor( - private VolumeService: VolumeService, - private ActivatedRoute: ActivatedRoute, - private profileService: ProfileService, - private VolumeGroupService:VolumeGroupService, - private confirmationService:ConfirmationService, - public I18N:I18NService - ) { } - - ngOnInit() { - this.ActivatedRoute.params.subscribe( - (params) => this.volumeGroupId = params.groupId - ); - this.getProfiles(); - this.items = [ - { label: this.I18N.keyID["sds_block_volume_group_router"], url: '/block' }, - { label: this.I18N.keyID["sds_block_volume_group_detail"], url: '/volumeGroupDetails' } - ]; - this.label = { - Name: this.I18N.keyID["sds_block_volume_name"], - Profile: this.I18N.keyID["sds_block_volume_profile"], - Status: this.I18N.keyID["sds_block_volume_status"], - groupId: this.I18N.keyID["sds_block_volume_group_id"], - description:this.I18N.keyID["sds_block_volume_descri"], - CreatedAt: this.I18N.keyID["sds_block_volume_createat"] - }; - } - getVolumeGroupById(groupId){ - this.VolumeGroupService.getVolumeGroupById(groupId).subscribe((res)=>{ - let volumeGroup = res.json(); - if(volumeGroup && volumeGroup.length != 0){ - if(!volumeGroup.description){ - volumeGroup.description = "--"; - } - let profileName = []; - volumeGroup.profiles.forEach((profileId)=>{ - profileName.push(this.profileJson[profileId]); - }); - volumeGroup.profileName = profileName; - } - this.volumeGroup = volumeGroup; - this.getAllOptionalVolumes(); - }); - } - getProfiles() { - this.profileService.getProfiles().subscribe((res) => { - let profiles = res.json(); - profiles.forEach(profile => { - this.profileJson[profile.id] = profile.name; - }); - this.getVolumeGroupById(this.volumeGroupId); - this.getVolumesByGroupId(this.volumeGroupId); - }); - } - getAllOptionalVolumes(){ - this.VolumeService.getVolumes().subscribe((res)=>{ - let allVolumes = res.json(); - this.allOptionalVolumes = []; - if(allVolumes){ - allVolumes.forEach((item)=>{ - if(item.pooId == this.volumeGroup.pooId && !item.groupId && this.volumeGroup.profiles.includes(item.profileId)){ - item.size = Utils.getDisplayGBCapacity(item.size); - item.profileName = this.profileJson[item.profileId]; - this.allOptionalVolumes.push(item); - } - }); - } - }); - } - getVolumesByGroupId(volumeGroupId){ - this.VolumeService.getVolumeByGroupId(volumeGroupId).subscribe((res)=>{ - let volumes = res.json(); - if(volumes && volumes.length != 0){ - volumes.forEach((item)=>{ - item.size = Utils.getDisplayGBCapacity(item.size); - item.profileName = this.profileJson[item.profileId]; - }); - } - this.volumes = volumes; - }); - }; - addVolumesToGroup(){ - let volumes = []; - this.selectedVolumes.forEach((item)=>{ - volumes.push(item.id); - }); - let param = { - "addVolumes": volumes, - } - this.selectedVolumes = []; - this.VolumeGroupService.addOrRemovevolumes(this.volumeGroupId,param).subscribe((res)=>{ - this.showAddVolumes = false; - this.getProfiles(); - }); - } - removeVolumeFromGroup(volume){ - let msg = "
Are you sure you want to remove the selected Volume ?

[ "+ volume.name +"]

"; - let header ="Remove Volume"; - let acceptLabel = "Remove"; - let warming = true; - this.confirmDialog([msg,header,acceptLabel,warming,"remove",volume]) - } - confirmDialog([msg,header,acceptLabel,warming=true,func,data]){ - this.confirmationService.confirm({ - message: msg, - header: header, - acceptLabel: acceptLabel, - isWarning: warming, - accept: ()=>{ - try { - if(func === "remove"){ - let param = { - "removeVolumes": [ - data.id - ], - } - this.VolumeGroupService.addOrRemovevolumes(this.volumeGroupId,param).subscribe((res)=>{ - this.getProfiles(); - }); - } - } - catch (e) { - console.log(e); - } - finally { - - } - }, - reject:()=>{} - }) - } - -} diff --git a/dashboard/src/app/business/block/volume-group-detail/volume-group-detail.module.ts b/dashboard/src/app/business/block/volume-group-detail/volume-group-detail.module.ts deleted file mode 100644 index a1e665b29..000000000 --- a/dashboard/src/app/business/block/volume-group-detail/volume-group-detail.module.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { VolumeGroupDetailComponent } from './volume-group-detail.component'; -import { RouterModule } from '@angular/router'; -import { ReactiveFormsModule, FormsModule } from '@angular/forms'; -import { TabViewModule,ButtonModule, DataTableModule, DropMenuModule, DialogModule, FormModule, InputTextModule, InputTextareaModule, ConfirmDialogModule ,ConfirmationService} from './../../../components/common/api'; -import { HttpService } from './../../../shared/service/Http.service'; -import { VolumeService,VolumeGroupService} from './../volume.service'; -import { ProfileService } from './../../profile/profile.service'; - -let routers = [{ - path: '', - component: VolumeGroupDetailComponent -}] -@NgModule({ - imports: [ - CommonModule, - RouterModule.forChild(routers), - ReactiveFormsModule, - FormsModule, - InputTextModule, - InputTextareaModule, - TabViewModule, - ButtonModule, - DataTableModule, - DialogModule, - FormModule, - ConfirmDialogModule - ], - declarations: [VolumeGroupDetailComponent], - providers: [ - HttpService, - VolumeService, - ConfirmationService, - ProfileService, - VolumeGroupService - ] -}) -export class VolumeGroupDetailModule { } diff --git a/dashboard/src/app/business/block/volume.service.ts b/dashboard/src/app/business/block/volume.service.ts deleted file mode 100644 index 0dccc1e6a..000000000 --- a/dashboard/src/app/business/block/volume.service.ts +++ /dev/null @@ -1,192 +0,0 @@ -import { Injectable } from '@angular/core'; -import { I18NService, HttpService, ParamStorService } from '../../shared/api'; -import { Observable } from 'rxjs'; - -@Injectable() -export class VolumeService { - constructor( - private http: HttpService, - private paramStor: ParamStorService - ) { } - - url = 'v1beta/{project_id}/block/volumes'; - - //Create volume - createVolume(param) { - return this.http.post(this.url, param); - } - - //Update volume - modifyVolume(id,param) { - let modifyUrl = this.url + '/' + id - return this.http.put(modifyUrl, param); - } - - //Delete volume - deleteVolume(id): Observable { - let deleteUrl = this.url + '/' + id - return this.http.delete(deleteUrl); - } - - //Search all volumes - getVolumes(): Observable { - return this.http.get(this.url); - } - - //Search volume - getVolumeById(id): Observable { - let url = this.url + '/' + id; - return this.http.get(url); - } - //Search volume by groupId - getVolumeByGroupId(id): Observable { - let url = this.url + '?GroupId=' + id; - return this.http.get(url); - } - - //Create volumesGroup - createVolumesGroup(param) { - return this.http.post(this.url, param); - } - - //Delete volumesGroup - deleteVolumesGroup(id): Observable { - let deleteUrl = this.url + '/' + id - return this.http.delete(deleteUrl); - } - - //Search volumesGroups - getVolumesGroups(): Observable { - return this.http.get(this.url); - } - expandVolume(id,param):Observable { - let expandVolumeUrl = 'v1beta/{project_id}/block/volumes' + '/' + id + "/resize" - return this.http.post(expandVolumeUrl,param); - } -} - -@Injectable() -export class SnapshotService { - constructor( - private http: HttpService, - private paramStor: ParamStorService - ) { } - - url = 'v1beta/{project_id}/block/snapshots'; - - //Create snapshot - createSnapshot(param) { - return this.http.post(this.url, param); - } - - //Delete snapshot - deleteSnapshot(id){ - let url = this.url + "/" + id; - return this.http.delete(url); - } - - //Search snapshot - getSnapshots(filter?){ - let url = this.url; - if(filter){ - url = this.url + "?" + filter.key + "=" + filter.value; - } - return this.http.get(url); - } - - //Update snapshot - modifySnapshot(id,param){ - let url = this.url + "/" + id; - return this.http.put(url,param); - } -} -@Injectable() -export class ReplicationService { - constructor( - private http: HttpService, - private paramStor: ParamStorService - ) { } - - project_id = this.paramStor.CURRENT_TENANT().split("|")[1]; - replicationUrl = 'v1beta/{project_id}/block/replications'; - //create replication - createReplication(param){ - let url = this.replicationUrl; - return this.http.post(url,param); - } - getReplicationDetailByVolumeId(filter?){ - let url = this.replicationUrl+"/detail"; - if(filter){ - url = url + "?" + filter.key + "=" + filter.value; - } - return this.http.get(url); - } - disableReplication(param){ - let url = this.replicationUrl+"/"+param+"/disable"; - return this.http.post(url,param); - } - enableReplication(param){ - let url = this.replicationUrl+"/"+param+"/enable"; - return this.http.post(url,param); - } - failoverReplication(id){ - let url = this.replicationUrl+"/"+id+"/failover"; - let param = { - "allowAttachedVolume": true, - "secondaryBackendId": "default" - } - return this.http.post(url,param); - } - deleteReplication(param){ - let url = this.replicationUrl+"/"+param; - return this.http.delete(url); - } - modifyReplication(replicationId,param){ - let url = this.replicationUrl+"/"+replicationId; - return this.http.put(url,param); - } - //get all replications - getAllReplicationsDetail(){ - let url = this.replicationUrl+"/detail"; - return this.http.get(url); - } -} -@Injectable() -export class VolumeGroupService { - constructor( - private http: HttpService, - private paramStor: ParamStorService - ) { } - - project_id = this.paramStor.CURRENT_TENANT().split("|")[1]; - volumeGroupUrl = 'v1beta/{project_id}/block/volumeGroup'; - //create volume group - createVolumeGroup(param){ - let url = this.volumeGroupUrl; - return this.http.post(url,param); - } - //get volume group - getVolumeGroups(): Observable { - return this.http.get(this.volumeGroupUrl); - } - //delete volume group - deleteVolumeGroup(groupId): Observable { - let url = this.volumeGroupUrl+"/" + groupId - return this.http.delete(url); - } - //modify volume group - modifyVolumeGroup(groupId,param): Observable { - let url = this.volumeGroupUrl+"/" + groupId - return this.http.put(url,param); - } - //get volume group by id - getVolumeGroupById(groupId): Observable { - let url = this.volumeGroupUrl+"/"+groupId; - return this.http.get(url); - } - //add or remove volumes - addOrRemovevolumes(groupId,param): Observable { - let url = this.volumeGroupUrl+"/"+groupId; - return this.http.put(url,param); - } -} diff --git a/dashboard/src/app/business/block/volumeGroup.component.ts b/dashboard/src/app/business/block/volumeGroup.component.ts deleted file mode 100644 index abde0e952..000000000 --- a/dashboard/src/app/business/block/volumeGroup.component.ts +++ /dev/null @@ -1,213 +0,0 @@ -import { Component, OnInit, ViewContainerRef, ViewChild, Directive, ElementRef, HostBinding, HostListener } from '@angular/core'; -import { I18NService } from 'app/shared/api'; -import { AppService } from 'app/app.service'; -import { I18nPluralPipe } from '@angular/common'; -import { trigger, state, style, transition, animate} from '@angular/animations'; -import { DialogModule } from '../../components/common/api'; -import { FormControl, FormGroup, FormBuilder, Validators, ValidatorFn, AbstractControl} from '@angular/forms'; -import { VolumeService ,VolumeGroupService} from './volume.service'; -import { ProfileService } from './../profile/profile.service'; -import { AvailabilityZonesService } from './../resource/resource.service'; -import { ConfirmationService,ConfirmDialogModule} from '../../components/common/api'; -import { Router } from '@angular/router'; - -@Component({ - selector: 'volume-group-list', - templateUrl: 'volumeGroup.html', - providers: [ConfirmationService], - styleUrls: [], - animations: [] -}) -export class VolumeGroupComponent implements OnInit{ - volumeGroups=[]; - volemeOptions = []; - profileOptions = []; - currentGroup:any; - availabilityZones = []; - selectedOption :string; - selectedVolumeGroups=[]; - profileJson = {}; - showVolumeGroupDialog :boolean = false; - showModifyGroup :boolean = false; - volumeGroupForm:any; - modifyGroupForm:any; - validRule= { - 'name':'^[a-zA-Z]{1}([a-zA-Z0-9]|[_]){0,127}$' - }; - constructor( - public I18N: I18NService, - private router: Router, - private volumeGroupService : VolumeGroupService, - private fb : FormBuilder, - private profileService :ProfileService, - private confirmationService:ConfirmationService, - private availabilityZonesService:AvailabilityZonesService - ){ - this.volumeGroupForm = this.fb.group({ - "group_name":["",{validators:[Validators.required, Validators.pattern(this.validRule.name)], updateOn:'change'} ], - "description":[""], - "profile":["",Validators.required], - "zone":[""] - }); - this.modifyGroupForm = this.fb.group({ - "group_name":["",{validators:[Validators.required, Validators.pattern(this.validRule.name)], updateOn:'change'} ], - "description":[""] - }); - } - errorMessage = { - "group_name": { required: "group name is required.", pattern:"Beginning with a letter with a length of 1-128, it can contain letters / numbers / underlines."}, - "profile": { required: "profile is required."} - }; - - label = { - group_name_lable:'Group Name', - profile_label:'Profile', - description:this.I18N.keyID['sds_block_volume_descri'], - zone:this.I18N.keyID['sds_block_volume_az'] - } - - ngOnInit() { - this.volemeOptions = []; - this.getProfiles(); - this.getAZ(); - } - getAZ(){ - this.availabilityZonesService.getAZ().subscribe((azRes) => { - let AZs=azRes.json(); - let azArr = []; - if(AZs && AZs.length !== 0){ - AZs.forEach(item =>{ - let obj = {label: item, value: item}; - azArr.push(obj); - }) - } - this.availabilityZones = azArr; - }) - } - //show create volumes group - createVolumeGroup(){ - this.volumeGroupForm.reset(); - this.showVolumeGroupDialog = true; - } - ModifyVolumeGroupDisplay(volumeGroup){ - this.modifyGroupForm.reset(); - this.currentGroup = volumeGroup; - this.modifyGroupForm.controls['group_name'].setValue(this.currentGroup.name); - this.modifyGroupForm.controls['description'].setValue(""); - this.showModifyGroup = true; - } - submit(group){ - if(!this.volumeGroupForm.valid){ - for(let i in this.volumeGroupForm.controls){ - this.volumeGroupForm.controls[i].markAsTouched(); - } - return; - }else{ - let param = { - name : group.group_name, - profiles : group.profile, - description:group.description, - availabilityZone:group.zone - } - this.volumeGroupService.createVolumeGroup(param).subscribe((res) => { - this.getVolumeGroups(); - }); - } - this.showVolumeGroupDialog = false; - } - getVolumeGroups(){ - this.volumeGroupService.getVolumeGroups().subscribe((res) => { - let volumeGroups = res.json(); - if(volumeGroups && volumeGroups.length != 0){ - volumeGroups.forEach((item)=>{ - if(!item.description){ - item.description = "--"; - } - let profileName = []; - item.profiles.forEach((profileId)=>{ - profileName.push(this.profileJson[profileId]); - }); - item.profileName = profileName; - }); - } - this.volumeGroups = volumeGroups; - }); - } - getProfiles() { - this.profileService.getProfiles().subscribe((res) => { - let profiles = res.json(); - profiles.forEach(profile => { - this.profileOptions.push({ - label: profile.name, - value: profile.id - }); - this.profileJson[profile.id] = profile.name; - }); - this.getVolumeGroups(); - }); - } - deleteVolumeGroup(volumeGroup){ - this.currentGroup = volumeGroup; - let msg = "
Are you sure you want to delete the Volume Group?

[ "+ volumeGroup.name +" ]

"; - let header ="Delete Volume Group"; - let acceptLabel = "Delete"; - let warming = true; - this.confirmDialog([msg,header,acceptLabel,warming,"delete"]) - } - deleteMultiVolumeGroups(){ - let msg = "
Are you sure you want to delete the selected Volume Groups?

[ "+ this.selectedVolumeGroups.length +" Volume Group ]

"; - let header ="Delete Volume Group"; - let acceptLabel = "Delete"; - let warming = true; - this.confirmDialog([msg,header,acceptLabel,warming,"multiDelete"]) - } - modifyGroup(value){ - if(!this.modifyGroupForm.valid){ - for(let i in this.modifyGroupForm.controls){ - this.modifyGroupForm.controls[i].markAsTouched(); - } - return; - }else{ - let param = { - name:value.group_name, - description:value.description, - } - this.volumeGroupService.modifyVolumeGroup(this.currentGroup.id,param).subscribe((res) => { - this.getVolumeGroups(); - }); - } - this.showModifyGroup = false; - } - confirmDialog([msg,header,acceptLabel,warming=true,func]){ - this.confirmationService.confirm({ - message: msg, - header: header, - acceptLabel: acceptLabel, - isWarning: warming, - accept: ()=>{ - try { - if(func === "delete"){ - this.volumeGroupService.deleteVolumeGroup(this.currentGroup.id).subscribe((res) => { - this.getVolumeGroups(); - }) - }else if(func === "multiDelete"){ - this.selectedVolumeGroups.forEach(item=>{ - this.volumeGroupService.deleteVolumeGroup(item.id).subscribe((res) => { - this.getVolumeGroups(); - }) - }); - this.selectedVolumeGroups = []; - } - } - catch (e) { - console.log(e); - } - finally { - - } - }, - reject:()=>{} - }) - } - -} diff --git a/dashboard/src/app/business/block/volumeGroup.html b/dashboard/src/app/business/block/volumeGroup.html deleted file mode 100644 index 962c28dcb..000000000 --- a/dashboard/src/app/business/block/volumeGroup.html +++ /dev/null @@ -1,66 +0,0 @@ -
-
- -
-
-
- - -
- -
-
- - - - - - {{group.name}} - - - - - - - - - {{I18N.keyID['sds_block_volume_modify']}}{{I18N.keyID['sds_block_volume_delete']}} - - - - - -
- - - - - - - - - - - - -
- - - - -
- -
- - - - - - -
- - - - -
- diff --git a/dashboard/src/app/business/block/volumeGroup.module.ts b/dashboard/src/app/business/block/volumeGroup.module.ts deleted file mode 100644 index 091a352c2..000000000 --- a/dashboard/src/app/business/block/volumeGroup.module.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { NgModule, APP_INITIALIZER } from '@angular/core'; -import { VolumeGroupComponent } from './volumeGroup.component'; -import { ButtonModule, DataTableModule, InputTextModule, DialogModule,FormModule,MultiSelectModule ,DropdownModule,InputTextareaModule} from '../../components/common/api'; -import { ReactiveFormsModule, FormsModule } from '@angular/forms'; -import { HttpService } from './../../shared/service/Http.service'; -import { VolumeService ,VolumeGroupService} from './volume.service'; -import { AvailabilityZonesService } from './../resource/resource.service'; -import { ConfirmationService,ConfirmDialogModule} from '../../components/common/api'; -import { RouterModule } from '@angular/router'; - -@NgModule({ - declarations: [ VolumeGroupComponent ], - imports: [ ButtonModule, DataTableModule, InputTextModule, DialogModule,FormModule,MultiSelectModule,DropdownModule,ReactiveFormsModule,FormsModule,ConfirmDialogModule,InputTextareaModule,RouterModule], - exports: [ VolumeGroupComponent ], - providers: [ - HttpService, - VolumeService, - VolumeGroupService, - ConfirmationService, - AvailabilityZonesService - ] -}) -export class VolumeGroupModule { } diff --git a/dashboard/src/app/business/block/volumeList.component.ts b/dashboard/src/app/business/block/volumeList.component.ts deleted file mode 100644 index 30c8c0e30..000000000 --- a/dashboard/src/app/business/block/volumeList.component.ts +++ /dev/null @@ -1,367 +0,0 @@ -import { Component, OnInit, ViewContainerRef, ViewChild, Directive, ElementRef, HostBinding, HostListener } from '@angular/core'; -import { Router } from '@angular/router'; -import { I18NService, Utils } from 'app/shared/api'; -import { FormControl, FormGroup, FormBuilder, Validators, ValidatorFn, AbstractControl } from '@angular/forms'; -import { AppService } from 'app/app.service'; -import { I18nPluralPipe } from '@angular/common'; -import { trigger, state, style, transition, animate } from '@angular/animations'; -import { MenuItem ,ConfirmationService} from '../../components/common/api'; - -import { VolumeService, SnapshotService,ReplicationService} from './volume.service'; -import { ProfileService } from './../profile/profile.service'; -import { identifierModuleUrl } from '@angular/compiler'; - -let _ = require("underscore"); -@Component({ - selector: 'volume-list', - templateUrl: 'volumeList.html', - providers: [ConfirmationService], - styleUrls: [], - animations: [] -}) -export class VolumeListComponent implements OnInit { - createSnapshotDisplay = false; - createReplicationDisplay = false; - expandDisplay = false; - modifyDisplay = false; - selectVolumeSize; - newVolumeSize; - newVolumeSizeFormat; - unit:number = 1; - repPeriod : number=60; - capacityOptions = [ - { - label: 'GB', - value: 'gb' - }, - { - label: 'TB', - value: 'tb' - } - - ]; - profileOptions = [ - { - label: 'Select Profile', - value: null - } - ]; - azOption=[{label:"Secondary",value:"secondary"}]; - selectedVolumes = []; - volumes = []; - menuItems: MenuItem[]; - menuDeleDisableItems: MenuItem[]; - label = { - name: this.I18N.keyID['sds_block_volume_name'], - volume: this.I18N.keyID['sds_block_volume_title'], - description: this.I18N.keyID['sds_block_volume_descri'] - }; - snapshotFormGroup; - modifyFormGroup; - expandFormGroup; - replicationGroup; - errorMessage = { - "name": { required: "Name is required." }, - "description": { maxlength: "Max. length is 200." }, - "repName":{ required: "Name is required." }, - "profileOption":{ required: "Name is required." }, - "expandSize":{required: "Expand Capacity is required."} - }; - profiles; - selectedVolume; - - constructor( - public I18N: I18NService, - private router: Router, - private VolumeService: VolumeService, - private SnapshotService: SnapshotService, - private ProfileService: ProfileService, - private ReplicationService: ReplicationService, - private confirmationService: ConfirmationService, - private fb: FormBuilder - ) { - this.snapshotFormGroup = this.fb.group({ - "name": ["", Validators.required], - "description": ["", Validators.maxLength(200)] - }); - this.modifyFormGroup = this.fb.group({ - "name": ['', Validators.required] - }); - this.expandFormGroup = this.fb.group({ - "expandSize":[1,{validators:[Validators.required], updateOn:'change'} ], - "capacityOption":[this.capacityOptions[0] ] - }); - this.expandFormGroup.get("expandSize").valueChanges.subscribe( - (value:string)=>{ - this.newVolumeSize = parseInt(this.selectedVolume.size) + parseInt(value)*this.unit; - this.newVolumeSizeFormat = Utils.getDisplayGBCapacity(this.newVolumeSize); - } - ); - this.expandFormGroup.get("capacityOption").valueChanges.subscribe( - (value:string)=>{ - this.unit =(value === "tb" ? 1024: 1); - this.newVolumeSize = parseInt(this.selectedVolume.size) + parseInt(this.expandFormGroup.value.expandSize)*this.unit; - this.newVolumeSizeFormat = Utils.getDisplayGBCapacity(this.newVolumeSize); - } - ) - this.replicationGroup = this.fb.group({ - "repName": ['',{validators:[Validators.required], updateOn:'change'}], - "az": [this.azOption[0]], - "profileOption":['',{validators:[Validators.required], updateOn:'change'}] - }); - - } - - ngOnInit() { - this.menuItems = [ - { - "label": this.I18N.keyID['sds_block_volume_modify'], - command: () => { - this.modifyDisplay = true; - }, - disabled:false - }, - { - "label": this.I18N.keyID['sds_block_volume_expand'], - command: () => { - this.expandDisplay = true; - this.expandFormGroup.reset(); - this.expandFormGroup.controls["expandSize"].setValue(1); - this.unit = 1; - }, - disabled:false - }, - { - "label": this.I18N.keyID['sds_block_volume_delete'], - command: () => { - if (this.selectedVolume && this.selectedVolume.id) { - this.deleteVolumes(this.selectedVolume); - } - }, - disabled:false - } - ]; - this.menuDeleDisableItems = [ - { - "label": this.I18N.keyID['sds_block_volume_modify'], - command: () => { - this.modifyDisplay = true; - }, - disabled:false - }, - { - "label": this.I18N.keyID['sds_block_volume_expand'], - command: () => { - this.expandDisplay = true; - this.expandFormGroup.reset(); - this.expandFormGroup.controls["expandSize"].setValue(1); - this.unit = 1; - }, - disabled:false - }, - { - "label": this.I18N.keyID['sds_block_volume_delete'], - command: () => { - if (this.selectedVolume && this.selectedVolume.id) { - this.deleteVolumes(this.selectedVolume); - } - }, - disabled:true - } - ]; - - this.getProfiles() - } - - getVolumes() { - this.selectedVolumes = []; - this.VolumeService.getVolumes().subscribe((res) => { - let volumes = res.json(); - this.ReplicationService.getAllReplicationsDetail().subscribe((resRep)=>{ - let replications = resRep.json(); - volumes.map((item)=> - { - let _profile = this.profiles.filter((profile,index,arr)=>{ - return profile.id == item.profileId; - })[0]; - item['profileName'] = _profile != undefined ? _profile.name : "--"; - item['isDisableRep'] = false; - replications.map((rep)=>{ - if(rep.primaryVolumeId == item.id || rep.secondaryVolumeId == item.id){ - item['isDisableRep'] = true; - } - }); - item.size = Utils.getDisplayGBCapacity(item.size); - } - ); - this.SnapshotService.getSnapshots().subscribe((resSnap)=>{ - let snaps = resSnap.json(); - volumes.map((item)=> - { - item['disabled'] = false; - snaps.map((snap)=>{ - if(snap.volumeId == item.id){ - item['disabled'] = true; - } - }); - } - ); - this.volumes = volumes; - }); - }); - }); - } - - getProfiles() { - this.ProfileService.getProfiles().subscribe((res) => { - this.profiles = res.json(); - this.profiles.forEach(profile => { - this.profileOptions.push({ - label: profile.name, - value: profile.id - }); - }); - - this.getVolumes(); - }); - } - - batchDeleteVolume() { - this.selectedVolumes.forEach(volume => { - this.deleteVolume(volume.id); - }); - } - - deleteVolumeById(id) { - this.deleteVolume(id); - } - - deleteVolume(id) { - this.VolumeService.deleteVolume(id).subscribe((res) => { - this.getVolumes(); - }); - } - - createSnapshot() { - if(!this.snapshotFormGroup.valid){ - for(let i in this.snapshotFormGroup.controls){ - this.snapshotFormGroup.controls[i].markAsTouched(); - } - return; - } - let param = { - name: this.snapshotFormGroup.value.name, - volumeId: this.selectedVolume.id, - description: this.snapshotFormGroup.value.description - } - this.SnapshotService.createSnapshot(param).subscribe((res) => { - this.createSnapshotDisplay = false; - this.getProfiles(); - }); - } - - returnSelectedVolume(selectedVolume, dialog) { - if (dialog === 'snapshot') { - this.snapshotFormGroup.reset(); - this.createSnapshotDisplay = true; - } else if (dialog === 'replication') { - this.createReplicationDisplay = true; - } - let unit = selectedVolume.size.includes("GB") ? 1 : 10; - - this.selectedVolume = selectedVolume; - this.replicationGroup.reset(); - this.replicationGroup.controls["repName"].setValue(selectedVolume.name+"-replication"); - this.replicationGroup.controls["az"].setValue(this.azOption[0]); - this.selectVolumeSize = parseInt(selectedVolume.size)*unit; - } - - modifyVolume() { - let param = { - name: this.modifyFormGroup.value.name - }; - this.VolumeService.modifyVolume(this.selectedVolume.id, param).subscribe((res) => { - this.getVolumes(); - this.modifyDisplay = false; - }); - } - expandVolume(){ - if(!this.expandFormGroup.valid){ - for(let i in this.expandFormGroup.controls){ - this.expandFormGroup.controls[i].markAsTouched(); - } - return; - } - - let param = { - "newSize": this.newVolumeSize - } - this.VolumeService.expandVolume(this.selectedVolume.id, param).subscribe((res) => { - this.getVolumes(); - this.expandDisplay = false; - }); - } - createReplication(){ - if(!this.replicationGroup.valid){ - for(let i in this.replicationGroup.controls){ - this.replicationGroup.controls[i].markAsTouched(); - } - return; - } - let param = { - "name":this.replicationGroup.value.repName , - "size": Number(this.selectedVolume.size.replace(" GB","")), - "availabilityZone": this.replicationGroup.value.az.value, - "profileId": this.replicationGroup.value.profileOption, - } - this.VolumeService.createVolume(param).subscribe((res) => { - let param = { - "name":this.replicationGroup.value.repName , - "primaryVolumeId": this.selectedVolume.id, - "availabilityZone": this.replicationGroup.value.az.value, - "profileId": this.replicationGroup.value.profileOption, - "replicationMode":"async", - "replicationPeriod":Number(this.repPeriod), - "secondaryVolumeId":res.json().id - } - this.createReplicationDisplay = false; - this.ReplicationService.createReplication(param).subscribe((res) => { - this.getVolumes(); - }, - error=>{ - this.getVolumes(); - }); - }); - } - deleteVolumes(volumes){ - let arr=[], msg; - if(_.isArray(volumes)){ - volumes.forEach((item,index)=> { - arr.push(item.id); - }) - msg = "
Are you sure you want to delete the selected volumes?

[ "+ volumes.length +" Volumes ]

"; - }else{ - arr.push(volumes.id); - msg = "
Are you sure you want to delete the volume?

[ "+ volumes.name +" ]

"; - } - - this.confirmationService.confirm({ - message: msg, - header: this.I18N.keyID['sds_block_volume_deleVolu'], - acceptLabel: this.I18N.keyID['sds_block_volume_delete'], - isWarning: true, - accept: ()=>{ - arr.forEach((item,index)=> { - this.deleteVolume(item) - }) - - }, - reject:()=>{} - }) - - } - - tablePaginate() { - this.selectedVolumes = []; - } -} diff --git a/dashboard/src/app/business/block/volumeList.html b/dashboard/src/app/business/block/volumeList.html deleted file mode 100644 index 66584d949..000000000 --- a/dashboard/src/app/business/block/volumeList.html +++ /dev/null @@ -1,159 +0,0 @@ -
-
- - -
-
-
- - -
- -
-
- - - - - {{volume.name}} - - - - - - - - - {{I18N.keyID['sds_block_volume_createsna']}} - {{I18N.keyID['sds_block_volume_createrep']}} - - - - - - -
- - {{selectedVolume.name}} - - - - - - - - - -
- - - - - -
- - -
- - - -
- - - - -
- - -
- - {{selectedVolume.name}} - - - {{selectedVolume.size}} - - -
- - -
-
- - {{newVolumeSizeFormat}} - -
- - - - -
- - -
-
-
-
-
-
- -
- {{selectedVolume && selectedVolume.name}} -
-
- - default -
-
-
-
-
-
-
-
-
-
- Period - = - - Minutes -
- -
-
-
-
-
-
-
-
- -
-
-
-
-
-
- - - - -
- -
-
- -
- -
-
-
-
-
-
-
- - - - -
- diff --git a/dashboard/src/app/business/block/volumeList.module.ts b/dashboard/src/app/business/block/volumeList.module.ts deleted file mode 100644 index da627be72..000000000 --- a/dashboard/src/app/business/block/volumeList.module.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { NgModule, APP_INITIALIZER } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { ReactiveFormsModule, FormsModule } from '@angular/forms'; -import { VolumeListComponent } from './volumeList.component'; -import { ButtonModule, DataTableModule, DropMenuModule, DialogModule, FormModule, InputTextModule, InputTextareaModule, DropdownModule ,ConfirmationService,ConfirmDialogModule} from '../../components/common/api'; - -import { HttpService } from './../../shared/service/Http.service'; -import {VolumeService, SnapshotService, ReplicationService} from './volume.service'; -import { ProfileService } from './../profile/profile.service'; -import { RouterModule } from '@angular/router'; - -@NgModule({ - declarations: [ VolumeListComponent ], - imports: [ - CommonModule, - ReactiveFormsModule, - FormsModule, - ButtonModule, - InputTextModule, - InputTextareaModule, - DataTableModule, - DropdownModule, - DropMenuModule, - DialogModule, - FormModule, - ConfirmDialogModule, - RouterModule - ], - exports: [ VolumeListComponent ], - providers: [ - HttpService, - VolumeService, - SnapshotService, - ProfileService, - ReplicationService, - ConfirmationService - ] -}) -export class VolumeListModule { } diff --git a/dashboard/src/app/business/cloud/cloud-service-item/cloud-service-item.component.html b/dashboard/src/app/business/cloud/cloud-service-item/cloud-service-item.component.html deleted file mode 100644 index 6d63c84d9..000000000 --- a/dashboard/src/app/business/cloud/cloud-service-item/cloud-service-item.component.html +++ /dev/null @@ -1,13 +0,0 @@ -
-
- -
-

{{cloudService.name}}

-
-
region:{{cloudService.region}}
-
type:{{cloudService.type}}
-
- -
-
-
\ No newline at end of file diff --git a/dashboard/src/app/business/cloud/cloud-service-item/cloud-service-item.component.scss b/dashboard/src/app/business/cloud/cloud-service-item/cloud-service-item.component.scss deleted file mode 100644 index 8fa4efde1..000000000 --- a/dashboard/src/app/business/cloud/cloud-service-item/cloud-service-item.component.scss +++ /dev/null @@ -1,15 +0,0 @@ -.img-div { - width: 217px; - height: 153px; - position: relative; - background-image: url(../../../../assets/business/images/cloud_service/u2309.png); - text-align: center; -} - -.img-center { - height: 60px; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -40%); -} \ No newline at end of file diff --git a/dashboard/src/app/business/cloud/cloud-service-item/cloud-service-item.component.spec.ts b/dashboard/src/app/business/cloud/cloud-service-item/cloud-service-item.component.spec.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/dashboard/src/app/business/cloud/cloud-service-item/cloud-service-item.component.ts b/dashboard/src/app/business/cloud/cloud-service-item/cloud-service-item.component.ts deleted file mode 100644 index 70ae7a471..000000000 --- a/dashboard/src/app/business/cloud/cloud-service-item/cloud-service-item.component.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Component, OnInit, Input } from '@angular/core'; - -@Component({ - selector: 'app-cloud-service-item', - templateUrl: './cloud-service-item.component.html', - styleUrls: ['./cloud-service-item.component.scss'] -}) -export class CloudServiceItemComponent implements OnInit { - - @Input() cloudService; - - constructor() { } - - ngOnInit() { - } - - deleteCloud(name){ - alert("delete "+name); - //删除某个云 - } - -} diff --git a/dashboard/src/app/business/cloud/cloud.component.html b/dashboard/src/app/business/cloud/cloud.component.html deleted file mode 100644 index 40a9ccf9f..000000000 --- a/dashboard/src/app/business/cloud/cloud.component.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/dashboard/src/app/business/cloud/cloud.component.scss b/dashboard/src/app/business/cloud/cloud.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/dashboard/src/app/business/cloud/cloud.component.ts b/dashboard/src/app/business/cloud/cloud.component.ts deleted file mode 100644 index 616b22281..000000000 --- a/dashboard/src/app/business/cloud/cloud.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Component, OnInit } from '@angular/core'; - -@Component({ - selector: 'app-cloud', - templateUrl: './cloud.component.html', - styleUrls: ['./cloud.component.scss'] -}) -export class CloudComponent implements OnInit { - - constructor() { } - - ngOnInit() { - } - -} diff --git a/dashboard/src/app/business/cloud/cloud.module.ts b/dashboard/src/app/business/cloud/cloud.module.ts deleted file mode 100644 index eec027959..000000000 --- a/dashboard/src/app/business/cloud/cloud.module.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { RouterModule } from '@angular/router'; -import { FormsModule } from '@angular/forms'; - -import { ButtonModule,MessageModule,TabViewModule,DialogModule,DropdownModule } from '../../components/common/api'; - -import { CloudComponent } from './cloud.component'; -import { RegistryComponent } from './registry/registry.component'; -import { ReplicationComponent } from './replication/replication.component'; -import { MigrationComponent } from './migration/migration.component'; -import { CloudServiceItemComponent } from './cloud-service-item/cloud-service-item.component'; - -let routers = [{ - path: '', - component: CloudComponent -}] - -@NgModule({ - imports: [ - CommonModule, - RouterModule.forChild(routers), - FormsModule, - ButtonModule, - MessageModule, - TabViewModule, - DialogModule, - DropdownModule - ], - declarations: [ - CloudComponent, - RegistryComponent, - ReplicationComponent, - MigrationComponent, - CloudServiceItemComponent - ] -}) -export class CloudModule { } diff --git a/dashboard/src/app/business/cloud/migration/migration.component.html b/dashboard/src/app/business/cloud/migration/migration.component.html deleted file mode 100644 index 6b120b252..000000000 --- a/dashboard/src/app/business/cloud/migration/migration.component.html +++ /dev/null @@ -1,3 +0,0 @@ -

- migration works! -

diff --git a/dashboard/src/app/business/cloud/migration/migration.component.scss b/dashboard/src/app/business/cloud/migration/migration.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/dashboard/src/app/business/cloud/migration/migration.component.ts b/dashboard/src/app/business/cloud/migration/migration.component.ts deleted file mode 100644 index 26ce78ea3..000000000 --- a/dashboard/src/app/business/cloud/migration/migration.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Component, OnInit } from '@angular/core'; - -@Component({ - selector: 'app-migration', - templateUrl: './migration.component.html', - styleUrls: ['./migration.component.scss'] -}) -export class MigrationComponent implements OnInit { - - constructor() { } - - ngOnInit() { - } - -} diff --git a/dashboard/src/app/business/cloud/registry/registry.component.html b/dashboard/src/app/business/cloud/registry/registry.component.html deleted file mode 100644 index 03de8009d..000000000 --- a/dashboard/src/app/business/cloud/registry/registry.component.html +++ /dev/null @@ -1,41 +0,0 @@ -
-
- -
-
-
- -
-
-
-
- - - -
-
- {{label.name}} - -
-
- {{label.type}} - -
-
- {{label.region}} - -
-
- {{label.accessKey}} - -
-
- {{label.secretKey}} - -
-
- - - - -
\ No newline at end of file diff --git a/dashboard/src/app/business/cloud/registry/registry.component.scss b/dashboard/src/app/business/cloud/registry/registry.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/dashboard/src/app/business/cloud/registry/registry.component.ts b/dashboard/src/app/business/cloud/registry/registry.component.ts deleted file mode 100644 index ca8367cd8..000000000 --- a/dashboard/src/app/business/cloud/registry/registry.component.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { Component, OnInit } from '@angular/core'; - -@Component({ - selector: 'app-registry', - templateUrl: './registry.component.html', - styleUrls: ['./registry.component.scss'] -}) -export class RegistryComponent implements OnInit { - - registryServiceDisplay = false; - label; - cloudServices = []; - serviceTypeOptions = []; - regionOptions = []; - selectedType = ''; - selectedRegion = ''; - - - constructor() { } - - ngOnInit() { - //界面文本 - this.label = { - name: 'Service Name', - type: 'Service Type', - region: 'Region', - accessKey: 'AWS Access Key', - secretKey: 'Secret Key' - }; - - //type下拉框的项 - this.serviceTypeOptions = [ - { label: 'AWS S3', value: { id: 0, name: 'New York', code: 'NY' } }, - { label: 'Microsoft Azure Blob Storage', value: { id: 1, name: 'New York', code: 'NY' } }, - { label: 'Huawei OBS', value: { id: 2, name: 'Rome', code: 'RM' } } - ]; - - //region下拉框的项 - this.regionOptions = [ - { label: 'CN North', value: { id: 0, name: 'New York', code: 'NY' } }, - { label: 'CN South', value: { id: 1, name: 'New York', code: 'NY' } }, - { label: 'Huawei OBS', value: { id: 2, name: 'Rome', code: 'RM' } } - ]; - - //查询回来已有的云服务 - this.cloudServices = [ - { - name:'service_for_analytics', - region:'EU(Paris)', - type:'AWS S3' - }, - { - name:'service_for_finance', - region:'CN North', - type:'Huawei OBS' - }, - { - name:'service_for_media', - region:'North Europe', - type:'Microsoft Azure Blob Storage' - } - ]; - - - - - - } - - showRegistryService() { - this.registryServiceDisplay = true; - } - - registryCloud() { - //http注册新的云 - alert("registry"); - } - - getServiceType() { - //http获取service type - } - - getRegions() { - //http获取regions - } - - getCloudServices() { - //http获取cloudServices - } -} diff --git a/dashboard/src/app/business/cloud/replication/replication.component.html b/dashboard/src/app/business/cloud/replication/replication.component.html deleted file mode 100644 index ac4e19a5b..000000000 --- a/dashboard/src/app/business/cloud/replication/replication.component.html +++ /dev/null @@ -1,29 +0,0 @@ - \ No newline at end of file diff --git a/dashboard/src/app/business/cloud/replication/replication.component.scss b/dashboard/src/app/business/cloud/replication/replication.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/dashboard/src/app/business/cloud/replication/replication.component.ts b/dashboard/src/app/business/cloud/replication/replication.component.ts deleted file mode 100644 index b6b2efd92..000000000 --- a/dashboard/src/app/business/cloud/replication/replication.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Component, OnInit } from '@angular/core'; - -@Component({ - selector: 'app-replication', - templateUrl: './replication.component.html', - styleUrls: ['./replication.component.scss'] -}) -export class ReplicationComponent implements OnInit { - - constructor() { } - - ngOnInit() { - } - -} diff --git a/dashboard/src/app/business/home/home.component.html b/dashboard/src/app/business/home/home.component.html deleted file mode 100644 index 3b4104d07..000000000 --- a/dashboard/src/app/business/home/home.component.html +++ /dev/null @@ -1,125 +0,0 @@ -
-
-
-

{{I18N.keyID["sds_home_overvew"]}}

-

{{I18N.keyID["sds_home_update"]}}

-
-
-
-
-
-
- -
-
- -
-
-
-
-
- -
-
- -
-
-
-
-
-
- -
-
-
- -
-
- -
-
- -
-
-
- - -
-
-
-
-
-

{{I18N.keyID["Capacity"]}}

-
-
-
{{I18N.keyID["sds_home_block_capacity"]}}
-

{{I18N.keyID["sds_home_update"]}}

-
- -
-
-
-
-
{{I18N.keyID["sds_home_top5"]}}
-

{{I18N.keyID["sds_home_update"]}}

- -
-
-
-
- -
-
-
-

Overview

-

Updated 5 minutes ago

-
-
- - -
-
-
- -
-
- -
-
- -
-
-
-
-
- -
-

Trend

-
-
-
Trend of block storage capacity growth
-

Updated 5 minutes ago

-
- -
-
-
-
-
Trend of quantity of volumes growth
-

Updated 5 minutes ago

-
- -
-
-
-
-
diff --git a/dashboard/src/app/business/home/home.component.scss b/dashboard/src/app/business/home/home.component.scss deleted file mode 100644 index 07ab7ba06..000000000 --- a/dashboard/src/app/business/home/home.component.scss +++ /dev/null @@ -1,43 +0,0 @@ -@import "./../scss-variable"; -.img-item-div-height { - height: 258px; - margin: 2em; -} - -.statisBg{ - background: #f3f6f7; - border-radius: 12px; -} - -.img-item-div { - padding: 2em; - border-radius: 10px; - // background-color: rgb(208, 232, 240); -} - -.home-img-item-margin { - margin: 2em 0; -} - -.user-img-item-margin { - margin-top: 3em; -} - -.header-h2-title-font { - font-size: 2em; - padding: 0.5em 0.25em; -} - -.home-font-color-class { - color: map-get($color-title, primary); - padding-bottom: .30rem; -} - -.header-p-text { - padding: 0 0.5em; - // color: map-get($color-title, secondary); -} - -.capacity-secondary { - margin: 1em 0; -} \ No newline at end of file diff --git a/dashboard/src/app/business/home/home.component.ts b/dashboard/src/app/business/home/home.component.ts deleted file mode 100644 index 5d3e7551e..000000000 --- a/dashboard/src/app/business/home/home.component.ts +++ /dev/null @@ -1,271 +0,0 @@ -import { Component, OnInit, ViewContainerRef, ViewChild, Directive, ElementRef, HostBinding, HostListener } from '@angular/core'; -import { Http } from '@angular/http'; -import { ParamStorService } from 'app/shared/api'; -import { ProfileService } from 'app/business/profile/profile.service'; -import { Observable } from "rxjs/Rx"; -import { I18NService } from 'app/shared/api'; - -@Component({ - templateUrl: './home.component.html', - styleUrls: [ - './home.component.scss' - ] -}) -export class HomeComponent implements OnInit { - items = []; - chartDatas; - chartDatasbar; - option; - chartBarOpion; - profileOptions = []; - lineData_nums; - lineData_capacity; - showAdminStatis = true; - tenants =[]; - constructor( - private http: Http, - private paramStor: ParamStorService, - private profileService: ProfileService, - private I18N: I18NService, - ) { } - - ngOnInit() { - if(this.paramStor.CURRENT_USER().split("|")[0] == "admin"){ - this.showAdminStatis = true; - this.getCountData(); - }else{ - this.showAdminStatis = false; - this.getTenantCountData(); - } - - this.items = [ - { - countNum: 0, - label: this.I18N.keyID["sds_home_tenants"] - }, - { - countNum:0, - label: this.I18N.keyID["sds_home_users"] - }, - { - countNum: 0, - label: this.I18N.keyID["sds_home_storages"] - }, - { - countNum: 0, - label: this.I18N.keyID["sds_home_pools"] - }, - { - countNum: 0, - label: this.I18N.keyID["sds_home_volumes"] - }, - { - countNum: 0, - label:this.I18N.keyID["sds_home_snapshots"] - }, - { - countNum: 0, - label: this.I18N.keyID["sds_home_replications"] - }, - { - countNum: 0, - label: "Cross-Region Replications" - }, - { - countNum: 0, - label: "Cross-Region Migrations" - } - ]; - - - this.option = { - cutoutPercentage: 80, - title: { - display: false, - text: 'My Title', - fontSize: 12 - }, - legend: { - labels: { - boxWidth: 12 - }, - display: true, - position: 'right', - fontSize: 12 - } - }; - this.chartBarOpion= { - scales: { - yAxes: [{ - ticks: { - min: 0, - } - }] - }, - legend: { - display: false - } - } - - this.lineData_capacity = { - labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], - datasets: [ - { - label: 'Capacity(GB)', - data: [10, 11, 20, 160, 156, 195, 200], - fill: false, - borderColor: '#4bc0c0' - } - ] - } - - this.lineData_nums = { - labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], - datasets: [ - { - label: 'Volumes', - data: [10, 23, 40, 38, 86, 107, 190], - fill: false, - borderColor: '#565656' - } - ] - } - - } - - getProfiles() { - this.profileService.getProfiles().subscribe((res) => { - let profiles = res.json(); - profiles.forEach(profile => { - this.profileOptions.push({ - name: profile.name, - id: profile.id, - capacity: 0 - }) - }); - }); - } - - listTenants() { - let request: any = { params:{} }; - request.params = { - "domain_id": "default" - } - - this.http.get("/v3/projects", request).subscribe((res) => { - - this.items[0].countNum = res.json().projects.length; - this.tenants = res.json().projects; - this.tenants.forEach((item, i)=>{ - if(item.name == "admin"){ - this.getAllvolumes(item.id, this.tenants.length - 1); - this.getAllSnapshots(item.id); - this.getAllReplications(item.id); - this.getAllPools(item.id); - this.getAllDocks(item.id); - } - }); - - - }); - } - listUsers(){ - let request: any = { params:{} }; - request.params = { - "domain_id": "default" - } - this.http.get("/v3/users", request).subscribe((res) => { - this.items[1].countNum = res.json().users.length; - }); - } - getAllvolumes(projectId, index?){ - let url = 'v1beta/'+projectId+'/block/volumes'; - this.http.get(url).subscribe((res)=>{ - this.items[4].countNum = this.items[4].countNum + res.json().length; - - if(this.showAdminStatis){ - res.json().forEach(volume => { - this.profileOptions.forEach(profile => { - if(volume.profileId == profile.id){ - profile.capacity = profile.capacity + volume.size; - } - }); - }); - - if(index == (this.tenants.length-1)){ - let [chartData, chartLabel] = [[],[]]; - this.profileOptions.forEach(ele=>{ - chartData.push(ele.capacity); - chartLabel.push(ele.name); - }); - - this.chartDatasbar = { - labels: chartLabel, - datasets: [{ - label:"Used Capacity (GB)", - backgroundColor: '#42A5F5', - data: chartData - }] - } - } - } - }); - } - getAllSnapshots(projectId){ - let url = 'v1beta/'+projectId+'/block/snapshots'; - this.http.get(url).subscribe((res)=>{ - this.items[5].countNum = this.items[5].countNum + res.json().length; - }); - } - getAllReplications(projectId){ - let url = 'v1beta/'+projectId+'/block/replications'; - this.http.get(url).subscribe((res)=>{ - if(res.json()){ - this.items[6].countNum = this.items[6].countNum + res.json().length; - } - }); - } - getAllPools(projectId){ - let url = 'v1beta/'+projectId+'/pools'; - this.http.get(url).subscribe((res)=>{ - this.items[3].countNum = this.items[3].countNum + res.json().length; - - let [storCapacityTotal, storCapacityFree]=[0,0]; - res.json().forEach(element => { - storCapacityTotal = storCapacityTotal + element.totalCapacity; - storCapacityFree = storCapacityFree + element.freeCapacity; - }); - - this.chartDatas = { - labels: [this.I18N.keyID["sds_home_used_capacity"] + " (GB)",this.I18N.keyID["sds_home_free_capacity"] + " (GB)"], - datasets: [ - { - label: 'high_capacity', - data: [(storCapacityTotal-storCapacityFree), storCapacityFree], - backgroundColor: [ - "#438bd3", - "rgba(224, 224, 224, .5)" - ] - }] - }; - }); - } - getAllDocks(projectId){ - let url = 'v1beta/'+projectId+'/docks'; - this.http.get(url).subscribe((res)=>{ - this.items[2].countNum = this.items[2].countNum + res.json().length; - }); - } - getCountData(){ - this.getProfiles(); - this.listTenants(); - this.listUsers(); - } - - getTenantCountData(){ - let tenantId = this.paramStor.CURRENT_TENANT().split("|")[1]; - this.getAllvolumes(tenantId); - this.getAllSnapshots(tenantId); - this.getAllReplications(tenantId); - } -} diff --git a/dashboard/src/app/business/home/home.module.ts b/dashboard/src/app/business/home/home.module.ts deleted file mode 100644 index 62667a672..000000000 --- a/dashboard/src/app/business/home/home.module.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { NgModule, APP_INITIALIZER } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { HomeComponent } from './home.component'; -import { ImgItemComponent } from './imgItem.component/imgItem.component'; -import { ProfileService } from 'app/business/profile/profile.service'; -import { HttpService } from 'app/shared/service/Http.service'; - -import { RouterModule } from '@angular/router'; -import { ButtonModule, ChartModule } from '../../components/common/api'; - -let routers = [{ - path: '', - component: HomeComponent -}] - -@NgModule({ - declarations: [ - HomeComponent, - ImgItemComponent, - ], - imports: [ - RouterModule.forChild(routers), ButtonModule, - CommonModule, - ChartModule - ], - providers: [HttpService, ProfileService] -}) -export class HomeModule { } \ No newline at end of file diff --git a/dashboard/src/app/business/home/imgItem.component/imgItem.component.html b/dashboard/src/app/business/home/imgItem.component/imgItem.component.html deleted file mode 100644 index 44dfee26c..000000000 --- a/dashboard/src/app/business/home/imgItem.component/imgItem.component.html +++ /dev/null @@ -1,10 +0,0 @@ -
-
- -
-
-
{{item.countNum}}
-
{{item.label}}
-
-
-
\ No newline at end of file diff --git a/dashboard/src/app/business/home/imgItem.component/imgItem.component.scss b/dashboard/src/app/business/home/imgItem.component/imgItem.component.scss deleted file mode 100644 index 53ab0a516..000000000 --- a/dashboard/src/app/business/home/imgItem.component/imgItem.component.scss +++ /dev/null @@ -1,13 +0,0 @@ -@import "./../../scss-variable"; -.img-item-float-class { - float: left; -} - -.img-width { - width: 80px; -} - -.title-font-class { - color: map-get($color-primary, normal); - font-size: 2em; -} diff --git a/dashboard/src/app/business/home/imgItem.component/imgItem.component.ts b/dashboard/src/app/business/home/imgItem.component/imgItem.component.ts deleted file mode 100644 index 1542cf100..000000000 --- a/dashboard/src/app/business/home/imgItem.component/imgItem.component.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Component, OnInit, ViewContainerRef, ViewChild, Directive, ElementRef, HostBinding, HostListener,Input } from '@angular/core'; -import { Http } from '@angular/http'; - -@Component({ - selector: 'img-item', - templateUrl: './imgItem.component.html', - styleUrls: [ - './imgItem.component.scss' - ] -}) -export class ImgItemComponent implements OnInit{ - @Input() item; - - - constructor( - private http: Http - ){} - - ngOnInit() { - } -} diff --git a/dashboard/src/app/business/identity/identity.component.ts b/dashboard/src/app/business/identity/identity.component.ts deleted file mode 100644 index b3855ea97..000000000 --- a/dashboard/src/app/business/identity/identity.component.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Router } from '@angular/router'; -import { Component, OnInit, ViewContainerRef, ViewChild, Directive, ElementRef, HostBinding, HostListener } from '@angular/core'; -import { I18NService } from 'app/shared/api'; -import { AppService } from 'app/app.service'; -import { trigger, state, style, transition, animate} from '@angular/animations'; -import { I18nPluralPipe } from '@angular/common'; - -@Component({ - templateUrl: './identity.html', - styleUrls: [ - - ], - animations: [ - trigger('overlayState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]), - - trigger('notificationTopbar', [ - state('hidden', style({ - height: '0', - opacity: 0 - })), - state('visible', style({ - height: '*', - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]) - ] -}) -export class IdentityComponent implements OnInit{ - constructor( - public I18N: I18NService, - // private router: Router - ){} - - ngOnInit() { - - } -} diff --git a/dashboard/src/app/business/identity/identity.html b/dashboard/src/app/business/identity/identity.html deleted file mode 100644 index 54a80ec44..000000000 --- a/dashboard/src/app/business/identity/identity.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/dashboard/src/app/business/identity/identity.module.ts b/dashboard/src/app/business/identity/identity.module.ts deleted file mode 100644 index dd40892b6..000000000 --- a/dashboard/src/app/business/identity/identity.module.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { NgModule, APP_INITIALIZER } from '@angular/core'; -import { IdentityComponent } from './identity.component'; -import { RouterModule } from '@angular/router'; -import { TabViewModule } from '../../components/common/api'; -import { TenantListModule } from './tenantList.module'; -import { UserListModule } from './userList.module'; - -let routers = [{ - path: '', - component: IdentityComponent -}] - -@NgModule({ - declarations: [ - IdentityComponent - ], - imports: [ - RouterModule.forChild(routers), - TenantListModule, - UserListModule, - TabViewModule - ], - providers: [] -}) -export class IdentityModule { } \ No newline at end of file diff --git a/dashboard/src/app/business/identity/tenantDetail/tenantDetail.component.ts b/dashboard/src/app/business/identity/tenantDetail/tenantDetail.component.ts deleted file mode 100644 index f26c08c2c..000000000 --- a/dashboard/src/app/business/identity/tenantDetail/tenantDetail.component.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { Component, Input, OnInit, ViewContainerRef, ViewChild, Directive, ElementRef, HostBinding, HostListener } from '@angular/core'; -import { Http } from '@angular/http'; -import { I18NService, Utils } from 'app/shared/api'; -import { AppService } from 'app/app.service'; -import { ParamStorService } from 'app/shared/api'; -import { I18nPluralPipe } from '@angular/common'; -import { trigger, state, style, transition, animate } from '@angular/animations'; -import { MenuItem, ConfirmationService} from '../../../components/common/api'; - -@Component({ - selector: 'tenant-detail', - templateUrl: 'tenantDetail.html', - styleUrls: ['tenantDetail.scss'], - providers: [ConfirmationService], - animations: [] -}) -export class TenantDetailComponent implements OnInit { - @Input() projectID; - @Input() projectName; - @Input() isDetailFinished: Boolean; - addUserDisplay: boolean=false; - userfilter: string=""; - projectGroups = []; - users = []; - popSelectedUsers; - allUsers; - - statistics_volumeSnapshots: string; - statistics_volumes: string; - statistics_capacity: string; - - constructor( - private http: Http, - private confirmationService: ConfirmationService, - private paramStor: ParamStorService, - public I18N: I18NService, - // private router: Router - ) { } - - ngOnInit() { - this.listProjectGroup(); - this.projectResources(); - } - - projectResources(){ - this.http.get("/v1beta/"+ this.projectID +"/block/volumes").subscribe((res)=>{ - let originCapacity = 0; - res.json().map(ele => { - originCapacity += ele.size; - }) - this.statistics_volumes = res.json().length; - this.statistics_capacity = Utils.getDisplayGBCapacity(originCapacity); - }) - - this.http.get("/v1beta/"+ this.projectID +"/block/snapshots").subscribe((res)=>{ - this.statistics_volumeSnapshots = res.json().length; - }) - } - - listProjectGroup(){ - this.http.get("/v3/role_assignments?scope.project.id="+ this.projectID).subscribe((res)=>{ - let arr = res.json().role_assignments; - let newarr = []; - let roles=[]; - - // get roles - let reqRole: any = { params:{} }; - this.http.get("/v3/roles", reqRole).subscribe((roleRES) => { - let currentRoleName = this.projectName == "admin" ? "admin" : (this.projectName == "service" ? "service" : "Member"); - - roleRES.json().roles.forEach((item, index) => { - if(item.name == currentRoleName){ // more role can be expand - let roleJson = {}; - roleJson["id"] = item.id; - roleJson["name"] = item.name; - roles.push(roleJson); - } - }) - - roles.forEach((item, index)=>{ - arr.forEach(ele => { - if(ele.role.id == item.id){ - ele.role["name"] = item.name; - newarr.push(ele); - } - }); - }) - - newarr.forEach((item, index) => { - if(item.group){ - let groupJson = {}; - groupJson["groupid"] = item.group.id; - groupJson["grouprole"] = item.role - this.projectGroups.push(groupJson); - } - }); - - this.listUsers(); - }) - }) - } - - showAddUsers(){ - this.addUserDisplay = true; - this.listAllUsers(); - } - - addUsers(){ - - let group_id; - this.projectGroups.forEach((item)=>{ - if(item.grouprole.name == "Member"){ - group_id = item.groupid; - } - }) - - this.popSelectedUsers.forEach((user, i) => { - let request: any = {}; - this.http.put("/v3/groups/"+ group_id +"/users/"+ user.id, request).subscribe((r) => { - if(i == (this.popSelectedUsers.length-1)){ - this.listUsers(); - this.addUserDisplay = false; - } - }) - }); - - } - - listAllUsers(){ - this.popSelectedUsers = []; - this.allUsers = []; - let request: any = { params:{} }; - request.params = { - "domain_id": "default" - } - - if(this.userfilter != ""){ - request.params["name"] = this.userfilter; - } - - this.http.get("/v3/users", request).subscribe((res) => { - let newarr = []; - res.json().users.map((item, index) => { - item["description"] = item.description == '' ? '--' : item.description; - newarr.push(item); - }); - - //Filter added users - if(this.users.length > 0){ - this.users.forEach((addedUser) => { - this.allUsers = newarr.filter((user, idx, arr)=>{ - return (user.name != 'admin' && user.name != 'opensds' && user.name != addedUser.name); - }) - }) - }else{ - this.allUsers = newarr.filter((user, idx, arr)=>{ - return (user.name != 'admin' && user.name != 'opensds'); - }) - } - - }); - } - - listUsers(){ - this.users = []; - this.isDetailFinished = false; - this.projectGroups.forEach((item, index)=>{ - let request: any = { params:{} }; - this.http.get("/v3/groups/"+ item.groupid +"/users", request).subscribe((userRES)=>{ - userRES.json().users.forEach((ele) => { - ele["role"] = item.grouprole.name; - ele["description"] = ele.description == '' ? '--' : ele.description; - this.users.push(ele); - }); - - this.isDetailFinished = true; - }) - }) - - } - - removeUser(user){ - let group_id; - this.projectGroups.forEach((item)=>{ - if(item.grouprole.name == user.role){ - group_id = item.groupid; - } - }) - - let msg = "
Are you sure you want to remove the user?

[ "+ user.name +" ]

" - this.confirmationService.confirm({ - message: msg, - header: "Remove user", - acceptLabel: "Remove", - accept: ()=>{ - let request: any = {}; - this.http.delete("/v3/groups/"+ group_id +"/users/"+ user.id, request).subscribe((r) => { - this.listUsers(); - }) - }, - reject:()=>{} - }) - } - -} diff --git a/dashboard/src/app/business/identity/tenantDetail/tenantDetail.html b/dashboard/src/app/business/identity/tenantDetail/tenantDetail.html deleted file mode 100644 index 8b8bf9987..000000000 --- a/dashboard/src/app/business/identity/tenantDetail/tenantDetail.html +++ /dev/null @@ -1,61 +0,0 @@ -
Loading...
-
- -

{{I18N.keyID['sds_identity_res_usage']}}

-
    -
  • {{I18N.keyID['sds_identity_tenant_cap']}}: {{ statistics_capacity }}
  • -
  • {{I18N.keyID['sds_home_volumes']}}: {{ statistics_volumes }}
  • -
  • {{I18N.keyID['sds_home_snapshots']}}: {{ statistics_volumeSnapshots }}
  • -
- -

{{I18N.keyID['sds_identity_tenant_manage']}}

-
-
-
- - - - - -
-
-
- - - - - Remove - - -
-
- - -
-
-
-
- - -
- -
-
- - - - - -
-
-
- -
- - - - - -
- - \ No newline at end of file diff --git a/dashboard/src/app/business/identity/tenantDetail/tenantDetail.module.ts b/dashboard/src/app/business/identity/tenantDetail/tenantDetail.module.ts deleted file mode 100644 index 445f9a9a4..000000000 --- a/dashboard/src/app/business/identity/tenantDetail/tenantDetail.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { NgModule, APP_INITIALIZER } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { TenantDetailComponent } from './tenantDetail.component'; -import { ButtonModule, DataTableModule, DropMenuModule, DialogModule, ConfirmDialogModule, BadgeModule, InputTextModule } from '../../../components/common/api'; - -@NgModule({ - declarations: [ TenantDetailComponent ], - imports: [ CommonModule, ButtonModule, DataTableModule, DropMenuModule, DialogModule, ConfirmDialogModule, BadgeModule, InputTextModule ], - exports: [ TenantDetailComponent ], - providers: [] -}) -export class TenantDetailModule { } \ No newline at end of file diff --git a/dashboard/src/app/business/identity/tenantDetail/tenantDetail.scss b/dashboard/src/app/business/identity/tenantDetail/tenantDetail.scss deleted file mode 100644 index 1fadb369d..000000000 --- a/dashboard/src/app/business/identity/tenantDetail/tenantDetail.scss +++ /dev/null @@ -1,15 +0,0 @@ -.table-detail-con > ul{ - display: flex; - display: -webkit-flex; - justify-content: space-between; - padding-bottom: 0.25rem; -} -.table-detail-con > ul li{ - color: #666; - width: 30%; -} -.table-detail-con > ul li span{ - padding-left: 0.1rem; - font-size: 20px; - color: #40BCEC; -} \ No newline at end of file diff --git a/dashboard/src/app/business/identity/tenantList.component.ts b/dashboard/src/app/business/identity/tenantList.component.ts deleted file mode 100644 index 12a9bb0c2..000000000 --- a/dashboard/src/app/business/identity/tenantList.component.ts +++ /dev/null @@ -1,248 +0,0 @@ -import { Component, OnInit, ViewContainerRef, ViewChild, Directive, ElementRef, HostBinding, HostListener, ViewChildren } from '@angular/core'; -import { Http } from '@angular/http'; -import { I18NService } from 'app/shared/api'; -import { AppService } from 'app/app.service'; -import { I18nPluralPipe } from '@angular/common'; -import { trigger, state, style, transition, animate } from '@angular/animations'; -import { MenuItem, ConfirmationService } from '../../components/common/api'; -import { FormControl, FormGroup, FormBuilder, Validators, ValidatorFn, AbstractControl} from '@angular/forms'; - -let _ = require("underscore"); - -@Component({ - selector: 'tenant-list', - templateUrl: 'tenantList.html', - styleUrls: [], - providers: [ConfirmationService], - animations: [] -}) -export class TenantListComponent implements OnInit { - tenants = []; - isDetailFinished = false; - createTenantDisplay = false; - isEditTenant = false; - - selectedTenants = []; - - sortField: string; - currentTenant: string; - popTitle: string; - - tenantFormGroup; - projectID: string; - projectName: string; - - validRule= { - 'name':'^[a-zA-Z]{1}([a-zA-Z0-9]|[_]){0,127}$' - }; - - constructor( - private http: Http, - private confirmationService: ConfirmationService, - public I18N: I18NService, - // private router: Router, - private fb: FormBuilder - ) { - this.tenantFormGroup = this.fb.group({ - "form_name": ["", [Validators.required, Validators.pattern(this.validRule.name), this.ifTenantExisting(this.tenants)] ], - "form_description":["", Validators.maxLength(200) ], - }) - } - - errorMessage = { - "form_name": { required: "Username is required.", pattern:"Beginning with a letter with a length of 1-128, it can contain letters / numbers / underlines.", ifTenantExisting:"Tenant is existing."}, - "form_description": { maxlength: "Max. length is 200."} - }; - - ngOnInit() { - this.listTenants(); - - } - - ifTenantExisting (param: any): ValidatorFn{ - return (c: AbstractControl): {[key:string]: boolean} | null => { - let isExisting= false; - this.tenants.forEach(element => { - if(element.name == c.value){ - isExisting = true; - } - }) - if(isExisting && this.isEditTenant == false){ - return {'ifTenantExisting': true}; - }else{ - return null; - } - } - } - - listTenants() { - this.tenants=[]; - this.selectedTenants = []; - - this.sortField = "name"; - - let request: any = { params:{} }; - request.params = { - "domain_id": "default" - } - - this.http.get("/v3/projects", request).subscribe((res) => { - this.tenants = res.json().projects; - this.tenants.forEach((item)=>{ - item["description"] = item.description == '' ? '--' : item.description; - if(item.name == "admin" || item.name == "service"){ - item["disabled"] = true; - } - }) - }); - } - - showCreateTenant(tenant?) { - this.createTenantDisplay = true; - - //Reset form - this.tenantFormGroup.reset(); - - if(tenant){ - this.isEditTenant = true; - this.popTitle = "Modify"; - - this.currentTenant = tenant.id; - - this.tenantFormGroup.controls['form_name'].value = tenant.name; - this.tenantFormGroup.controls['form_description'].value = tenant.description; - - }else{ - this.isEditTenant = false; - this.popTitle = "Create"; - - } - } - - createTenant(){ - let request: any = { project:{} }; - request.project = { - "domain_id": "default", - "name": this.tenantFormGroup.value.form_name, - "description": this.tenantFormGroup.value.form_description - } - - if(this.tenantFormGroup.status == "VALID"){ - // create tenant - this.http.post("/v3/projects", request).subscribe((res) => { - let tenantid = res.json().project.id; - - - // get roles - let request: any = { params:{} }; - this.http.get("/v3/roles", request).subscribe((roleRES) => { - roleRES.json().roles.forEach((item, index) => { - if(item.name == "Member"){ - // create group for role named [Member] - let request: any = { group:{} }; - request.group = { - "domain_id": "default", - "name": "group_"+ tenantid + "_Member" - } - this.http.post("/v3/groups/", request).subscribe((groupRES) => { - let groupid = groupRES.json().group.id; - - // Assign role to group on project - let reqRole: any = { }; - this.http.put("/v3/projects/"+ tenantid +"/groups/"+ groupid +"/roles/"+ item.id, reqRole).subscribe(() => { - this.createTenantDisplay = false; - this.listTenants(); - }) - }); - } - }) - - }) - - - }); - }else{ - // validate - for(let i in this.tenantFormGroup.controls){ - this.tenantFormGroup.controls[i].markAsTouched(); - } - } - } - - updateTenant(){ - let request: any = { project:{} }; - request.project = { - "domain_id": "default", - "name": this.tenantFormGroup.value.form_name, - "description": this.tenantFormGroup.value.form_description - } - - if(this.tenantFormGroup.status == "VALID"){ - this.http.patch("/v3/projects/"+ this.currentTenant, request).subscribe((res) => { - this.createTenantDisplay = false; - this.listTenants(); - }); - } - } - - deleteTenant(tenants){ - let arr=[],msg; - if(_.isArray(tenants)){ - tenants.forEach((item,index)=> { - arr.push(item.id); - }) - msg = "
Are you sure you want to delete the selected tenants?

[ "+ tenants.length +" Tenants ]

"; - }else{ - arr.push(tenants.id); - msg = "
Are you sure you want to delete the tenant?

[ "+ tenants.name +" ]

" - } - - this.confirmationService.confirm({ - message: msg, - header: "Delete Tenant", - acceptLabel: "Delete", - isWarning: true, - accept: ()=>{ - arr.forEach((ele)=> { - this.http.get("/v3/role_assignments?scope.project.id="+ ele).subscribe((res)=>{ - res.json().role_assignments.forEach((item, index) => { - if(item.group){ - let request: any = {}; - this.http.delete("/v3/groups/"+ item.group.id, request).subscribe(); - } - }); - - let request: any = {}; - this.http.delete("/v3/projects/"+ ele, request).subscribe((r) => { - this.listTenants(); - }) - }) - }) - }, - reject:()=>{} - }) - - } - - onRowExpand(evt) { - this.isDetailFinished = false; - this.projectID = evt.data.id; - this.projectName = evt.data.name; - } - - tablePaginate() { - this.selectedTenants = []; - } - - label: object = { - tenantNameLabel: 'Name', - descriptionLabel: 'Description', - } - -} - - - - - - diff --git a/dashboard/src/app/business/identity/tenantList.html b/dashboard/src/app/business/identity/tenantList.html deleted file mode 100644 index 9b0cfd316..000000000 --- a/dashboard/src/app/business/identity/tenantList.html +++ /dev/null @@ -1,53 +0,0 @@ -
-

A tenant is used to group and manage resources and users.

-
- -
-
- - -
-
-
- - -
- -
-
- - - - - - - - - {{I18N.keyID['sds_block_volume_modify']}} - {{I18N.keyID['sds_block_volume_delete']}} - - - - - - - - -
- - - - - - - -
- - - - - - -
- - \ No newline at end of file diff --git a/dashboard/src/app/business/identity/tenantList.module.ts b/dashboard/src/app/business/identity/tenantList.module.ts deleted file mode 100644 index 3111b2c79..000000000 --- a/dashboard/src/app/business/identity/tenantList.module.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { NgModule, APP_INITIALIZER } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { TenantListComponent } from './tenantList.component'; -import { ReactiveFormsModule, FormsModule } from '@angular/forms'; -import { FormModule, CheckboxModule, ConfirmDialogModule, ButtonModule, MultiSelectModule, DataTableModule, DropMenuModule, DialogModule, InputTextModule, InputTextareaModule, DropdownModule } from '../../components/common/api'; -import { TenantDetailModule } from './tenantDetail/tenantDetail.module'; - -@NgModule({ - declarations: [ TenantListComponent ], - imports: [ - CommonModule, - ButtonModule, - DataTableModule, - DropMenuModule, - DialogModule, - InputTextModule, - InputTextareaModule, - ReactiveFormsModule, - FormsModule, - FormModule, - ConfirmDialogModule, - MultiSelectModule, - CheckboxModule, - TenantDetailModule - ], - exports: [ TenantListComponent ], - providers: [] -}) -export class TenantListModule { } \ No newline at end of file diff --git a/dashboard/src/app/business/identity/userDetail/userDetail.component.ts b/dashboard/src/app/business/identity/userDetail/userDetail.component.ts deleted file mode 100644 index 70ed1bd86..000000000 --- a/dashboard/src/app/business/identity/userDetail/userDetail.component.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Component, Input, OnInit, ViewContainerRef, ViewChild, Directive, ElementRef, HostBinding, HostListener } from '@angular/core'; -import { Http } from '@angular/http'; -import { I18NService } from 'app/shared/api'; -import { AppService } from 'app/app.service'; -import { I18nPluralPipe } from '@angular/common'; -import { trigger, state, style, transition, animate } from '@angular/animations'; -import { MenuItem } from '../../../components/common/api'; - -@Component({ - selector: 'user-detail', - templateUrl: 'userDetail.html', - styleUrls: ['userDetail.scss'], - animations: [] -}) -export class userDetailComponent implements OnInit { - @Input() isUserDetailFinished: Boolean; - - @Input() detailUserInfo: string; - - userID: string; - - unspecified: boolean = false; - - ownedTenant: string = ""; - - constructor( - private http: Http, - // private I18N: I18NService, - // private router: Router - ) { } - - ngOnInit() { - this.userID = this.detailUserInfo; - - let request: any = { params: {} }; - this.http.get("/v3/users/" + this.userID + "/projects", request).subscribe((res) => { - if(res.json().projects.length == 0){ - this.ownedTenant = "Unspecified"; - this.unspecified = true; - } - res.json().projects.forEach((ele, i) => { - if(i==0){ - this.ownedTenant = ele.name; - }else{ - this.ownedTenant += ", "+ ele.name; - } - }); - - this.isUserDetailFinished = true; - }); - - } - -} diff --git a/dashboard/src/app/business/identity/userDetail/userDetail.html b/dashboard/src/app/business/identity/userDetail/userDetail.html deleted file mode 100644 index a2b900600..000000000 --- a/dashboard/src/app/business/identity/userDetail/userDetail.html +++ /dev/null @@ -1,7 +0,0 @@ -
Loading...
-
-
    -
  • {{ ownedTenant }}
  • -
  • {{ userID }}
  • -
-
\ No newline at end of file diff --git a/dashboard/src/app/business/identity/userDetail/userDetail.module.ts b/dashboard/src/app/business/identity/userDetail/userDetail.module.ts deleted file mode 100644 index 3df1c2b89..000000000 --- a/dashboard/src/app/business/identity/userDetail/userDetail.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { NgModule, APP_INITIALIZER } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { userDetailComponent } from './userDetail.component'; -import { ButtonModule, DataTableModule, DropMenuModule } from '../../../components/common/api'; - -@NgModule({ - declarations: [ userDetailComponent ], - imports: [ CommonModule, ButtonModule, DataTableModule, DropMenuModule ], - exports: [ userDetailComponent ], - providers: [] -}) -export class UserDetailModule { } \ No newline at end of file diff --git a/dashboard/src/app/business/identity/userDetail/userDetail.scss b/dashboard/src/app/business/identity/userDetail/userDetail.scss deleted file mode 100644 index 8cbddaa0d..000000000 --- a/dashboard/src/app/business/identity/userDetail/userDetail.scss +++ /dev/null @@ -1,18 +0,0 @@ -.table-detail-con > ul{ - padding: 0; -} -.table-detail-con > ul li{ - display: flex; - display: -webkit-flex; - justify-content: flex-start; - line-height: .28rem; -} -.table-detail-con > ul li label{ - display: inline-block; - width: 135px; - color: #8893a6; -} -.table-detail-con > ul li span{ - padding-left: 0.1rem; - color: #657D95; -} \ No newline at end of file diff --git a/dashboard/src/app/business/identity/userList.component.ts b/dashboard/src/app/business/identity/userList.component.ts deleted file mode 100644 index 09a16edd5..000000000 --- a/dashboard/src/app/business/identity/userList.component.ts +++ /dev/null @@ -1,395 +0,0 @@ -import { Component, OnInit, AfterViewChecked, AfterContentChecked, ViewContainerRef, ViewChild, Directive, ElementRef, HostBinding, HostListener, ViewChildren } from '@angular/core'; -import { Http } from '@angular/http'; -import { I18NService } from 'app/shared/api'; -import { AppService } from 'app/app.service'; -import { I18nPluralPipe } from '@angular/common'; -import { trigger, state, style, transition, animate, group } from '@angular/animations'; -import { MenuItem, ConfirmationService } from '../../components/common/api'; -import { FormControl, FormGroup, FormBuilder, Validators, ValidatorFn, AbstractControl} from '@angular/forms'; -import { retry } from 'rxjs/operators'; -import { forEach } from '@angular/router/src/utils/collection'; - -let _ = require("underscore"); - -@Component({ - selector: 'user-list', - templateUrl: 'userList.html', - styleUrls: [], - providers: [ConfirmationService], - animations: [] -}) -export class UserListComponent implements OnInit, AfterViewChecked { - tenantUsers = []; - createUserDisplay = false; - isUserDetailFinished = false; - isEditUser = false; - myFormGroup; - - selectedUsers = []; - - userRole: string; - tenantLists = []; - - username: string; - currentUser; - - detailUserInfo: string; - popTitle: string; - - sortField: string; - - validRule= { - 'name':'^[a-zA-Z]{1}([a-zA-Z0-9]|[_]){0,127}$' - }; - - newPassword = ""; - - constructor( - private http: Http, - private confirmationService: ConfirmationService, - public I18N: I18NService, - // private router: Router, - private fb: FormBuilder - ) { - - this.myFormGroup = this.fb.group({ - "form_username": ["", {validators:[Validators.required, Validators.pattern(this.validRule.name), this.ifUserExisting(this.tenantUsers)], updateOn:'change'} ], - "form_description":["", Validators.maxLength(200) ], - "form_tenant": [""], - "form_isModifyPsw": [true], - "form_psw": ["", {validators: [Validators.required, Validators.minLength(8), this.regPassword], updateOn:'blur'} ], - "form_pswConfirm": ["", [Validators.required, this.regConfirmPassword(this.newPassword)] ] - }) - } - - errorMessage = { - "form_username": { required: "Username is required.", pattern:"Beginning with a letter with a length of 1-128, it can contain letters / numbers / underlines.", ifUserExisting:"User is existing."}, - "form_description": { maxlength: "Max. length is 200."}, - "form_tenant": { required: "Tenant is required."}, - "form_psw": { required: "Password is required.", minlength: "At least two kinds of letters / numbers / special characters, min. length is 8.", regPassword:"At least two kinds of letters / numbers / special characters, min. length is 8." }, - "form_pswConfirm": { required: "Password is required.", regConfirmPassword: "Two inputted password inconsistencies." } - }; - - label:object = { - userNameLabel:'Username', - passwordLabel:'Password', - descriptionLabel:'Description', - confirmPasswordLabel:'Confirm Password', - roleLabel:'Role', - tenantLabel:'Tenant' - } - - ifUserExisting (param: any): ValidatorFn{ - return (c: AbstractControl): {[key:string]: boolean} | null => { - let isExisting= false; - this.tenantUsers.forEach(element => { - if(element.username == c.value){ - isExisting = true; - } - }) - if(isExisting){ - return {'ifUserExisting': true}; - }else{ - return null; - } - } - } - - regPassword(c:AbstractControl):{[key:string]:boolean} | null { - let reg1 = /.*[a-zA-Z]+.*/; - let reg2 = /.*[0-9]+.*/; - let reg3 = /.*[\ \`\~\!\@\#\$\%\^\&\*\(\)\-\_\=\+\\\|\[\{\}\]\;\:\'\"\,\<\.\>\/\?]+.*/; - if( !reg1.test(c.value) && !reg2.test(c.value) ){ - return {'regPassword': true}; - } - if( !reg1.test(c.value) && !reg3.test(c.value) ){ - return {'regPassword': true}; - } - if( !reg2.test(c.value) && !reg3.test(c.value) ){ - return {'regPassword': true}; - } - return null; - } - - regConfirmPassword (param: any): ValidatorFn{ - return (c: AbstractControl): {[key:string]: boolean} | null => { - if(c.value != this.newPassword){ - return {'regConfirmPassword': true}; - } - return null; - } - } - - showUserForm(user?): void{ - this.getRoles(); - this.getTenants(); - this.createUserDisplay = true; - - //Reset form - this.myFormGroup.reset(); - - if(user){ - this.isEditUser = true; - this.popTitle = "Modify"; - - this.username = user.username; - this.currentUser = user; - - this.myFormGroup.controls['form_description'].value = user.description; - this.myFormGroup.controls['form_isModifyPsw'].value = false; - - this.myFormGroup.controls['form_username'].clearValidators(); - this.myFormGroup.controls['form_psw'].clearValidators(); - this.myFormGroup.controls['form_pswConfirm'].clearValidators(); - - - }else{ - this.isEditUser = false; - this.popTitle = "Create"; - - this.myFormGroup.controls['form_isModifyPsw'].value = true; - this.myFormGroup.controls['form_username'].setValidators({validators:[Validators.required, Validators.pattern(this.validRule.name), this.ifUserExisting(this.tenantUsers)], updateOn:'change'}); - this.myFormGroup.controls['form_psw'].setValidators([Validators.required, Validators.minLength(8), this.regPassword]); - this.myFormGroup.controls['form_pswConfirm'].setValidators([Validators.required, this.regConfirmPassword(this.newPassword)] ); - } - - // Update form validate status - for(let i in this.myFormGroup.controls){ - this.myFormGroup.controls[i].updateValueAndValidity(); - } - } - - createUser(){ - let request: any = { user:{} }; - request.user = { - "domain_id": "default", - "name": this.myFormGroup.value.form_username, - "description": this.myFormGroup.value.form_description, - "password": this.myFormGroup.value.form_psw - } - - if(this.myFormGroup.status == "VALID"){ - this.http.post("/v3/users", request).subscribe( (res) => { - let tenants = this.myFormGroup.value.form_tenant; - - if(!tenants){ - this.createUserDisplay = false; - this.listUsers(); - return; - } - - tenants.forEach( (element, i) => { - this.http.get("/v3/role_assignments?scope.project.id="+ element).subscribe((ass_res)=>{ - let groupid; - - ass_res.json().role_assignments.map((element)=>{ - if(element.group){ - return groupid = element.group.id; - } - }) - - let request: any = {}; - this.http.put("/v3/groups/"+ groupid + "/users/"+ res.json().user.id, request).subscribe(); - }) - if(i == (tenants.length-1)){ - this.createUserDisplay = false; - this.listUsers(); - } - }) - }); - }else{ - // validate - for(let i in this.myFormGroup.controls){ - this.myFormGroup.controls[i].markAsTouched(); - } - } - } - - updateUser(){ - let request: any = { user:{} }; - request.user = { - "description": this.myFormGroup.value.form_description - } - if(this.myFormGroup.value.form_isModifyPsw==true){ - request.user["password"] = this.myFormGroup.value.form_psw; - - if(this.myFormGroup.status == "VALID"){ - this.http.patch("/v3/users/"+ this.currentUser.userid, request).subscribe((res) => { - this.createUserDisplay = false; - this.listUsers(); - }); - }else{ - // validate - for(let i in this.myFormGroup.controls){ - this.myFormGroup.controls[i].markAsTouched(); - } - } - }else{ - - if(this.myFormGroup.status == "VALID"){ - this.http.patch("/v3/users/"+ this.currentUser.userid, request).subscribe((res) => { - this.createUserDisplay = false; - this.listUsers(); - }); - }else{ - // validate - for(let i in this.myFormGroup.controls){ - this.myFormGroup.controls[i].markAsTouched(); - } - } - } - - - } - - getRoles(){ - let request: any = { params:{} }; - this.http.get("/v3/roles", request).subscribe((res) => { - res.json().roles.forEach((item, index) => { - if(item.name == "Member"){ - this.userRole = item.id; - } - }) - }); - } - - getTenants(){ - this.tenantLists = []; - - let request: any = { params:{} }; - request.params = { - "domain_id": "default" - } - - this.http.get("/v3/projects", request).subscribe((res) => { - res.json().projects.map((item, index) => { - let tenant = {}; - if(item.name != "admin" && item.name != "service"){ - tenant["label"] = item.name; - tenant["value"] = item.id; - this.tenantLists.push(tenant); - } - }); - }); - } - - - ngOnInit() { - this.listUsers(); - - } - - ngAfterViewChecked(){ - this.newPassword = this.myFormGroup.value.form_psw; - - } - - ModifyPswChecked(checked){ - if(checked){ - this.myFormGroup.controls['form_psw'].setValidators([Validators.required, Validators.minLength(8), this.regPassword]); - this.myFormGroup.controls['form_pswConfirm'].setValidators([Validators.required, this.regConfirmPassword(this.newPassword)] ); - - }else{ - this.myFormGroup.controls['form_psw'].clearValidators(); - this.myFormGroup.controls['form_pswConfirm'].clearValidators(); - - } - - // Update form validate status - for(let i in this.myFormGroup.controls){ - this.myFormGroup.controls[i].updateValueAndValidity(); - } - } - - listUsers(){ - this.tenantUsers = []; - this.selectedUsers = []; - - this.sortField = "username"; - - let request: any = { params:{} }; - request.params = { - "domain_id": "default" - } - - this.http.get("/v3/users", request).subscribe((res) => { - res.json().users.map((item, index) => { - let user = {}; - user["enabled"] = item.enabled; - user["username"] = item.name; - user["userid"] = item.id; - user["defaultTenant"] = item.default_project_id; - user["description"] = !item.description ? '--' : item.description=='' ? '--' : item.description; - - if(item.name == "admin" || item.name == "opensds"){ - user["disabled"] = true; - } - this.tenantUsers.push(user); - }); - }); - } - - userStatus(user){ - let msg = user.enabled == true ? "
Are you sure you want to disable the user?

[ "+ user.username +" ]

" : "
Are you sure you want to enable the user?

[ "+ user.username +" ]

"; - let status = user.enabled ? false : true; - - this.confirmationService.confirm({ - message: msg, - header: user.enabled ? 'Disable User' : 'Enable User', - acceptLabel: user.enabled ? 'Disable' : 'Enable', - accept: ()=>{ - let request: any = { user:{} }; - request.user = { - "enabled": status - } - this.http.patch("/v3/users/"+ user.userid, request).subscribe((res) => { - this.listUsers(); - }); - - }, - reject:()=>{} - }) - } - - deleteUsers(users){ - let arr=[], msg; - if(_.isArray(users)){ - users.forEach((item,index)=> { - arr.push(item.userid); - }) - msg = "
Are you sure you want to delete the selected users?

[ "+ users.length +" Users ]

"; - }else{ - arr.push(users.userid); - msg = "
Are you sure you want to delete the user?

[ "+ users.username +" ]

"; - } - - this.confirmationService.confirm({ - message: msg, - header: "Delete User", - acceptLabel: "Delete", - isWarning: true, - accept: ()=>{ - arr.forEach((item,index)=> { - let request: any = {}; - this.http.delete("/v3/users/"+ item, request).subscribe((res) => { - if(index == arr.length-1){ - this.listUsers(); - } - }); - }) - - }, - reject:()=>{} - }) - - } - - onRowExpand(evt) { - this.isUserDetailFinished = false; - this.detailUserInfo = evt.data.userid; - } - - tablePaginate() { - this.selectedUsers = []; - } -} diff --git a/dashboard/src/app/business/identity/userList.html b/dashboard/src/app/business/identity/userList.html deleted file mode 100644 index 9a1ebe512..000000000 --- a/dashboard/src/app/business/identity/userList.html +++ /dev/null @@ -1,81 +0,0 @@ -
-

A tenant is used to group and manage resources and users.

-
- -
-
- - -
-
-
- - -
- -
-
- - - - - - - -
-
-
- - - - {{I18N.keyID['sds_block_volume_modify']}} - {{ (user.enabled == true) ? "Disable" : "Enable" }} - {{I18N.keyID['sds_block_volume_delete']}} - - - - - - -
- - - -
- - - {{ username }} - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
- \ No newline at end of file diff --git a/dashboard/src/app/business/identity/userList.module.ts b/dashboard/src/app/business/identity/userList.module.ts deleted file mode 100644 index afbedddbc..000000000 --- a/dashboard/src/app/business/identity/userList.module.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { NgModule, APP_INITIALIZER } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { ReactiveFormsModule, FormsModule } from '@angular/forms'; -import { UserListComponent } from './userList.component'; -import { BadgeModule, FormModule, ButtonModule, CheckboxModule, DataTableModule, DropMenuModule, MultiSelectModule, DialogModule, InputTextModule, InputTextareaModule, DropdownModule, PasswordModule, ConfirmDialogModule } from '../../components/common/api'; - -import { UserDetailModule } from './userDetail/userDetail.module'; - -@NgModule({ - declarations: [UserListComponent], - imports: [ - CommonModule, - ButtonModule, - BadgeModule, - DataTableModule, - DropMenuModule, - DialogModule, - ConfirmDialogModule, - InputTextModule, - InputTextareaModule, - DropdownModule, - CheckboxModule, - PasswordModule, - FormsModule, - ReactiveFormsModule, - MultiSelectModule, - FormModule, - UserDetailModule - ], - exports: [UserListComponent], - providers: [] -}) -export class UserListModule { } \ No newline at end of file diff --git a/dashboard/src/app/business/profile/createProfile/createProfile.component.html b/dashboard/src/app/business/profile/createProfile/createProfile.component.html deleted file mode 100644 index c70165314..000000000 --- a/dashboard/src/app/business/profile/createProfile/createProfile.component.html +++ /dev/null @@ -1,185 +0,0 @@ -
-

{{I18N.keyID['sds_profile_create_title']}}

-

{{I18N.keyID['sds_profile_create_descrip']}}

-
- -
-
-
- - - - - - - - - - - - - - - - - -
-
-
-
-
- - -
- - {{I18N.keyID['sds_profile_IOPS_unit']}} -
-
- -
- - {{I18N.keyID['sds_profile_BWS_unit']}} -
-
- -
-
-
- - - -
-
-
-
-
-
-
- - - - - - - -
- {{I18N.keyID['sds_profile_unit_minutes']}} -
-
- -
- {{I18N.keyID['sds_profile_BWS_unit']}} -
-
-
-
- - - - - - - - - - - - -
-
-
-
-
- - - -
-
-
-
-
-
- - - - -
- -
-
- -
- -
- - -
- {{I18N.keyID['sds_profile_nuit_days']}} -
-
-
-
-
-
- - - -
-
-
-
-
- {{customizationItem.key}}: -
-
- {{customizationItem.value}} -
-
- -
-
-
- - - -
-
-
-
- -
-
-
-
- - -
- -
- - -
-
- {{label.key}} - -
-
- {{label.value}} - -
-
- - - - -
diff --git a/dashboard/src/app/business/profile/createProfile/createProfile.component.ts b/dashboard/src/app/business/profile/createProfile/createProfile.component.ts deleted file mode 100644 index a19836eef..000000000 --- a/dashboard/src/app/business/profile/createProfile/createProfile.component.ts +++ /dev/null @@ -1,482 +0,0 @@ -import { Router } from '@angular/router'; -import { Component, OnInit, ViewContainerRef, ViewChild, Directive, ElementRef, HostBinding, HostListener } from '@angular/core'; -import { Validators, FormControl, FormGroup, FormBuilder } from '@angular/forms'; -import { I18NService } from 'app/shared/api'; -import { AppService } from 'app/app.service'; -import { trigger, state, style, transition, animate } from '@angular/animations'; -import { I18nPluralPipe } from '@angular/common'; - -import { Message, SelectItem } from './../../../components/common/api'; -import { ProfileService } from './../profile.service'; - -@Component({ - templateUrl: './createProfile.component.html', - styleUrls: [ - - ], - animations: [ - trigger('overlayState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]), - - trigger('notificationTopbar', [ - state('hidden', style({ - height: '0', - opacity: 0 - })), - state('visible', style({ - height: '*', - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]) - ] -}) -export class CreateProfileComponent implements OnInit { - showCustomization = false; - showStoragePool = false; - msgs: Message[] = []; - userform: FormGroup; - submitted: boolean; - genders: SelectItem[]; - description: string; - - profileform: FormGroup; - qosPolicy:FormGroup; - repPolicy:FormGroup; - snapPolicy:FormGroup; - paramData= { - extras:{protocol:""}, - storageType:"" - }; - label; - param = { - name: '', - description: '', - extras: { - - } - }; - qosIsChecked = false; - replicationIsChecked = false; - snapshotIsChecked = false; - protocolOptions = [ - { - label: 'iSCSI', - value: 'iSCSI' - }, - { - label: 'FC', - value: 'FC' - }, - { - label: 'RBD', - value: 'RBD' - } - ]; - - //用户自定义key、value,用于双向数据绑定 - customizationKey = ''; - customizationValue = ''; - - //用户自定义项,用于 - customizationItems = []; - - replicationTypeOptions = [ - { - label: 'Mirror', - value: 'mirror' - }/*, - { - label: 'Snapshot', - value: 'snapshot' - }, - { - label: 'Clone', - value: 'clone' - }, - { - label: 'Tokenized Clone', - value: 'tokenized' - }*/ - ]; - - replicationRGOOptions = [ - { - label: 'Availability Zone', - value: 'availabilityZone' - }, - { - label: 'Rack', - value: 'rack' - }, - { - label: 'Row', - value: 'row' - }, - { - label: 'Server', - value: 'server' - }, - { - label: 'Facility', - value: 'facility' - }, - { - label: 'Region', - value: 'region' - } - ]; - - replicationModeOptions = [ - { - label: 'Synchronous', - value: 'Synchronous' - }, - { - label: 'Asynchronous', - value: 'Asynchronous' - }, - { - label: 'Active', - value: 'Active' - }, - { - label: 'Adaptive', - value: 'Adaptive' - } - ]; - - replicationRTOOptions = [ - { - label: 'Immediate', - value: 'Immediate' - }, - { - label: 'Online', - value: 'Online' - }, - { - label: 'Nearline', - value: 'Nearline' - }, - { - label: 'Offline', - value: 'Offline' - } - ]; - - replicationRPOOptions = [ - { - label: '0', - value: 0 - }, - { - label: '4', - value: 4 - }, - { - label: '60', - value: 60 - }, - { - label: '3600', - value: 3600 - } - ]; - errorMessage={ - "name": { required: this.I18N.keyID['sds_profile_create_name_require']}, - "maxIOPS": { required: this.I18N.keyID['sds_required'].replace("{0}","MaxIOPS")}, - "maxBWS" :{ required: this.I18N.keyID['sds_required'].replace("{0}","MaxBWS")}, - "repPeriod" :{ required: this.I18N.keyID['sds_required'].replace("{0}","Period")}, - "repBandwidth" :{ required: this.I18N.keyID['sds_required'].replace("{0}","Bandwidth")}, - "repRPO" :{ required: this.I18N.keyID['sds_required'].replace("{0}","RPO")}, - "datetime" :{ required: this.I18N.keyID['sds_required'].replace("{0}","Execution Time")}, - "snapNum" :{ required: this.I18N.keyID['sds_required'].replace("{0}","Retention")}, - "duration" :{ required: this.I18N.keyID['sds_required'].replace("{0}","Retention")}, - "description":{maxlength:this.I18N.keyID['sds_validate_max_length']} - }; - snapshotRetentionOptions = [ - { - label: 'Time', - value: 'Time' - }, - { - label: 'Quantity', - value: 'Quantity' - } - ]; - snapSchedule = [ - { - label: 'Daily', - value: 'Daily' - }, - { - label: 'Weekly', - value: 'Weekly' - }, - { - label: 'Monthly', - value: 'Monthly' - } - ]; - - weekDays; - - constructor( - public I18N: I18NService, - private router: Router, - private ProfileService: ProfileService, - private fb: FormBuilder - ) { - this.weekDays = [ - { - label: 'Sun', - value: 0, - styleClass: 'week-select-list' - }, - { - label: 'Mon', - value: 1, - styleClass: 'week-select-list' - }, - { - label: 'Tue', - value: 2, - styleClass: 'week-select-list' - }, - { - label: 'Wed', - value: 3, - styleClass: 'week-select-list' - }, - { - label: 'Thu', - value: 4, - styleClass: 'week-select-list' - }, - { - label: 'Fri', value: 5, - styleClass: 'week-select-list' - }, - { - label: 'Sat', - value: 6, - styleClass: 'week-select-list' - } - ]; - } - - ngOnInit() { - this.label = { - name: this.I18N.keyID['sds_block_volume_name'], - description: this.I18N.keyID['sds_block_volume_descri'], - protocol: this.I18N.keyID['sds_profile_access_pro'], - type: this.I18N.keyID['sds_profile_pro_type'], - qosPolicy: this.I18N.keyID['sds_profile_qos_policy'], - replicationPolicy: this.I18N.keyID['sds_profile_replication_policy'], - snapshotPolicy: this.I18N.keyID['sds_profile_snap_policy'], - customization: this.I18N.keyID['sds_profile_create_customization'], - storagePool: this.I18N.keyID['sds_profile_avai_pool'], - key: this.I18N.keyID['sds_profile_extra_key'], - value: this.I18N.keyID['sds_profile_extra_value'], - maxIOPS: this.I18N.keyID['sds_profile_create_maxIOPS'], - MBPS: this.I18N.keyID['sds_profile_create_maxBWS'], - replicationLabel: { - type:this.I18N.keyID['sds_profile_rep_type'] , - RGO: this.I18N.keyID['sds_profile_rep_rgo'], - Mode:this.I18N.keyID['sds_profile_rep_mode'], - RTO: this.I18N.keyID['sds_profile_rep_rto'], - Period: this.I18N.keyID['sds_profile_rep_period'], - RPO: this.I18N.keyID['sds_profile_rep_rpo'], - Bandwidth: this.I18N.keyID['sds_profile_rep_bandwidth'], - Consistency: this.I18N.keyID['sds_profile_rep_consis'] - }, - snapshotLabel: { - Schedule: this.I18N.keyID['sds_profile_snap_sche'], - executionTime:this.I18N.keyID['sds_profile_snap_exetime'], - Retention: this.I18N.keyID['sds_profile_snap_reten'] - } - }; - - this.profileform = this.fb.group({ - 'name': new FormControl('', Validators.required), - 'description':new FormControl('',Validators.maxLength(200)), - 'protocol': new FormControl('iSCSI'), - 'storageType': new FormControl('Thin', Validators.required), - 'policys': new FormControl(''), - 'snapshotRetention': new FormControl('Time') - }); - this.qosPolicy = this.fb.group({ - "maxIOPS": new FormControl(6000, Validators.required), - "maxBWS" : new FormControl(100, Validators.required), - }); - this.repPolicy = this.fb.group({ - "repType": new FormControl("mirror", Validators.required), - "repMode": new FormControl(this.replicationModeOptions[0].value, Validators.required), - "repPeriod": new FormControl(60, Validators.required), - "repBandwidth": new FormControl(10, Validators.required), - "repRGO": new FormControl(this.replicationRGOOptions[0].value, Validators.required), - "repRTO": new FormControl(this.replicationRTOOptions[0].value, Validators.required), - "repRPO": new FormControl(0, Validators.required), - "repCons": new FormControl([]) - }); - this.snapPolicy = this.fb.group({ - "Schedule": new FormControl(this.snapSchedule[0].value, Validators.required), - "datetime": new FormControl("00:00", Validators.required), - "snapNum": new FormControl(1, Validators.required), - "duration": new FormControl(0, Validators.required), - "retentionOptions": new FormControl(this.snapshotRetentionOptions[0].value) - }); - this.paramData= { - extras:{protocol:this.profileform.value.protocol}, - storageType:this.profileform.value.storageType - }; - this.profileform.get("protocol").valueChanges.subscribe( - (value:string)=>{ - this.paramData = { - extras:{protocol:value}, - storageType:this.profileform.value.storageType - } - } - ); - this.profileform.get("storageType").valueChanges.subscribe( - (value:string)=>{ - this.paramData = { - extras:{protocol:this.profileform.value.protocol}, - storageType:value - } - } - ); - - - - } - - onSubmit(value) { - this.submitted = true; - this.msgs = []; - this.msgs.push({ severity: 'info', summary: 'Success', detail: 'Form Submitted' }); - this.param.name = value.name; - this.param.description = value.description; - if(this.qosIsChecked){ - if(!this.qosPolicy.valid){ - for(let i in this.qosPolicy.controls){ - this.qosPolicy.controls[i].markAsTouched(); - } - return; - } - this.param.extras[":provisionPolicy"]= { - "ioConnectivityLoS": { - "maxIOPS": this.qosPolicy.value.maxIOPS, - "maxBWS": this.qosPolicy.value.maxBWS, - "accessProtocol": value.protocol - }, - "dataStorageLoS": { - "provisioningPolicy": value.storageType - } - } - }else{ - this.param.extras[":provisionPolicy"]= { - "ioConnectivityLoS": { - "accessProtocol": value.protocol - }, - "dataStorageLoS": { - "provisioningPolicy": value.storageType - } - } - } - if(this.replicationIsChecked){ - if(!this.repPolicy.valid){ - for(let i in this.repPolicy.controls){ - this.repPolicy.controls[i].markAsTouched(); - } - return; - } - this.param.extras["replicationType"]= "ArrayBased"; - this.param.extras[":replicationPolicy"]={ - "dataProtectionLoS": { - "replicaTypes": this.repPolicy.value.repType, - "recoveryGeographicObject": this.repPolicy.value.repRGO, - "recoveryPointObjective": this.repPolicy.value.repRPO, - "recoveryTimeObjective": this.repPolicy.value.repRTO, - }, - "replicaInfos": { - "replicaUpdateMode": this.repPolicy.value.repMode, - "consistencyEnabled": this.repPolicy.value.repCons.length==0 ? false:true, - "replicationPeriod": this.repPolicy.value.repPeriod, - "replicationBandwidth": this.repPolicy.value.repBandwidth - } - } - } - if(this.snapshotIsChecked){ - if(!this.snapPolicy.valid){ - for(let i in this.snapPolicy.controls){ - this.snapPolicy.controls[i].markAsTouched(); - } - return; - } - let reten = this.snapPolicy.value.retentionOptions === "Quantity" ? { - "number": this.snapPolicy.value.snapNum, - }:{"duration": this.snapPolicy.value.duration} - this.param.extras[":snapshotPolicy"]= { - "schedule": { - "datetime": "1970-01-01T"+this.snapPolicy.value.datetime+":00", - "occurrence": this.snapPolicy.value.Schedule //Monthly, Weekly, Daily, Hourly - }, - "retention": reten - } - } - if (this.customizationItems.length > 0) { - let arrLength = this.customizationItems.length; - for (let i = 0; i < arrLength; i++) { - this.param.extras[this.customizationItems[i].key] = this.customizationItems[i].value; - } - } - this.createProfile(this.param); - } - - retentionChange(){ - console.log(this.profileform.controls['snapshotRetention'].value); - } - - createProfile(param) { - this.ProfileService.createProfile(param).subscribe((res) => { - - this.router.navigate(['/profile']); - }); - } - - - - getI18n() { - // return {}; - } - - showDetails(policyType) { - this[policyType + 'IsChecked'] = !this[policyType + 'IsChecked']; - } - - addCustomization() { - this.customizationItems.push({ - key: this.customizationKey, - value: this.customizationValue - }); - this.showCustomization = false - this.customizationKey = ''; - this.customizationValue = ''; - } - - deleteCustomization(index) { - this.customizationItems.splice(index, 1); - } - -} diff --git a/dashboard/src/app/business/profile/createProfile/createProfile.module.ts b/dashboard/src/app/business/profile/createProfile/createProfile.module.ts deleted file mode 100644 index 781c3e25a..000000000 --- a/dashboard/src/app/business/profile/createProfile/createProfile.module.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Component, NgModule, APP_INITIALIZER } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { ReactiveFormsModule, FormsModule } from '@angular/forms'; -import { CreateProfileComponent } from './createProfile.component'; -import { RouterModule } from '@angular/router'; -import { InputTextModule,InputTextareaModule, CheckboxModule, FormModule, ButtonModule, DropdownModule, RadioButtonModule, DialogModule, Message, GrowlModule, SelectButtonModule } from '../../../components/common/api'; -import { HttpService } from './../../../shared/api'; -import { ProfileService,PoolService } from './../profile.service'; -import { PoolModule } from './../storage-pools-table/storage-pools-table.module'; - -let routers = [{ - path: '', - component: CreateProfileComponent -}] - -@NgModule({ - declarations: [ - CreateProfileComponent - ], - imports: [ - CommonModule, - ReactiveFormsModule, - FormsModule, - RouterModule.forChild(routers), - InputTextModule, - CheckboxModule, - ButtonModule, - DropdownModule, - RadioButtonModule, - DialogModule, - GrowlModule, - PoolModule, - SelectButtonModule, - FormModule, - InputTextareaModule - ], - providers: [ - HttpService, - ProfileService, - PoolService - ] -}) -export class CreateProfileModule { } diff --git a/dashboard/src/app/business/profile/modifyProfile/modifyProfile.component.html b/dashboard/src/app/business/profile/modifyProfile/modifyProfile.component.html deleted file mode 100644 index cbfeedce4..000000000 --- a/dashboard/src/app/business/profile/modifyProfile/modifyProfile.component.html +++ /dev/null @@ -1,50 +0,0 @@ -
- - {{item.label}} - > - -
-
-
-
-

{{data.name}}

-
-
- Access Protocol: - {{data.extras.protocol}} -
-
- Provisioning Type: - {{data.storageType}} -
-
- QoS Policy: -
-
{{policy}}
-
- Replication Policy: -
-
{{policy}}
-
- Snapshot Policy: -
-
{{policy}}
-
-
-
-
- -
-
- Storage Pools: -
- -
-
- -
-
- - -
-
diff --git a/dashboard/src/app/business/profile/modifyProfile/modifyProfile.component.ts b/dashboard/src/app/business/profile/modifyProfile/modifyProfile.component.ts deleted file mode 100644 index bbed0a5fc..000000000 --- a/dashboard/src/app/business/profile/modifyProfile/modifyProfile.component.ts +++ /dev/null @@ -1,152 +0,0 @@ -import { Router,ActivatedRoute} from '@angular/router'; -import { Component, OnInit, ViewContainerRef, ViewChild, Directive, ElementRef, HostBinding, HostListener } from '@angular/core'; -import { I18NService } from 'app/shared/api'; -import { AppService } from 'app/app.service'; -import { trigger, state, style, transition, animate } from '@angular/animations'; -import { I18nPluralPipe } from '@angular/common'; - -import { ProfileService, PoolService} from './../profile.service'; - -@Component({ - templateUrl: './modifyProfile.component.html', - styleUrls: [ - - ], - animations: [ - trigger('overlayState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]), - - trigger('notificationTopbar', [ - state('hidden', style({ - height: '0', - opacity: 0 - })), - state('visible', style({ - height: '*', - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]) - ] -}) -export class modifyProfileComponent implements OnInit { - items; - chartDatas; - totalFreeCapacity = 0; - option; - data; - cars; - cols: any[]; - formGroup; - errorMessage; - pools; - totalCapacity = 0; - // profileId; - constructor( - // private I18N: I18NService, - // private router: Router - private ActivatedRoute: ActivatedRoute, - private ProfileService: ProfileService, - private poolService:PoolService - ) { } - ngOnInit() { - let profileId; - this.ActivatedRoute.params.subscribe((params) => profileId = params.profileId); - - this.ProfileService.getProfileById(profileId).subscribe((res) => { - // return res.json(); - // this.profiles = res.json(); - this.data = res.json(); - this.getPools(); - }); - this.items = [ - { label: 'Profile', url: '/profile' }, - { label: 'Profile detail', url: '/modifyProfile' } - ]; - this.option = { - cutoutPercentage: 80, - // rotation: (-0.2 * Math.PI), - title: { - display: false, - text: 'My Title', - fontSize: 12 - }, - legend: { - display: true, - labels:{ - boxWidth:12 - }, - position: 'bottom', - fontSize: 12 - } - }; - // this.data = { - // "id": "5d8c3732-a248-50ed-bebc-539a6ffd25c1", - // "name": "Gold", - // "protocol": "FC", - // "type": "Thin", - // "policys": [ - // "Qos", - // "Snapshot", - // "Replication" - // ], - // "description": "provide gold storage service", - // "extras": { - // "key1": "value1", - // "key2": { - // "subKey1": "subValue1", - // "subKey2": "subValue2" - // }, - // "key3": "value3" - // } - // }; - - } - getPools() { - this.poolService.getPools().subscribe((res) => { - this.pools = res.json(); - this.totalFreeCapacity = this.getSumCapacity(this.pools, 'free'); - this.totalCapacity = this.getSumCapacity(this.pools, 'total'); - this.chartDatas = { - labels: ['Total Capacity', 'Used Capacity'], - datasets: [ - { - data: [this.totalCapacity, this.totalCapacity-this.totalFreeCapacity], - backgroundColor: [ - "rgba(224, 224, 224, 1)", - "#438bd3" - ] - // hoverBackgroundColor: [ - // "#FF6384", - // "#36A2EB", - // "#FFCE56" - // ] - }] - }; - }); - } - - getSumCapacity(pools, FreeOrTotal) { - let SumCapacity: number = 0; - let arrLength = pools.length; - for (let i = 0; i < arrLength; i++) { - if(this.data.extras.protocol.toLowerCase() == pools[i].extras.ioConnectivity.accessProtocol && this.data.storageType == pools[i].extras.dataStorage.provisioningPolicy){ - if (FreeOrTotal === 'free') { - SumCapacity += pools[i].freeCapacity; - } else { - SumCapacity += pools[i].totalCapacity; - } - } - } - return SumCapacity; - } -} diff --git a/dashboard/src/app/business/profile/modifyProfile/modifyProfile.module.ts b/dashboard/src/app/business/profile/modifyProfile/modifyProfile.module.ts deleted file mode 100644 index c4ce0b3ee..000000000 --- a/dashboard/src/app/business/profile/modifyProfile/modifyProfile.module.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Component, NgModule, APP_INITIALIZER } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { modifyProfileComponent } from './modifyProfile.component'; -import { RouterModule } from '@angular/router'; -import { BreadcrumbModule,ChartModule,ButtonModule } from './../../../components/common/api'; - -import { HttpService } from './../../../shared/api'; -import { ProfileService,PoolService } from './../profile.service'; -import { PoolModule } from './../storage-pools-table/storage-pools-table.module'; - -let routers = [{ - path: '', - component: modifyProfileComponent -}] - -@NgModule({ - declarations: [ - modifyProfileComponent - ], - imports: [ - CommonModule, - RouterModule.forChild(routers), - BreadcrumbModule, - ChartModule, - ButtonModule, - PoolModule - // FormModule - ], - providers: [ - HttpService, - ProfileService, - PoolService - ] -}) -export class ModifyProfileModule { } \ No newline at end of file diff --git a/dashboard/src/app/business/profile/profile.component.html b/dashboard/src/app/business/profile/profile.component.html deleted file mode 100644 index c6b3aa1e5..000000000 --- a/dashboard/src/app/business/profile/profile.component.html +++ /dev/null @@ -1,26 +0,0 @@ -
-

{{I18N.keyID['sds_block_volume_profile']}}

-

{{I18N.keyID['sds_profile_list_descrip']}}

-
- -
- -
- -
-
- - -
- - - -
- - - - - - - - diff --git a/dashboard/src/app/business/profile/profile.component.ts b/dashboard/src/app/business/profile/profile.component.ts deleted file mode 100644 index e62fbccbd..000000000 --- a/dashboard/src/app/business/profile/profile.component.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { Router } from '@angular/router'; -import { Component, OnInit, ViewContainerRef, ViewChild, Directive, ElementRef, HostBinding, HostListener } from '@angular/core'; -import { I18NService } from 'app/shared/api'; -import { AppService } from 'app/app.service'; -import { trigger, state, style, transition, animate } from '@angular/animations'; -import { I18nPluralPipe } from '@angular/common'; - -import { ProfileService } from './profile.service'; -import { ConfirmationService,ConfirmDialogModule} from '../../components/common/api'; - -@Component({ - templateUrl: './profile.component.html', - styleUrls: [ - - ], - animations: [ - trigger('overlayState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]), - - trigger('notificationTopbar', [ - state('hidden', style({ - height: '0', - opacity: 0 - })), - state('visible', style({ - height: '*', - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]) - ] -}) -export class ProfileComponent implements OnInit { - profileId; - profiles; - showWarningDialog = false; - constructor( - public I18N: I18NService, - // private router: Router - private ProfileService: ProfileService, - private confirmationService:ConfirmationService - ) { } - showCard = true; - ngOnInit() { - this.getProfiles(); - this.profiles = []; - } - - getProfiles() { - this.ProfileService.getProfiles().subscribe((res) => { - this.profiles = res.json(); - }); - } - - showWarningDialogFun(profile) { - let msg = "
Are you sure you want to delete the Profile?

[ "+ profile.name +" ]

"; - let header ="Delete Profile"; - let acceptLabel = "Delete"; - let warming = true; - this.confirmDialog([msg,header,acceptLabel,warming,profile.id]) - } - deleteProfile(id) { - this.ProfileService.deleteProfile(id).subscribe((res) => { - this.getProfiles(); - }); - } - confirmDialog([msg,header,acceptLabel,warming=true,func]){ - this.confirmationService.confirm({ - message: msg, - header: header, - acceptLabel: acceptLabel, - isWarning: warming, - accept: ()=>{ - try { - this.deleteProfile(func); - } - catch (e) { - console.log(e); - } - finally { - - } - }, - reject:()=>{} - }) - } -} diff --git a/dashboard/src/app/business/profile/profile.module.ts b/dashboard/src/app/business/profile/profile.module.ts deleted file mode 100644 index 515d0032d..000000000 --- a/dashboard/src/app/business/profile/profile.module.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule, APP_INITIALIZER } from '@angular/core'; -import { ProfileComponent } from './profile.component'; -import { RouterModule } from '@angular/router'; - -import { ProfileCardComponent } from './profileCard/profile-card.component'; -import { ButtonModule,CardModule,ChartModule,MessageModule,OverlayPanelModule,DialogModule ,ConfirmationService,ConfirmDialogModule} from '../../components/common/api'; -import { ProfileService } from './profile.service'; -import { HttpService } from '../../shared/api'; -import { SuspensionFrameComponent } from './profileCard/suspension-frame/suspension-frame.component'; - -let routers = [{ - path: '', - component: ProfileComponent -}] - -@NgModule({ - declarations: [ - ProfileComponent, - ProfileCardComponent, - SuspensionFrameComponent - ], - imports: [ - RouterModule.forChild(routers), - ButtonModule, - CommonModule, - CardModule, - ChartModule, - MessageModule, - OverlayPanelModule, - DialogModule, - ConfirmDialogModule - ], - providers: [ - HttpService, - ProfileService, - ConfirmationService - ] -}) -export class ProfileModule { } \ No newline at end of file diff --git a/dashboard/src/app/business/profile/profile.service.ts b/dashboard/src/app/business/profile/profile.service.ts deleted file mode 100644 index a47f18f37..000000000 --- a/dashboard/src/app/business/profile/profile.service.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Injectable } from '@angular/core'; -import { HttpService } from './../../shared/service/Http.service'; -import { Observable } from 'rxjs'; - -@Injectable() -export class ProfileService { - url = 'v1beta/{project_id}/profiles' - constructor(private http: HttpService) { } - //创建profile - createProfile(param) { - return this.http.post(this.url, param); - } - - //删除profile - deleteProfile(id): Observable { - let deleteUrl = this.url + '/' + id - return this.http.delete(deleteUrl); - } - - //查询profiles - getProfiles(): Observable { - return this.http.get(this.url); - } - - //查询profiles - getProfileById(id) { - let getUrl = this.url + '/' + id - return this.http.get(getUrl); - } - - //修改profile - modifyProfile(id, param) { - let modifyUrl = this.url + '/' + id - this.http.put(modifyUrl, param).subscribe((res) => { - console.log(res.json().data); - }); - } -} - -@Injectable() -export class PoolService{ - url = 'v1beta/{project_id}/pools'; - constructor(private http: HttpService) { } - //查询profiles - getPools(): Observable { - return this.http.get(this.url); - } -} diff --git a/dashboard/src/app/business/profile/profileCard/profile-card.component.html b/dashboard/src/app/business/profile/profileCard/profile-card.component.html deleted file mode 100644 index c82a17275..000000000 --- a/dashboard/src/app/business/profile/profileCard/profile-card.component.html +++ /dev/null @@ -1,33 +0,0 @@ -
-
-
-

{{data.name}}

-
-
-
{{I18N.keyID['sds_block_volume_descri']}}:
-
{{data && data.description ?data.description :"--"}}
-
-
- Access Protocol: - {{data.extras && data.extras[':provisionPolicy'].ioConnectivityLoS.accessProtocol}} -
-
- Provisioning Type: - {{data.extras && data.extras[':provisionPolicy'].dataStorageLoS.provisioningPolicy}} -
- -
-
-
- {{policy}} -
- -
- -
-
-
- -
-
-
diff --git a/dashboard/src/app/business/profile/profileCard/profile-card.component.ts b/dashboard/src/app/business/profile/profileCard/profile-card.component.ts deleted file mode 100644 index b42378e82..000000000 --- a/dashboard/src/app/business/profile/profileCard/profile-card.component.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { Router } from '@angular/router'; -import { Component, OnInit, Input } from '@angular/core'; -import { I18NService } from 'app/shared/api'; -import { AppService } from 'app/app.service'; -import { trigger, state, style, transition, animate } from '@angular/animations'; -import { I18nPluralPipe } from '@angular/common'; -import { HttpService } from './../../../shared/api'; - -import { ButtonModule } from './../../../components/common/api'; - -// import {CardModule} from 'primeng/card'; - -@Component({ - selector: 'profile-card', - templateUrl: './profile-card.component.html', - styleUrls: [ - - ], - animations: [ - trigger('overlayState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]), - - trigger('notificationTopbar', [ - state('hidden', style({ - height: '0', - opacity: 0 - })), - state('visible', style({ - height: '*', - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]) - ] -}) -export class ProfileCardComponent implements OnInit { - policys = []; - data:any; - @Input() - set cardData(data: any) { - this.data = data; - this.policys = []; - if(data.extras){ - if(data.extras[':provisionPolicy'].ioConnectivityLoS.maxIOPS){ - this.policys.push("QoS"); - } - if(data.extras[':snapshotPolicy']){ - this.policys.push("Snapshot"); - } - if(data.extras[':replicationPolicy']){ - this.policys.push("Replication"); - } - } - - }; - - chartDatas: any; - constructor( - public I18N: I18NService, - // private router: Router - private http: HttpService - ) { } - option = {}; - pools = []; - totalFreeCapacity = 0; - totalCapacity = 0; - ngOnInit() { - this.getPools(); - this.option = { - cutoutPercentage: 80, - // rotation: (0.5 * Math.PI), - // circumference: (Math.PI), - title: { - display: false, - text: 'My Title', - fontSize: 12 - }, - legend: { - labels: { - boxWidth: 12 - }, - display: false, - width: '5px', - position: 'right', - fontSize: 12 - } - }; - } - - index; - isHover; - - showSuspensionFrame(event){ - if(event.type === 'mouseenter'){ - this.isHover = true; - }else if(event.type === 'mouseleave'){ - this.isHover = false; - } - let arrLength = event.target.parentNode.children.length; - for(let i=0; i { - this.pools = res.json(); - this.totalFreeCapacity = this.getSumCapacity(this.pools, 'free'); - this.totalCapacity = this.getSumCapacity(this.pools, 'total'); - this.chartDatas = { - labels: ['Unused Capacity', 'Used Capacity'], - datasets: [ - { - data: [this.totalFreeCapacity,this.totalCapacity-this.totalFreeCapacity], - backgroundColor: [ - "rgba(224, 224, 224, .5)", - "#438bd3" - ] - // hoverBackgroundColor: [ - // "#FF6384", - // "#36A2EB", - // "#FFCE56" - // ] - }] - }; - }); - } - - getSumCapacity(pools, FreeOrTotal) { - let SumCapacity: number = 0; - let arrLength = pools.length; - for (let i = 0; i < arrLength; i++) { - if(this.data.extras && this.data.extras[":provisionPolicy"].ioConnectivityLoS.accessProtocol.toLowerCase() == pools[i].extras.ioConnectivity.accessProtocol && this.data.extras[":provisionPolicy"].dataStorageLoS.provisioningPolicy == pools[i].extras.dataStorage.provisioningPolicy){ - if (FreeOrTotal === 'free') { - SumCapacity += pools[i].freeCapacity; - } else { - SumCapacity += pools[i].totalCapacity; - } - }else{ - SumCapacity = 0; - } - } - return SumCapacity; - } -} diff --git a/dashboard/src/app/business/profile/profileCard/suspension-frame/suspension-frame.component.html b/dashboard/src/app/business/profile/profileCard/suspension-frame/suspension-frame.component.html deleted file mode 100644 index 114f8ca8e..000000000 --- a/dashboard/src/app/business/profile/profileCard/suspension-frame/suspension-frame.component.html +++ /dev/null @@ -1,9 +0,0 @@ -
-
-
-

{{policyName}} policy

-

{{item}}

- -
-
-
diff --git a/dashboard/src/app/business/profile/profileCard/suspension-frame/suspension-frame.component.ts b/dashboard/src/app/business/profile/profileCard/suspension-frame/suspension-frame.component.ts deleted file mode 100644 index 66bb6da59..000000000 --- a/dashboard/src/app/business/profile/profileCard/suspension-frame/suspension-frame.component.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Component, OnInit, Input } from '@angular/core'; - -@Component({ - selector: 'app-suspension-frame', - templateUrl: './suspension-frame.component.html', - styleUrls: [ - - ] -}) -export class SuspensionFrameComponent implements OnInit { - data=[]; - policyName:string; - @Input() - set policy(policy: any) { - let extra = policy[1]; - this.policyName = policy[0]; - if(this.policyName === "QoS"){ - let maxIpos ="MaxIOPS = " + extra[":provisionPolicy"].ioConnectivityLoS.maxIOPS + " IOPS/TB"; - this.data.push(maxIpos); - let maxBWS = "MaxBWS = " + extra[":provisionPolicy"].ioConnectivityLoS.maxBWS + " MBPS/TB"; - this.data.push(maxBWS); - }else if(this.policyName === "Replication"){ - let type ="Type = " + extra[":replicationPolicy"].dataProtectionLoS.replicaTypes; - this.data.push(type); - let mode = "Mode = " + extra[":replicationPolicy"].replicaInfos.replicaUpdateMode; - this.data.push(mode); - let Period = "Period = " + extra[":replicationPolicy"].replicaInfos.replicationPeriod +" Minutes"; - this.data.push(Period); - let Bandwidth = "Bandwidth = " + extra[":replicationPolicy"].replicaInfos.replicationBandwidth +" MBPS/TB"; - this.data.push(Bandwidth); - let RGO = "RGO = " + extra[":replicationPolicy"].dataProtectionLoS.recoveryGeographicObject; - this.data.push(RGO); - let RTO = "RTO = " + extra[":replicationPolicy"].dataProtectionLoS.recoveryTimeObjective; - this.data.push(RTO); - let RPO = "RPO = " + extra[":replicationPolicy"].dataProtectionLoS.recoveryPointObjective; - this.data.push(RPO); - let Consistency = "Consistency = " + extra[":replicationPolicy"].replicaInfos.consistencyEnabled; - this.data.push(Consistency); - }else{ - let schedule ="Schedule = " + extra[":snapshotPolicy"].schedule.occurrence; - this.data.push(schedule); - let execution = "Execution Time = " + extra[":snapshotPolicy"].schedule.datetime.split("T")[1] ; - this.data.push(execution); - let Retention = "Retention = " + (extra[":snapshotPolicy"].retention["number"] ? extra[":snapshotPolicy"].retention["number"]: (extra[":snapshotPolicy"].retention.duration+" Days")); - this.data.push(Retention ); - } - }; - constructor() { } - - ngOnInit() { - // console.log(this.policy); - } -} diff --git a/dashboard/src/app/business/profile/storage-pools-table/storage-pools-table.component.html b/dashboard/src/app/business/profile/storage-pools-table/storage-pools-table.component.html deleted file mode 100644 index 701440241..000000000 --- a/dashboard/src/app/business/profile/storage-pools-table/storage-pools-table.component.html +++ /dev/null @@ -1,41 +0,0 @@ - diff --git a/dashboard/src/app/business/profile/storage-pools-table/storage-pools-table.component.ts b/dashboard/src/app/business/profile/storage-pools-table/storage-pools-table.component.ts deleted file mode 100644 index f1fb8ef71..000000000 --- a/dashboard/src/app/business/profile/storage-pools-table/storage-pools-table.component.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Component, OnInit,Input } from '@angular/core'; -import { PoolService } from './../profile.service'; -import { Utils } from '../../../shared/api'; - -@Component({ - selector: 'app-storage-pools-table', - templateUrl: './storage-pools-table.component.html', - styleUrls: [ - - ] -}) -export class StoragePoolsTableComponent implements OnInit { - cols; - totalFreeCapacity = 0; - pools = []; - selectData; - @Input() - set selectProfile(selectProfile: any) { - this.selectData = selectProfile; - this.getPools(); - }; - constructor( - private PoolService: PoolService - ) { } - - getPools() { - this.PoolService.getPools().subscribe((res) => { - this.pools = []; - let pools = res.json(); - if(this.selectData){ - let arrLength = pools.length - for (let i = 0; i < arrLength; i++) { - if (this.selectData.extras.protocol.toLowerCase() == pools[i].extras.ioConnectivity.accessProtocol && this.selectData.storageType == pools[i].extras.dataStorage.provisioningPolicy){ - this.pools.push(pools[i]); - } - } - }else{ - this.pools = pools; - } - - this.pools.map((pool)=>{ - pool.freeCapacityFormat = Utils.getDisplayGBCapacity(pool.freeCapacity); - pool.totalCapacityFormat = Utils.getDisplayGBCapacity(pool.totalCapacity); - }) - - this.totalFreeCapacity = this.getSumCapacity(this.pools, 'free'); - }); - } - - getSumCapacity(pools, FreeOrTotal) { - let SumCapacity: number = 0; - let arrLength = pools.length; - for (let i = 0; i < arrLength; i++) { - if (FreeOrTotal === 'free') { - SumCapacity += pools[i].freeCapacity; - } else { - SumCapacity += pools[i].totalCapacity; - } - } - return SumCapacity; - } - - ngOnInit() { - - this.cols = [ - { field: 'name', header: 'Name' }, - { field: 'freeCapacity', header: 'FreeCapacity' }, - { field: 'totalCapacity', header: 'TotalCapacity' }, - { field: 'extras.advanced.diskType', header: 'Disk' }, - { field: 'extras.dataStorage.provisioningPolicy', header: 'Backend' } - ]; - this.getPools(); - } - -} diff --git a/dashboard/src/app/business/profile/storage-pools-table/storage-pools-table.module.ts b/dashboard/src/app/business/profile/storage-pools-table/storage-pools-table.module.ts deleted file mode 100644 index ec6b1bce2..000000000 --- a/dashboard/src/app/business/profile/storage-pools-table/storage-pools-table.module.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule, APP_INITIALIZER } from '@angular/core'; - -import { TableModule } from './../../../components/common/api'; -import { HttpService } from './../../../shared/api'; -import { PoolService } from './../profile.service'; - -import { StoragePoolsTableComponent } from './storage-pools-table.component'; - -@NgModule({ - declarations: [ - StoragePoolsTableComponent - ], - imports: [ - CommonModule, - TableModule - ], - providers: [ - HttpService, - PoolService - ], - exports: [ - StoragePoolsTableComponent - ], -}) -export class PoolModule { } \ No newline at end of file diff --git a/dashboard/src/app/business/resource/region/region.component.ts b/dashboard/src/app/business/resource/region/region.component.ts deleted file mode 100644 index d6b34c426..000000000 --- a/dashboard/src/app/business/resource/region/region.component.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { Router } from '@angular/router'; -import { Component, OnInit, ViewContainerRef, ViewChild, Directive, ElementRef, HostBinding, HostListener } from '@angular/core'; -import { I18NService } from './../../../../app/shared/api'; -import { AppService } from './../../../../app/app.service'; -import { trigger, state, style, transition, animate} from '@angular/animations'; -import { I18nPluralPipe } from '@angular/common'; - -@Component({ - selector: 'region-table', - templateUrl: './region.html', - styleUrls: [], - animations: [ - trigger('overlayState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]), - - trigger('notificationTopbar', [ - state('hidden', style({ - height: '0', - opacity: 0 - })), - state('visible', style({ - height: '*', - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]) - ] -}) -export class RegionComponent implements OnInit{ - regions = []; - - constructor( - public I18N: I18NService, - // private router: Router - ){} - - ngOnInit() { - this.regions = [ - { "name": this.I18N.keyID['sds_resource_region_default'], "role": "Primary Region", } - ]; - } - - rowSelect(rowdata){ - console.log(rowdata); - } - -} - diff --git a/dashboard/src/app/business/resource/region/region.html b/dashboard/src/app/business/resource/region/region.html deleted file mode 100644 index 9d57a5d9f..000000000 --- a/dashboard/src/app/business/resource/region/region.html +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/dashboard/src/app/business/resource/region/region.module.ts b/dashboard/src/app/business/resource/region/region.module.ts deleted file mode 100644 index c70c8a9bb..000000000 --- a/dashboard/src/app/business/resource/region/region.module.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { NgModule, APP_INITIALIZER } from '@angular/core'; -import { RegionComponent } from './region.component'; -import { ButtonModule, DataTableModule, InputTextModule } from './../../../components/common/api'; - - -@NgModule({ - declarations: [ - RegionComponent - ], - imports: [ - ButtonModule, - DataTableModule, - InputTextModule - ], - exports: [ RegionComponent ], - providers: [] -}) -export class RegionModule { } \ No newline at end of file diff --git a/dashboard/src/app/business/resource/resource.component.ts b/dashboard/src/app/business/resource/resource.component.ts deleted file mode 100644 index 9c2df5f62..000000000 --- a/dashboard/src/app/business/resource/resource.component.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Router } from '@angular/router'; -import { Component, OnInit, ViewContainerRef, ViewChild, Directive, ElementRef, HostBinding, HostListener } from '@angular/core'; -import { I18NService } from '../../../app/shared/api'; -import { AppService } from '../../../app/app.service'; -import { trigger, state, style, transition, animate} from '@angular/animations'; -import { I18nPluralPipe } from '@angular/common'; - -@Component({ - templateUrl: './resource.html', - styleUrls: [], - animations: [ - trigger('overlayState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]), - - trigger('notificationTopbar', [ - state('hidden', style({ - height: '0', - opacity: 0 - })), - state('visible', style({ - height: '*', - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]) - ] -}) -export class ResourceComponent implements OnInit{ - - constructor( - public I18N: I18NService, - // private router: Router - ){} - - ngOnInit() { - - } - -} - diff --git a/dashboard/src/app/business/resource/resource.html b/dashboard/src/app/business/resource/resource.html deleted file mode 100644 index e7727168c..000000000 --- a/dashboard/src/app/business/resource/resource.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/dashboard/src/app/business/resource/resource.module.ts b/dashboard/src/app/business/resource/resource.module.ts deleted file mode 100644 index 2379ecef9..000000000 --- a/dashboard/src/app/business/resource/resource.module.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { NgModule, APP_INITIALIZER } from '@angular/core'; -import { ResourceComponent } from './resource.component'; -import { RouterModule } from '@angular/router'; -import { TabViewModule, ButtonModule } from '../../components/common/api'; - -// 引入region模块 -import { RegionModule } from './region/region.module'; -// 引入zone模块 -import { ZoneModule } from './zone/zone.module'; -// 引入storage模块 -import { StorageModule } from './storage/storage.module'; - -let routers = [{ - path: '', - component: ResourceComponent -}] - -@NgModule({ - declarations: [ - ResourceComponent - ], - imports: [ - RouterModule.forChild(routers), - TabViewModule, - ButtonModule, - RegionModule,//region模块 - ZoneModule,//zone模块 - StorageModule//storage模块 - ], - providers: [] -}) -export class ResourceModule { } \ No newline at end of file diff --git a/dashboard/src/app/business/resource/resource.service.ts b/dashboard/src/app/business/resource/resource.service.ts deleted file mode 100644 index f748d4047..000000000 --- a/dashboard/src/app/business/resource/resource.service.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Injectable } from '@angular/core'; -import { I18NService, HttpService, ParamStorService } from '../../shared/api'; -import { Observable } from 'rxjs'; - -@Injectable() -export class AvailabilityZonesService{ - constructor( - private http: HttpService, - private paramStor: ParamStorService - ) { } - - url = 'v1beta/{project_id}/availabilityZones'; - - //get az - getAZ(param?): Observable{ - return this.http.get(this.url, param); - } - - -} diff --git a/dashboard/src/app/business/resource/storage/storage.component.ts b/dashboard/src/app/business/resource/storage/storage.component.ts deleted file mode 100644 index 3aad4f352..000000000 --- a/dashboard/src/app/business/resource/storage/storage.component.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { Router } from '@angular/router'; -import { Component, OnInit, ViewContainerRef, ViewChild, Directive, ElementRef, HostBinding, HostListener } from '@angular/core'; -import { I18NService, ParamStorService} from 'app/shared/api'; -import { Http } from '@angular/http'; -import { trigger, state, style, transition, animate} from '@angular/animations'; - -@Component({ - selector: 'storage-table', - templateUrl: './storage.html', - styleUrls: [], - animations: [ - trigger('overlayState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]), - - trigger('notificationTopbar', [ - state('hidden', style({ - height: '0', - opacity: 0 - })), - state('visible', style({ - height: '*', - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]) - ] -}) -export class StorageComponent implements OnInit{ - - storages = []; - - constructor( - public I18N: I18NService, - private http: Http, - private paramStor: ParamStorService - ){} - - ngOnInit() { - this.storages = []; - - this.listStorage(); - } - - listStorage(){ - this.storages = []; - let reqUser: any = { params:{} }; - let user_id = this.paramStor.CURRENT_USER().split("|")[1]; - this.http.get("/v3/users/"+ user_id +"/projects", reqUser).subscribe((objRES) => { - let project_id; - objRES.json().projects.forEach(element => { - if(element.name == "admin"){ - project_id = element.id; - } - }) - - let reqPool: any = { params:{} }; - this.http.get("/v1beta/"+ project_id +"/pools", reqPool).subscribe((poolRES) => { - let reqDock: any = { params:{} }; - this.http.get("/v1beta/"+ project_id +"/docks", reqDock).subscribe((dockRES) => { - dockRES.json().forEach(ele => { - let zone = poolRES.json().filter((pool)=>{ - return pool.dockId == ele.id; - })[0].availabilityZone; - let [name,ip,status,description,region,az] = [ele.name, ele.endpoint.split(":")[0], "Enabled", ele.description, "default_region", zone]; - this.storages.push({name,ip,status,description,region,az}); - }) - console.log(this.storages); - }) - }) - }) - } - -} - diff --git a/dashboard/src/app/business/resource/storage/storage.html b/dashboard/src/app/business/resource/storage/storage.html deleted file mode 100644 index e03b3d88b..000000000 --- a/dashboard/src/app/business/resource/storage/storage.html +++ /dev/null @@ -1,19 +0,0 @@ -
-
-
-
- - -
- -
-
- - - - - - - - - \ No newline at end of file diff --git a/dashboard/src/app/business/resource/storage/storage.module.ts b/dashboard/src/app/business/resource/storage/storage.module.ts deleted file mode 100644 index bdf84cfc7..000000000 --- a/dashboard/src/app/business/resource/storage/storage.module.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { NgModule, APP_INITIALIZER } from '@angular/core'; -import { StorageComponent } from './storage.component'; -import { ButtonModule, DataTableModule, InputTextModule } from './../../../components/common/api'; - - -@NgModule({ - declarations: [ - StorageComponent - ], - imports: [ - ButtonModule, - DataTableModule, - InputTextModule - ], - exports: [ - StorageComponent - ], - providers: [] -}) -export class StorageModule { } \ No newline at end of file diff --git a/dashboard/src/app/business/resource/zone/zone.component.ts b/dashboard/src/app/business/resource/zone/zone.component.ts deleted file mode 100644 index e7c6ee3b7..000000000 --- a/dashboard/src/app/business/resource/zone/zone.component.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { Router } from '@angular/router'; -import { Component, OnInit, ViewContainerRef, ViewChild, Directive, ElementRef, HostBinding, HostListener } from '@angular/core'; -import { I18NService, ParamStorService} from 'app/shared/api'; -import { Http } from '@angular/http'; -import { trigger, state, style, transition, animate } from '@angular/animations'; -import {AvailabilityZonesService} from '../resource.service'; - -@Component({ - selector: 'zone-table', - templateUrl: './zone.html', - styleUrls: [], - animations: [ - trigger('overlayState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]), - - trigger('notificationTopbar', [ - state('hidden', style({ - height: '0', - opacity: 0 - })), - state('visible', style({ - height: '*', - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]) - ] -}) -export class ZoneComponent implements OnInit { - - zones = []; - - constructor( - public I18N: I18NService, - private http: Http, - private paramStor: ParamStorService, - private availabilityZonesService: AvailabilityZonesService - ) { } - - ngOnInit() { - - this.listAZ(); - } - - listAZ(){ - this.zones = []; - this.availabilityZonesService.getAZ().subscribe((azRes) => { - let AZs=azRes.json(); - if(AZs && AZs.length !== 0){ - AZs.forEach(item =>{ - let [name,region,description] = [item, "default_region", "--"]; - this.zones.push({name,region,description}); - }) - } - }) - } -} - diff --git a/dashboard/src/app/business/resource/zone/zone.html b/dashboard/src/app/business/resource/zone/zone.html deleted file mode 100644 index 994629a7c..000000000 --- a/dashboard/src/app/business/resource/zone/zone.html +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/dashboard/src/app/business/resource/zone/zone.module.ts b/dashboard/src/app/business/resource/zone/zone.module.ts deleted file mode 100644 index 971390c21..000000000 --- a/dashboard/src/app/business/resource/zone/zone.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { NgModule, APP_INITIALIZER } from '@angular/core'; -import { ZoneComponent } from './zone.component'; -import { ButtonModule, DataTableModule, InputTextModule } from './../../../components/common/api'; -import {AvailabilityZonesService} from '../resource.service'; -import { HttpService } from '../../../shared/service/Http.service'; - -@NgModule({ - declarations: [ - ZoneComponent - ], - imports: [ - ButtonModule, - DataTableModule, - InputTextModule - ], - exports: [ - ZoneComponent - ], - providers: [HttpService,AvailabilityZonesService] -}) -export class ZoneModule { } \ No newline at end of file diff --git a/dashboard/src/app/business/scss-variable.scss b/dashboard/src/app/business/scss-variable.scss deleted file mode 100644 index 11a4a728f..000000000 --- a/dashboard/src/app/business/scss-variable.scss +++ /dev/null @@ -1,75 +0,0 @@ -$color-primary: (normal: #438bd3, hover: #4596e8, active: #1f5fac); -$color-disabled: #c9d1d8; -$color-text: (primary: #657D95, secondary: #8893a6, tertary: #b9c3c8, auxiliary: #c9d1d8); -$color-title: (primary: #2e3039, secondary: #657D95); -$color-splitline: #ecf0f2; -$color-panelbg: #f3f6f7; -$widget-border: (normal: #cfd7db, hover: #98a5bc, focus: #98a5bc, active: #98a5bc); -$widget-bg: (normal: #fdfdfd, hover: #ffffff, focus: #ffffff, active: #f1f1f1); -$border-radius: (small, 3px), -(medium, 10px), -(large, 20px); -@each $type, -$size in $border-radius { - $radius-pos: (tl, $size 0 0 0), (tr, 0 $size 0 0), (br, 0 0 $size 0), (bl, 0 0 0 $size), (top, $size $size 0 0), (right, 0 $size $size 0), (left, $size 0 0 $size), (bottom, 0 0 $size $size), (all, $size); - @each $pos, - $cornerStyle in $radius-pos { - .ui-corner-#{ $pos }-#{ $type } { - -moz-border-radius: $cornerStyle; - -webkit-border-radius: $cornerStyle; - ; - border-radius: $cornerStyle; - } - } -} - -$fontFamily: "Roboto", -"Trebuchet MS", -Arial, -Helvetica, -sans-serif; -$fontSize: 0.14rem; -$borderRadius: 3px; -$disabledOpacity: 0.35; -//Header -$headerBorderWidth: 1px; -$headerBorderColor: #d9d9d9; -$headerBgColor: #f6f7f9; -$headerTextColor: #1b1d1f; -$headerFontWeight: normal; -$headerIconTextColor: #1b1d1f; -//Content -$contentBorderWidth: 1px; -$contentBorderColor: #D5D5D5; -$contentBgColor: #ffffff; -$contentTextColor: map-get($color-text, primary); -//Default State -$stateDefaultBorderWidth: 1px; -$stateDefaultBorderColor: map-get($widget-border, normal); -$stateDefaultBgColor: map-get($widget-bg, normal); -$stateDefaultTextColor: map-get($color-text, primary); -//Active State -$stateActiveBorderColor: map-get($widget-border, active); -$stateActiveBgColor: map-get($widget-bg, active); -$stateActiveTextColor: map-get($color-text, primary); -//Highlight State -$stateHighlightBorderColor: map-get($color-primary, normal); -$stateHighlightBgColor: map-get($color-primary, normal); -$stateHighlightTextColor: #FFFFFF; -//Focus State -$stateFocusBorderColor: map-get($widget-border, focus); -$stateFocusBgColor: map-get($widget-bg, focus); -$stateFocusTextColor: map-get($color-text, primary); -//Error State -$stateErrorBorderColor: #f44336; -$stateErrorBgColor: #f5554a; -$stateErrorTextColor: #cd0a0a; -//Hover State -$stateHoverBorderColor: map-get($widget-border, hover); -$stateHoverBgColor: map-get($widget-bg, hover); -$stateHoverTextColor: map-get($color-text, primary); -//Forms -$inputBgColor: #ffffff; -$inputTextColor: map-get($color-text, primary); -$invalidInputBorderColor: #f44336; -$inputGroupTextColor: map-get($color-text, primary); \ No newline at end of file diff --git a/dashboard/src/app/business/service/service.component.html b/dashboard/src/app/business/service/service.component.html deleted file mode 100644 index 78db672a4..000000000 --- a/dashboard/src/app/business/service/service.component.html +++ /dev/null @@ -1,3 +0,0 @@ -
- 我是service页面 -
\ No newline at end of file diff --git a/dashboard/src/app/business/service/service.component.ts b/dashboard/src/app/business/service/service.component.ts deleted file mode 100644 index 699a7b24b..000000000 --- a/dashboard/src/app/business/service/service.component.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Router } from '@angular/router'; -import { Component, OnInit, ViewContainerRef, ViewChild, Directive, ElementRef, HostBinding, HostListener } from '@angular/core'; -import { I18NService } from 'app/shared/api'; -import { AppService } from 'app/app.service'; -import { trigger, state, style, transition, animate} from '@angular/animations'; -import { I18nPluralPipe } from '@angular/common'; - -@Component({ - templateUrl: './service.component.html', - styleUrls: [], - animations: [ - trigger('overlayState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]), - - trigger('notificationTopbar', [ - state('hidden', style({ - height: '0', - opacity: 0 - })), - state('visible', style({ - height: '*', - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]) - ] -}) -export class ServiceComponent implements OnInit{ - - constructor( - // private I18N: I18NService, - // private router: Router - ){} - - ngOnInit() { - - } - -} diff --git a/dashboard/src/app/business/service/service.module.ts b/dashboard/src/app/business/service/service.module.ts deleted file mode 100644 index 107592ee1..000000000 --- a/dashboard/src/app/business/service/service.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { NgModule, APP_INITIALIZER } from '@angular/core'; -import { ServiceComponent } from './service.component'; -import { RouterModule } from '@angular/router'; - -let routers = [{ - path: '', - component: ServiceComponent -}] - -@NgModule({ - declarations: [ - ServiceComponent - ], - imports: [ RouterModule.forChild(routers) ], - providers: [] -}) -export class ServiceModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/accordion/accordion.css b/dashboard/src/app/components/accordion/accordion.css deleted file mode 100644 index 606e60390..000000000 --- a/dashboard/src/app/components/accordion/accordion.css +++ /dev/null @@ -1,44 +0,0 @@ -.ui-accordion { - width: 100%; -} - -.ui-accordion .ui-accordion-header { - cursor: pointer; - position: relative; - margin-top: 1px; - zoom: 1; -} - -.ui-accordion .ui-accordion-header a { - display: block; - padding: .5em; -} - -.ui-accordion .ui-accordion-content { - padding: 1em; - border-top: 0; - overflow: visible; - zoom: 1; -} - -.ui-accordion .ui-accordion-header.ui-state-disabled, -.ui-accordion .ui-accordion-header.ui-state-disabled a { - cursor: default; -} - -.ui-accordion-content-wrapper-overflown { - overflow: hidden; -} - -.ui-rtl .ui-accordion .ui-accordion-header a { - padding: .5em 2em .5em .5em; -} - -.ui-rtl .ui-accordion .ui-accordion-header > .fa { - left: initial; - right: .5em; -} - -.ui-rtl .ui-accordion .ui-accordion-header > .fa-caret-right::before { - content: '\f0d9'; -} \ No newline at end of file diff --git a/dashboard/src/app/components/accordion/accordion.spec.ts b/dashboard/src/app/components/accordion/accordion.spec.ts deleted file mode 100644 index f165fb0ea..000000000 --- a/dashboard/src/app/components/accordion/accordion.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Accordion } from './accordion'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Accordion', () => { - - let accordion: Accordion; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Accordion - ] - }); - - fixture = TestBed.createComponent(Accordion); - accordion = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/accordion/accordion.ts b/dashboard/src/app/components/accordion/accordion.ts deleted file mode 100644 index fafd16e8e..000000000 --- a/dashboard/src/app/components/accordion/accordion.ts +++ /dev/null @@ -1,209 +0,0 @@ -import { NgModule, Component, ElementRef, AfterContentInit, OnDestroy, Input, Output, EventEmitter, - ContentChildren, QueryList, ChangeDetectorRef, Inject, forwardRef} from '@angular/core'; -import { trigger, state, style, transition, animate } from '@angular/animations'; -import { CommonModule } from '@angular/common'; -import { SharedModule, Header } from '../common/shared'; -import { BlockableUI } from '../common/blockableui'; -import { Subscription } from 'rxjs/Subscription'; - -let idx: number = 0; - -@Component({ - selector: 'p-accordionTab', - template: ` - -
-
- -
-
- `, - animations: [ - trigger('tabContent', [ - state('hidden', style({ - height: '0' - })), - state('visible', style({ - height: '*' - })), - transition('visible <=> hidden', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')) - ]) - ] -}) -export class AccordionTab implements OnDestroy { - - @Input() header: string; - - @Input() selected: boolean; - - @Input() disabled: boolean; - - @Output() selectedChange: EventEmitter = new EventEmitter(); - - @ContentChildren(Header) headerFacet: QueryList
; - - animating: boolean; - - id: string = `ui-accordiontab-${idx++}`; - - constructor( @Inject(forwardRef(() => Accordion)) public accordion: Accordion) {} - - toggle(event) { - if (this.disabled || this.animating) { - return false; - } - - this.animating = true; - let index = this.findTabIndex(); - - if (this.selected) { - this.selected = false; - this.accordion.onClose.emit({ originalEvent: event, index: index }); - } - else { - if (!this.accordion.multiple) { - for (var i = 0; i < this.accordion.tabs.length; i++) { - this.accordion.tabs[i].selected = false; - this.accordion.tabs[i].selectedChange.emit(false); - } - } - - this.selected = true; - this.accordion.onOpen.emit({ originalEvent: event, index: index }); - } - - this.selectedChange.emit(this.selected); - - event.preventDefault(); - } - - findTabIndex() { - let index = -1; - for (var i = 0; i < this.accordion.tabs.length; i++) { - if (this.accordion.tabs[i] == this) { - index = i; - break; - } - } - return index; - } - - get lazy(): boolean { - return this.accordion.lazy; - } - - get hasHeaderFacet(): boolean { - return this.headerFacet && this.headerFacet.length > 0; - } - - onToggleDone(event: Event) { - this.animating = false; - } - - ngOnDestroy() { - this.accordion.tabs.splice(this.findTabIndex(), 1); - } -} - -@Component({ - selector: 'p-accordion', - template: ` -
- -
- ` -}) -export class Accordion implements BlockableUI, AfterContentInit, OnDestroy { - - @Input() multiple: boolean; - - @Output() onClose: EventEmitter = new EventEmitter(); - - @Output() onOpen: EventEmitter = new EventEmitter(); - - @Input() style: any; - - @Input() styleClass: string; - - @Input() expandIcon: string = 'fa fa-fw fa-caret-right'; - - @Input() collapseIcon: string = 'fa fa-fw fa-caret-down'; - - @Input() lazy: boolean; - - @ContentChildren(AccordionTab) tabList: QueryList; - - tabListSubscription: Subscription; - - private _activeIndex: any; - - public tabs: AccordionTab[] = []; - - constructor(public el: ElementRef, public changeDetector: ChangeDetectorRef) {} - - ngAfterContentInit() { - this.initTabs(); - - this.tabListSubscription = this.tabList.changes.subscribe(_ => { - this.initTabs(); - this.changeDetector.markForCheck(); - }); - } - - initTabs(): any { - this.tabs = this.tabList.toArray(); - this.updateSelectionState(); - } - - getBlockableElement(): HTMLElement { - return this.el.nativeElement.children[0]; - } - - @Input() get activeIndex(): any { - return this._activeIndex; - } - - set activeIndex(val: any) { - this._activeIndex = val; - this.updateSelectionState(); - } - - updateSelectionState() { - if (this.tabs && this.tabs.length && this._activeIndex != null) { - for (let i = 0; i < this.tabs.length; i++) { - let selected = this.multiple ? this._activeIndex.includes(i) : (i === this._activeIndex); - let changed = selected !== this.tabs[i].selected; - - if (changed) { - this.tabs[i].animating = true; - } - - this.tabs[i].selected = selected; - this.tabs[i].selectedChange.emit(selected); - } - } - } - - ngOnDestroy() { - if(this.tabListSubscription) { - this.tabListSubscription.unsubscribe(); - } - } -} - -@NgModule({ - imports: [CommonModule], - exports: [Accordion,AccordionTab,SharedModule], - declarations: [Accordion,AccordionTab] -}) -export class AccordionModule { } diff --git a/dashboard/src/app/components/autocomplete/autocomplete.css b/dashboard/src/app/components/autocomplete/autocomplete.css deleted file mode 100644 index 637ed7330..000000000 --- a/dashboard/src/app/components/autocomplete/autocomplete.css +++ /dev/null @@ -1,163 +0,0 @@ -.ui-autocomplete { - width: auto; - zoom: 1; - cursor: pointer; - -moz-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; - position: relative; - display: inline-block; -} - -.ui-autocomplete .ui-autocomplete-dropdown { - height: 100%; - width: 2em; - margin-right: 0; - vertical-align: top; -} - -.ui-autocomplete .ui-autocomplete-input { - padding-right: 1.5em; -} - -.ui-autocomplete-loader { - position: absolute; - right: .25em; - top: 50%; - margin-top: -.5em; -} - -.ui-autocomplete-query { - font-weight: bold; -} - -.ui-autocomplete .ui-autocomplete-panel { - min-width: 100%; -} - -.ui-autocomplete-panel { - position: absolute; - overflow: auto; -} - -.ui-autocomplete-panel .ui-autocomplete-list { - padding: 0.4em; - border: 0 none; -} - -.ui-autocomplete-panel .ui-autocomplete-list-item { - border: 0 none; - cursor: pointer; - font-weight: normal; - margin: 1px 0; - padding: 0.186em 0.313em; - text-align: left; -} - -.ui-autocomplete .ui-button-icon-only, -.ui-autocomplete .ui-button-icon-only:enabled:hover, -.ui-autocomplete .ui-button-icon-only:enabled:focus, -.ui-autocomplete .ui-button-icon-only:enabled:active { - border-left: 0 none; -} - -/* Multiple Selection */ -.ui-autocomplete-multiple-container { - display: inline-block; - vertical-align: middle; -} - -.ui-autocomplete-multiple-container.ui-inputtext { - clear: left; - cursor: text; - list-style-type: none; - margin: 0; - overflow: hidden; - padding: 0 1.5em 0 .25em; -} - -.ui-autocomplete-token { - cursor: default; - display: inline-block; - vertical-align: middle; - overflow: hidden; - padding: .125em .5em; - white-space: nowrap; - position: relative; - margin-right: .125em; - border: 0 none; - font-size: .9em; -} - -.ui-autocomplete-token-label { - display: block; - margin-right: 2em; -} - -.ui-autocomplete-token-icon { - margin-top: -.5em; - position: absolute; - right: 0.2em; - top: 50%; - cursor: pointer; -} - -.ui-autocomplete-input-token { - display: inline-block; - vertical-align: middle; - list-style-type: none; - margin: 0 0 0 .125em; - padding: .25em .25em .25em 0; -} - -.ui-autocomplete-input-token input { - border: 0 none; - width: 10em; - outline: medium none; - background-color: transparent; - margin: 0; - padding: 0; - box-shadow: none; - -moz-border-radius: 0; - -webkit-border-radius: 0; - border-radius: 0; -} - -.ui-autocomplete-dd .ui-autocomplete-loader { - right: 2.25em; -} - -.ui-autocomplete-dd input.ui-corner-all , -.ui-autocomplete-dd .ui-autocomplete-multiple-container.ui-corner-all { - -moz-border-radius-topright: 0px; - -webkit-border-top-right-radius: 0px; - border-top-right-radius: 0px; - -moz-border-radius-bottomright: 0px; - -webkit-border-bottom-right-radius: 0px; - border-bottom-right-radius: 0px; - } - -.ui-autocomplete-dd .ui-autocomplete-dropdown.ui-corner-all { - -moz-border-radius-topleft: 0px; - -webkit-border-top-left-radius: 0px; - border-top-left-radius: 0px; - -moz-border-radius-bottomleft: 0px; - -webkit-border-bottom-left-radius: 0px; - border-bottom-left-radius: 0px; -} - -/** AutoComplete **/ -.ui-fluid p-autocomplete, -.ui-fluid .ui-autocomplete, -.ui-fluid .ui-autocomplete-input { - width: 100%; -} - -.ui-fluid .ui-autocomplete.ui-autocomplete-dd .ui-autocomplete-input, -.ui-fluid .ui-autocomplete.ui-autocomplete-dd .ui-autocomplete-multiple-container { - width: calc(100% - 2em); -} - -.ui-fluid .ui-autocomplete .ui-autocomplete-dropdown.ui-button { - width: 2em; -} diff --git a/dashboard/src/app/components/autocomplete/autocomplete.spec.ts b/dashboard/src/app/components/autocomplete/autocomplete.spec.ts deleted file mode 100644 index 8272d75f2..000000000 --- a/dashboard/src/app/components/autocomplete/autocomplete.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { AutoComplete } from './autocomplete'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('AutoComplete', () => { - - let autocomplete: AutoComplete; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - AutoComplete - ] - }); - - fixture = TestBed.createComponent(AutoComplete); - autocomplete = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/autocomplete/autocomplete.ts b/dashboard/src/app/components/autocomplete/autocomplete.ts deleted file mode 100644 index edc3c56e4..000000000 --- a/dashboard/src/app/components/autocomplete/autocomplete.ts +++ /dev/null @@ -1,643 +0,0 @@ -import {NgModule,Component,ViewChild,ElementRef,AfterViewInit,AfterContentInit,DoCheck,AfterViewChecked,Input,Output,EventEmitter,ContentChildren,QueryList,TemplateRef,Renderer2,forwardRef,ChangeDetectorRef,IterableDiffers} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {InputTextModule} from '../inputtext/inputtext'; -import {ButtonModule} from '../button/button'; -import {SharedModule,PrimeTemplate} from '../common/shared'; -import {DomHandler} from '../dom/domhandler'; -import {ObjectUtils} from '../utils/objectutils'; -import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; - -export const AUTOCOMPLETE_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => AutoComplete), - multi: true -}; - -@Component({ - selector: 'p-autoComplete', - template: ` - -
    -
  • - - {{field ? objectUtils.resolveFieldData(val, field): val}} - -
  • -
  • - -
  • -
-
-
    -
  • - {{field ? objectUtils.resolveFieldData(option, field) : option}} - -
  • -
  • {{emptyMessage}}
  • -
-
-
- `, - host: { - '[class.ui-inputwrapper-filled]': 'filled', - '[class.ui-inputwrapper-focus]': 'focus' - }, - providers: [DomHandler,ObjectUtils,AUTOCOMPLETE_VALUE_ACCESSOR] -}) -export class AutoComplete implements AfterViewInit,AfterViewChecked,DoCheck,ControlValueAccessor { - - @Input() minLength: number = 1; - - @Input() delay: number = 300; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() inputStyle: any; - - @Input() inputId: string; - - @Input() inputStyleClass: string; - - @Input() placeholder: string; - - @Input() readonly: boolean; - - @Input() disabled: boolean; - - @Input() maxlength: number; - - @Input() required: boolean; - - @Input() size: number; - - @Input() appendTo: any; - - @Input() autoHighlight: boolean; - - @Input() forceSelection: boolean; - - @Input() type: string = 'text'; - - @Output() completeMethod: EventEmitter = new EventEmitter(); - - @Output() onSelect: EventEmitter = new EventEmitter(); - - @Output() onUnselect: EventEmitter = new EventEmitter(); - - @Output() onFocus: EventEmitter = new EventEmitter(); - - @Output() onBlur: EventEmitter = new EventEmitter(); - - @Output() onDropdownClick: EventEmitter = new EventEmitter(); - - @Output() onClear: EventEmitter = new EventEmitter(); - - @Output() onKeyUp: EventEmitter = new EventEmitter(); - - @Input() field: string; - - @Input() scrollHeight: string = '200px'; - - @Input() dropdown: boolean; - - @Input() dropdownMode: string = 'blank'; - - @Input() multiple: boolean; - - @Input() tabindex: number; - - @Input() dataKey: string; - - @Input() emptyMessage: string; - - @Input() immutable: boolean = true; - - @ViewChild('in') inputEL: ElementRef; - - @ViewChild('multiIn') multiInputEL: ElementRef; - - @ViewChild('panel') panelEL: ElementRef; - - @ViewChild('multiContainer') multiContainerEL: ElementRef; - - @ViewChild('ddBtn') dropdownButton: ElementRef; - - @ContentChildren(PrimeTemplate) templates: QueryList; - - itemTemplate: TemplateRef; - - selectedItemTemplate: TemplateRef; - - value: any; - - _suggestions: any[]; - - onModelChange: Function = () => {}; - - onModelTouched: Function = () => {}; - - timeout: any; - - panelVisible: boolean = false; - - documentClickListener: any; - - suggestionsUpdated: boolean; - - highlightOption: any; - - highlightOptionChanged: boolean; - - focus: boolean = false; - - filled: boolean; - - inputClick: boolean; - - inputKeyDown: boolean; - - noResults: boolean; - - differ: any; - - inputFieldValue: string = null; - - loading: boolean; - - constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2, public objectUtils: ObjectUtils, public cd: ChangeDetectorRef, public differs: IterableDiffers) { - this.differ = differs.find([]).create(null); - } - - @Input() get suggestions(): any[] { - return this._suggestions; - } - - set suggestions(val:any[]) { - this._suggestions = val; - if(this.immutable) { - this.handleSuggestionsChange(); - } - } - - ngDoCheck() { - if(!this.immutable) { - let changes = this.differ.diff(this.suggestions); - if(changes) { - this.handleSuggestionsChange(); - } - } - } - - handleSuggestionsChange() { - if(this.panelEL && this.panelEL.nativeElement && this.loading) { - this.highlightOption = null; - if(this._suggestions && this._suggestions.length) { - this.noResults = false; - this.show(); - this.suggestionsUpdated = true; - - if(this.autoHighlight) { - this.highlightOption = this._suggestions[0]; - } - } - else { - this.noResults = true; - - if(this.emptyMessage) { - this.show(); - this.suggestionsUpdated = true; - } - else { - this.hide(); - } - } - } - - this.loading = false; - } - - ngAfterContentInit() { - this.templates.forEach((item) => { - switch(item.getType()) { - case 'item': - this.itemTemplate = item.template; - break; - - case 'selectedItem': - this.selectedItemTemplate = item.template; - break; - - default: - this.itemTemplate = item.template; - break; - } - }); - } - - ngAfterViewInit() { - if(this.appendTo) { - if(this.appendTo === 'body') - document.body.appendChild(this.panelEL.nativeElement); - else - this.domHandler.appendChild(this.panelEL.nativeElement, this.appendTo); - } - } - - ngAfterViewChecked() { - //Use timeouts as since Angular 4.2, AfterViewChecked is broken and not called after panel is updated - if(this.suggestionsUpdated && this.panelEL.nativeElement && this.panelEL.nativeElement.offsetParent) { - setTimeout(() => this.align(), 1); - this.suggestionsUpdated = false; - } - - if(this.highlightOptionChanged) { - setTimeout(() => { - let listItem = this.domHandler.findSingle(this.panelEL.nativeElement, 'li.ui-state-highlight'); - if(listItem) { - this.domHandler.scrollInView(this.panelEL.nativeElement, listItem); - } - }, 1); - this.highlightOptionChanged = false; - } - } - - writeValue(value: any) : void { - this.value = value; - this.filled = this.value && this.value != ''; - this.updateInputField(); - } - - registerOnChange(fn: Function): void { - this.onModelChange = fn; - } - - registerOnTouched(fn: Function): void { - this.onModelTouched = fn; - } - - setDisabledState(val: boolean): void { - this.disabled = val; - } - - onInput(event: KeyboardEvent) { - if(!this.inputKeyDown) { - return; - } - - if(this.timeout) { - clearTimeout(this.timeout); - } - - let value = ( event.target).value; - if(!this.multiple && !this.forceSelection) { - this.onModelChange(value); - } - - if(value.length === 0) { - this.hide(); - this.onClear.emit(event); - } - - if(value.length >= this.minLength) { - this.timeout = setTimeout(() => { - this.search(event, value); - }, this.delay); - } - else { - this.suggestions = null; - this.hide(); - } - this.updateFilledState(); - this.inputKeyDown = false; - } - - onInputClick(event: MouseEvent) { - if(this.documentClickListener) { - this.inputClick = true; - } - } - - search(event: any, query: string) { - //allow empty string but not undefined or null - if(query === undefined || query === null) { - return; - } - - this.loading = true; - - this.completeMethod.emit({ - originalEvent: event, - query: query - }); - } - - selectItem(option: any, focus: boolean = true) { - if(this.multiple) { - this.multiInputEL.nativeElement.value = ''; - this.value = this.value||[]; - if(!this.isSelected(option)) { - this.value = [...this.value,option]; - this.onModelChange(this.value); - } - } - else { - this.inputEL.nativeElement.value = this.field ? this.objectUtils.resolveFieldData(option, this.field)||'': option; - this.value = option; - this.onModelChange(this.value); - } - - this.onSelect.emit(option); - this.updateFilledState(); - this._suggestions = null; - - if(focus) { - this.focusInput(); - } - } - - show() { - if(this.multiInputEL || this.inputEL) { - let hasFocus = this.multiple ? document.activeElement == this.multiInputEL.nativeElement : document.activeElement == this.inputEL.nativeElement ; - if(!this.panelVisible && hasFocus) { - this.panelVisible = true; - if(this.appendTo) { - this.panelEL.nativeElement.style.minWidth = this.domHandler.getWidth(this.el.nativeElement.children[0]) + 'px'; - } - this.panelEL.nativeElement.style.zIndex = ++DomHandler.zindex; - this.domHandler.fadeIn(this.panelEL.nativeElement, 200); - this.bindDocumentClickListener(); - } - } - } - - align() { - if(this.appendTo) - this.domHandler.absolutePosition(this.panelEL.nativeElement, (this.multiple ? this.multiContainerEL.nativeElement : this.inputEL.nativeElement)); - else - this.domHandler.relativePosition(this.panelEL.nativeElement, (this.multiple ? this.multiContainerEL.nativeElement : this.inputEL.nativeElement)); - } - - hide() { - this.panelVisible = false; - this.unbindDocumentClickListener(); - } - - handleDropdownClick(event) { - this.focusInput(); - let queryValue = this.multiple ? this.multiInputEL.nativeElement.value : this.inputEL.nativeElement.value; - - if(this.dropdownMode === 'blank') - this.search(event, ''); - else if(this.dropdownMode === 'current') - this.search(event, queryValue); - - this.onDropdownClick.emit({ - originalEvent: event, - query: queryValue - }); - } - - focusInput() { - if(this.multiple) - this.multiInputEL.nativeElement.focus(); - else - this.inputEL.nativeElement.focus(); - } - - removeItem(item: any) { - let itemIndex = this.domHandler.index(item); - let removedValue = this.value[itemIndex]; - this.value = this.value.filter((val, i) => i!=itemIndex); - this.onModelChange(this.value); - this.updateFilledState(); - this.onUnselect.emit(removedValue); - } - - onKeydown(event) { - if(this.panelVisible) { - let highlightItemIndex = this.findOptionIndex(this.highlightOption); - - switch(event.which) { - //down - case 40: - if(highlightItemIndex != -1) { - var nextItemIndex = highlightItemIndex + 1; - if(nextItemIndex != (this.suggestions.length)) { - this.highlightOption = this.suggestions[nextItemIndex]; - this.highlightOptionChanged = true; - } - } - else { - this.highlightOption = this.suggestions[0]; - } - - event.preventDefault(); - break; - - //up - case 38: - if(highlightItemIndex > 0) { - let prevItemIndex = highlightItemIndex - 1; - this.highlightOption = this.suggestions[prevItemIndex]; - this.highlightOptionChanged = true; - } - - event.preventDefault(); - break; - - //enter - case 13: - if(this.highlightOption) { - this.selectItem(this.highlightOption); - this.hide(); - } - event.preventDefault(); - break; - - //escape - case 27: - this.hide(); - event.preventDefault(); - break; - - - //tab - case 9: - if(this.highlightOption) { - this.selectItem(this.highlightOption); - } - this.hide(); - break; - } - } else { - if(event.which === 40 && this.suggestions) { - this.search(event,event.target.value); - } - } - - if(this.multiple) { - switch(event.which) { - //backspace - case 8: - if(this.value && this.value.length && !this.multiInputEL.nativeElement.value) { - this.value = [...this.value]; - let removedValue = this.value.pop(); - this.onUnselect.emit(removedValue); - this.onModelChange(this.value); - } - break; - } - } - - this.inputKeyDown = true; - } - - onKeyup(event) { - this.onKeyUp.emit(event); - } - - onInputFocus(event) { - this.focus = true; - this.onFocus.emit(event); - } - - onInputBlur(event) { - this.focus = false; - this.onModelTouched(); - this.onBlur.emit(event); - } - - onInputChange(event) { - if(this.forceSelection && this.suggestions) { - let valid = false; - let inputValue = event.target.value.trim(); - - if(this.suggestions) { - for(let suggestion of this.suggestions) { - let itemValue = this.field ? this.objectUtils.resolveFieldData(suggestion, this.field) : suggestion; - if(itemValue && inputValue === itemValue.trim()) { - valid = true; - this.selectItem(suggestion, false); - break; - } - } - } - - if(!valid) { - if(this.multiple) { - this.multiInputEL.nativeElement.value = ''; - } - else { - this.value = null; - this.inputEL.nativeElement.value = ''; - } - - this.onModelChange(this.value); - } - } - } - - isSelected(val: any): boolean { - let selected: boolean = false; - if(this.value && this.value.length) { - for(let i = 0; i < this.value.length; i++) { - if(this.objectUtils.equals(this.value[i], val, this.dataKey)) { - selected = true; - break; - } - } - } - return selected; - } - - findOptionIndex(option): number { - let index: number = -1; - if(this.suggestions) { - for(let i = 0; i < this.suggestions.length; i++) { - if(this.objectUtils.equals(option, this.suggestions[i])) { - index = i; - break; - } - } - } - - return index; - } - - updateFilledState() { - if(this.multiple) - this.filled = (this.value && this.value.length) || (this.multiInputEL && this.multiInputEL.nativeElement && this.multiInputEL.nativeElement.value != ''); - else - this.filled = (this.inputFieldValue && this.inputFieldValue != '') || (this.inputEL && this.inputEL.nativeElement && this.inputEL.nativeElement.value != '');; - } - - updateInputField() { - let formattedValue = this.value ? (this.field ? this.objectUtils.resolveFieldData(this.value, this.field)||'' : this.value) : ''; - this.inputFieldValue = formattedValue; - - if(this.inputEL && this.inputEL.nativeElement) { - this.inputEL.nativeElement.value = formattedValue; - } - - this.updateFilledState(); - } - - bindDocumentClickListener() { - if(!this.documentClickListener) { - this.documentClickListener = this.renderer.listen('document', 'click', (event) => { - if(event.which === 3) { - return; - } - - if(!this.inputClick && !this.isDropdownClick(event)) { - this.hide(); - } - - this.inputClick = false; - this.cd.markForCheck(); - }); - } - } - - isDropdownClick(event) { - if(this.dropdown) { - let target = event.target; - return (target === this.dropdownButton.nativeElement || target.parentNode === this.dropdownButton.nativeElement); - } - else { - return false; - } - } - - unbindDocumentClickListener() { - if(this.documentClickListener) { - this.documentClickListener(); - this.documentClickListener = null; - } - } - - ngOnDestroy() { - this.unbindDocumentClickListener(); - - if(this.appendTo) { - this.el.nativeElement.appendChild(this.panelEL.nativeElement); - } - } -} - -@NgModule({ - imports: [CommonModule,InputTextModule,ButtonModule,SharedModule], - exports: [AutoComplete,SharedModule], - declarations: [AutoComplete] -}) -export class AutoCompleteModule { } diff --git a/dashboard/src/app/components/badge/badge.scss b/dashboard/src/app/components/badge/badge.scss deleted file mode 100644 index f99ab601a..000000000 --- a/dashboard/src/app/components/badge/badge.scss +++ /dev/null @@ -1,117 +0,0 @@ -@keyframes statusProcessing { - 0% { - -webkit-transform: scale(.8); - transform: scale(.8); - opacity: .5 - } - to { - -webkit-transform: scale(2.4); - transform: scale(2.4); - opacity: 0 - } -} - -.ui-badge{ - display: inline-block; - height: .2rem; - width:auto; - min-width: .2rem; - position: absolute; - top: -.1rem; - right: 0rem; - overflow: hidden; - border-radius: .1rem; - background: nth(nth($color-alert,2),2); - color: white; - line-height: .2rem; - text-align: center; - padding: 0 .06rem; - font-size: .12rem; - white-space: nowrap; - transform: translateX(50%); - transform-origin: center center; - transition:width ease-in .3s; - z-index:9; - user-select: none; - &.ui-badge-dot{ - width: .1rem; - min-width: .1rem; - height:.1rem; - padding: 0; - top: -.05rem; - &.ui-badge-status-content{ - background-color: transparent; - transform: none; - top: 0; - overflow: visible; - font-size: 0; - line-height: .2rem; - height: .2rem; - width: auto; - position: relative; - .ui-badge-status{ - position:relative; - display: inline-block; - width:.1rem; - height:.1rem; - border-radius: .05rem; - vertical-align: middle; - &.ui-badge-status-success{ - background-color: nth(nth($color-alert,1),2); - } - &.ui-badge-status-processing{ - background-color: nth(nth($color-alert,3),2); - &::after{ - position: absolute; - top: -.01rem; - left: -.01rem; - width: 100%; - height: 100%; - border-radius: 50%; - border: 1px solid nth(nth($color-alert,3),2); - content: ""; - animation: statusProcessing 1.2s infinite ease-in-out; - } - } - &.ui-badge-status-default{ - background-color: nth(nth($color-alert,5),2); - } - &.ui-badge-status-warning{ - background-color: nth(nth($color-alert,4),2); - } - &.ui-badge-status-error{ - background-color: nth(nth($color-alert,2),2); - } - } - .ui-badge-status-text{ - font-size:.14rem; - color: map-get($color-text, primary); - padding-left: .08rem; - vertical-align: middle; - } - } - } - &.ui-badge-hide{ - display: none; - } - .ui-badge-counts{ - width: 100%; - height: 100%; - position: relative; - overflow: hidden; - display: block; - font-size:0; - .ui-badge-counts-item{ - display: inline-block; - transition: transform ease-in-out .3s; - p{ - width: 100%; - padding: 0; - margin:0; - line-height: .2rem; - font-size: .12rem; - color:inherit; - } - } - } -} \ No newline at end of file diff --git a/dashboard/src/app/components/badge/badge.ts b/dashboard/src/app/components/badge/badge.ts deleted file mode 100644 index d5fe91524..000000000 --- a/dashboard/src/app/components/badge/badge.ts +++ /dev/null @@ -1,196 +0,0 @@ -import {NgModule,Directive, ElementRef,OnInit,AfterViewInit,OnDestroy,Input,Output,SimpleChange,EventEmitter,forwardRef,Renderer} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import { DomHandler } from '../dom/domhandler'; - -@Directive({ - selector: '[pBadge]', - providers:[DomHandler] -}) -export class Badge implements OnInit,AfterViewInit{ - @Input('animate') animate:boolean = true; - - public _show:boolean = true; - - @Input('show') get show():boolean{ - return this._show; - } - - set show(val:boolean){ - this._show = val; - this.toggle(); - this.onBadgeChange.emit({'show':this.show,'count':this.count,'overflowCount':this.overflowCount}); - } - - public _count:number; - - get count():number{ - return this._count; - } - - @Input('pBadge') set count(val:number){ - this._count = val>=0?val:0; - this.onCountChange(val); - this.onBadgeChange.emit({'show':this.show,'count':this.count,'overflowCount':this.overflowCount}); - } - - @Input('dot') dot:boolean = false; - - @Input() overflowCount:number = 99; - - @Input() showZero:boolean = false; - - @Input('status') status:string;//Enum{ 'success', 'processing, 'default', 'error', 'warning' } - - @Input('text') text:string; - - @Input('style') style:any; - - @Output() onBadgeChange:EventEmitter = new EventEmitter(); - - public container:any; - - constructor(public el: ElementRef,private domHnadler: DomHandler, public renderer: Renderer) {} - - ngOnInit(){ - if(this.status){ - this.dot = true; - } - this.createContainer(); - } - - ngAfterViewInit(){ - this.el.nativeElement.style.position = 'relative'; - this.el.nativeElement.style.overflow = 'visible'; - if(this.style){ - this.updateContainerStyle(this.style); - } - } - - createContainer(){ - if(this.count == 0 && !this.showZero) return; - if(this.container) this.el.nativeElement.removeChild(this.container); - this.container = document.createElement('span'); - this.container.className = 'ui-badge ui-widget'; - - if(!this.show){ - this.container.classList.add('ui-badge-hide'); - } - - if(this.dot){ - this.container.classList.add('ui-badge-dot'); - if(this.status){ - this.updateStatus(); - return; - } - } else { - this.container.title = '' + this.count || ''; - } - - this.updateContainerStyle(this.style); - this.updateCountsHtml(); - this.el.nativeElement.appendChild(this.container); - } - - updateContainerStyle(style:any){ - if(!this.container || typeof style !== 'object') return; - for(let key in style){ - this.container.style[key] = style[key]; - } - } - - updateCountsHtml(){ - if(!this.container || this.dot) return; - if(this.animate && this.count <= this.overflowCount){ - if(this.domHnadler.find(this.container,'.ui-badge-counts').length > 0) return; - - let countsContainer = document.createElement('span'); - countsContainer.className = 'ui-badge-counts'; - let overflowArr = (this.overflowCount + '').split(''); - let countArr = (this.count + '').split(''); - for(let i = 0;i' + j + '

'; - } - countsContainer.appendChild(countsItem); - } - this.container.innerHTML = ''; - this.container.appendChild(countsContainer); - } else { - this.container.innerText = this.count > this.overflowCount?this.overflowCount + '+':this.count + ''; - } - } - - updateStatus(){ - if(!this.container || !this.status) return; - - this.container.classList.add('ui-badge-status-content'); - this.container.innerHTML = ''; - this.container.innerHTML += ''; - - if(this.text){ - this.container.innerHTML += '' + this.text + ''; - } - this.el.nativeElement.appendChild(this.container); - } - - updateCountsPosition(){ - if(!this.animate || this.count > this.overflowCount || this.dot) return; - let overflowArr = (this.overflowCount + '').split(''); - let countArr = (this.count + '').split(''); - let countsContainer = this.domHnadler.find(this.container,'.ui-badge-counts')[0]; - let counteItems = countsContainer.childNodes; - for(let i = 0;i < overflowArr.length;i++){ - if(countArr[i]){ - counteItems[i].style.display = 'inline-block'; - counteItems[i].style.transform = 'translateY(-' + 10 * parseInt(countArr[i]) + '%)'; - for(let j = 0;j < 10;j++){ - counteItems[i].childNodes[j].classList.remove('active'); - if(countArr[i] == j + ''){ - counteItems[i].childNodes[j].classList.add('active'); - } - } - } else { - counteItems[i].style.display = 'none'; - counteItems[i].style.transform = 'translateY(0%)'; - } - - } - } - - onCountChange(count:number):void{ - if(this.dot || this.status) return; - if(!this.container){ - this.createContainer(); - return; - } - this.container.title = '' + this.count || ''; - if(this.count < this.overflowCount && this.animate){ - this.updateCountsHtml(); - this.updateCountsPosition(); - } else { - this.updateCountsHtml(); - } - - } - - toggle(){ - if(!this.container) return; - if(this.show){ - this.container.classList.remove('ui-badge-hide'); - } else { - this.container.classList.add('ui-badge-hide'); - } - } - -} - -@NgModule({ - imports: [CommonModule], - exports: [Badge], - declarations: [Badge] -}) -export class BadgeModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/blockui/blockui.css b/dashboard/src/app/components/blockui/blockui.css deleted file mode 100644 index 4b00320e6..000000000 --- a/dashboard/src/app/components/blockui/blockui.css +++ /dev/null @@ -1,11 +0,0 @@ -.ui-blockui { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; -} - -.ui-blockui-document { - position: fixed; -} \ No newline at end of file diff --git a/dashboard/src/app/components/blockui/blockui.spec.ts b/dashboard/src/app/components/blockui/blockui.spec.ts deleted file mode 100644 index 34b14af22..000000000 --- a/dashboard/src/app/components/blockui/blockui.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { BlockUI } from './blockui'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('BlockUI', () => { - - let blockui: BlockUI; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - BlockUI - ] - }); - - fixture = TestBed.createComponent(BlockUI); - blockui = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/blockui/blockui.ts b/dashboard/src/app/components/blockui/blockui.ts deleted file mode 100644 index a2c6fcba5..000000000 --- a/dashboard/src/app/components/blockui/blockui.ts +++ /dev/null @@ -1,80 +0,0 @@ -import {NgModule,Component,Input,AfterViewInit,OnDestroy,EventEmitter,ElementRef,ViewChild} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; -import {BlockableUI} from '../common/blockableui'; - -@Component({ - selector: 'p-blockUI', - template: ` -
- -
- `, - providers: [DomHandler] -}) -export class BlockUI implements AfterViewInit,OnDestroy { - - @Input() target: any; - - @Input() autoZIndex: boolean = true; - - @Input() baseZIndex: number = 0; - - @ViewChild('mask') mask: ElementRef; - - _blocked: boolean; - - constructor(public el: ElementRef,public domHandler: DomHandler) {} - - @Input() get blocked(): boolean { - return this._blocked; - } - - set blocked(val: boolean) { - this._blocked = val; - - if(this.mask.nativeElement) { - if(this._blocked) - this.block(); - else - this.unblock(); - } - } - - ngAfterViewInit() { - if(this.target && !this.target.getBlockableElement) { - throw 'Target of BlockUI must implement BlockableUI interface'; - } - } - - block() { - if(this.target) { - this.target.getBlockableElement().appendChild(this.mask.nativeElement); - let style = this.target.style||{}; - style.position = 'relative'; - this.target.style = style; - } - else { - document.body.appendChild(this.mask.nativeElement); - } - - if(this.autoZIndex) { - this.mask.nativeElement.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex)); - } - } - - unblock() { - this.el.nativeElement.appendChild(this.mask.nativeElement); - } - - ngOnDestroy() { - this.unblock(); - } -} - -@NgModule({ - imports: [CommonModule], - exports: [BlockUI], - declarations: [BlockUI] -}) -export class BlockUIModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/breadcrumb/breadcrumb.css b/dashboard/src/app/components/breadcrumb/breadcrumb.css deleted file mode 100644 index ed4a7785a..000000000 --- a/dashboard/src/app/components/breadcrumb/breadcrumb.css +++ /dev/null @@ -1,21 +0,0 @@ -/** Breadcrumb **/ - -.ui-breadcrumb { - margin: 0; - padding: 0; - padding: .3em; -} - -.ui-breadcrumb ul { - margin: 0; - padding: 0; -} - -.ui-breadcrumb ul li { - display: inline-block; - vertical-align: middle; -} - -.ui-breadcrumb ul li .ui-menuitem-link { - text-decoration: none; -} \ No newline at end of file diff --git a/dashboard/src/app/components/breadcrumb/breadcrumb.spec.ts b/dashboard/src/app/components/breadcrumb/breadcrumb.spec.ts deleted file mode 100644 index fe715566f..000000000 --- a/dashboard/src/app/components/breadcrumb/breadcrumb.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Breadcrumb } from './breadcrumb'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Breadcrumb', () => { - - let breadcrumb: Breadcrumb; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Breadcrumb - ] - }); - - fixture = TestBed.createComponent(Breadcrumb); - breadcrumb = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/breadcrumb/breadcrumb.ts b/dashboard/src/app/components/breadcrumb/breadcrumb.ts deleted file mode 100644 index d6d973778..000000000 --- a/dashboard/src/app/components/breadcrumb/breadcrumb.ts +++ /dev/null @@ -1,80 +0,0 @@ -import {NgModule,Component,Input} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {MenuItem} from '../common/menuitem'; -import {Location} from '@angular/common'; -import {RouterModule} from '@angular/router'; - -@Component({ - selector: 'p-breadcrumb', - template: ` - - ` -}) -export class Breadcrumb { - - @Input() model: MenuItem[]; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() home: MenuItem; - - itemClick(event, item: MenuItem) { - if(item.disabled) { - event.preventDefault(); - return; - } - - if(!item.url) { - event.preventDefault(); - } - - if(item.command) { - item.command({ - originalEvent: event, - item: item - }); - } - } - - onHomeClick(event) { - if(this.home) { - this.itemClick(event, this.home); - } - } -} - -@NgModule({ - imports: [CommonModule,RouterModule], - exports: [Breadcrumb,RouterModule], - declarations: [Breadcrumb] -}) -export class BreadcrumbModule { } diff --git a/dashboard/src/app/components/button/button.scss b/dashboard/src/app/components/button/button.scss deleted file mode 100644 index 129671202..000000000 --- a/dashboard/src/app/components/button/button.scss +++ /dev/null @@ -1,324 +0,0 @@ -/* Button */ - -.ui-button { - display: inline-block; - position: relative; - padding: 0 0.25rem; - margin-right: .1rem; - text-decoration: none !important; - cursor: pointer; - text-align: center; - min-width: 1.00rem; - zoom: 1; - overflow: visible; - /* the overflow property removes extra width in IE */ - &:enabled:hover { - box-shadow: 0px 4px 8px #e3e3e3; - border-color: map-get($widget-border, normal); - } - &.ui-button-icon-only { - margin-right: 0; - padding: 0 0.05rem; - border: none; - background: none; - &:hover, - &:active { - border: none; - background: none; - box-shadow: none; - color: map-get($map: $color-primary, $key: hover); - } - &:active { - color: map-get($map: $color-primary, $key: active); - } - } - &.ui-button-large { - padding: 0 0.40rem; - .ui-button-text { - line-height: 0.38rem; - } - } -} - -.ui-button-icon-only { - min-width: 0; -} - -p-button { - display: inline-block; -} - - -/*button text element */ - -.ui-button .ui-button-text { - display: block; - line-height: 0.30rem; -} - -.ui-button-text-only .ui-button-text { - padding: 0; -} - -.ui-button-icon-only .ui-button-text, -.ui-button-text-empty .ui-button-text { - text-indent: -9999999px; - overflow: hidden; -} - -.ui-button-text-icon-left { - padding: 0 0.2rem 0 0.40rem; -} - -.ui-button-text-icon-right { - padding: 0 0.40rem 0 0.2rem; -} - - -/*button icon element(s) */ - -.ui-button-icon-only .fa, -.ui-button-text-icon-left .fa, -.ui-button-text-icon-right .fa { - position: absolute; - top: 50%; - margin-top: -0.08rem; - height: 0.16rem; -} - -.ui-button-icon-only .fa { - top: 50%; - left: 50%; - margin-top: -0.08rem; - margin-left: -0.08rem; - width: 0.16rem; - height: 0.16rem; -} - -.ui-button-icon-left { - left: -0.40rem; -} - -.ui-button-icon-right { - right: -0.40rem; -} - - -/*button sets*/ - -.ui-buttonset .ui-button { - margin-left: 0; - margin-right: 0; -} - - -/* workarounds */ - -button.ui-button::-moz-focus-inner { - border: 0; - padding: 0; - /* reset extra padding in Firefox */ -} - - -/** Fluid **/ - -.ui-fluid .ui-button { - width: 100%; -} - -.ui-fluid .ui-button-text-icon-left .ui-button-text, -.ui-fluid .ui-button-text-icon-right .ui-button-text { - padding-left: 0.1rem; - padding-right: 0.1rem; -} - - -/** ButtonSet **/ - -.ui-fluid .ui-buttonset { - width: 100%; -} - -.ui-fluid .ui-buttonset.ui-buttonset-1 .ui-button { - width: 100%; -} - -.ui-fluid .ui-buttonset.ui-buttonset-2 .ui-button { - width: 50%; -} - -.ui-fluid .ui-buttonset.ui-buttonset-3 .ui-button { - width: 33.3%; -} - -.ui-fluid .ui-buttonset.ui-buttonset-4 .ui-button { - width: 25%; -} - -.ui-fluid .ui-buttonset.ui-buttonset-5 .ui-button { - width: 20%; -} - -.ui-fluid .ui-buttonset.ui-buttonset-6 .ui-button { - width: 16.6%; -} - -@media (max-width: 640px) { - .ui-fluid .ui-buttonset.ui-buttonset-1 .ui-button, - .ui-fluid .ui-buttonset.ui-buttonset-2 .ui-button, - .ui-fluid .ui-buttonset.ui-buttonset-3 .ui-button, - .ui-fluid .ui-buttonset.ui-buttonset-4 .ui-button, - .ui-fluid .ui-buttonset.ui-buttonset-5 .ui-button, - .ui-fluid .ui-buttonset.ui-buttonset-6 .ui-button { - width: 100%; - } -} - - -/* Severity Buttons */ - - -/* secondary */ - -.ui-button.ui-button-secondary.ui-state-default, -.ui-splitbutton.ui-button-secondary .ui-button.ui-state-default { - background-color: map-get($color-primary, normal); - border-color: map-get($color-primary, normal); - color: #fff; -} - -.ui-button.ui-button-secondary:enabled:hover, -.ui-button.ui-button-secondary:focus, -.ui-splitbutton.ui-button-secondary .ui-button:enabled:hover, -.ui-splitbutton.ui-button-secondary .ui-button:focus { - background-color: map-get($color-primary, hover); - border-color: map-get($color-primary, hover); - color: #fff; - box-shadow: 0px 4px 8px rgba(0, 101, 203, 0.4); -} - -.ui-button.ui-button-secondary:enabled:active, -.ui-splitbutton.ui-button-secondary .ui-button:enabled:active { - background-color: map-get($color-primary, active); - border-color: map-get($color-primary, active); - color: #fff; -} - - -/* Success */ - -.ui-button.ui-button-success.ui-state-default, -.ui-splitbutton.ui-button-success .ui-button.ui-state-default { - background-color: #5cb85c; - border-color: #5cb85c; - color: #ffffff; -} - -.ui-button.ui-button-success:enabled:hover, -.ui-button.ui-button-success:focus, -.ui-splitbutton.ui-button-success .ui-button:enabled:hover, -.ui-splitbutton.ui-button-success .ui-button:focus { - background-color: #4cae4c; - border-color: #5cb85c; -} - -.ui-button.ui-button-success:enabled:active, -.ui-splitbutton.ui-button-success .ui-button:enabled:active { - background-color: #449d44; - border-color: #5cb85c; -} - - -/* Info */ - -.ui-button.ui-button-info.ui-state-default, -.ui-splitbutton.ui-button-info .ui-button.ui-state-default { - background-color: #5bc0de; - border-color: #5bc0de; - color: #ffffff; -} - -.ui-button.ui-button-info:enabled:hover, -.ui-button.ui-button-info:focus, -.ui-splitbutton.ui-button-info .ui-button:enabled:hover, -.ui-splitbutton.ui-button-info .ui-button:focus { - background-color: #46b8da; - border-color: #5bc0de; -} - -.ui-button.ui-button-info:enabled:active, -.ui-splitbutton.ui-button-info .ui-button:enabled:active { - background-color: #31b0d5; - border-color: #5bc0de; -} - - -/* Warning */ - -.ui-button.ui-button-warning.ui-state-default, -.ui-splitbutton.ui-button-warning .ui-button.ui-state-default { - background-color: #FF8833; - border-color: #FF8833; - color: #ffffff; -} - -.ui-button.ui-button-warning:enabled:hover, -.ui-button.ui-button-warning:focus, -.ui-splitbutton.ui-button-warning .ui-button:enabled:hover, -.ui-splitbutton.ui-button-warning .ui-button:focus { - background-color: #FF8833; - border-color: #FF8833; -} -.ui-button.ui-button-warning:enabled:hover, -.ui-splitbutton.ui-button-warning .ui-button:enabled:hover{ - box-shadow: 0px 4px 8px rgba(243, 163, 15, 0.4); -} - -.ui-button.ui-button-warning:enabled:active, -.ui-splitbutton.ui-button-warning .ui-button:enabled:active { - background-color: #FF8833; - border-color: #FF8833; -} - - -/* Danger */ - -.ui-button.ui-button-danger.ui-state-default, -.ui-splitbutton.ui-button-danger .ui-button.ui-state-default { - background-color: #d9534f; - border-color: #d9534f; - color: #ffffff; -} - -.ui-button.ui-button-danger:enabled:hover, -.ui-button.ui-button-danger:focus, -.ui-splitbutton.ui-button-danger .ui-button:enabled:hover, -.ui-splitbutton.ui-button-danger .ui-button:focus { - background-color: #d43f3a; - border-color: #d9534f; -} - -.ui-button.ui-button-danger:enabled:active, -.ui-splitbutton.ui-button-danger .ui-button:enabled:active { - background-color: #c9302c; - border-color: #d9534f; -} - -// custom button style -.ui-button.ui-button-icon-only.close-class { - position: absolute; - top: 0; - right: .25rem; - background-color: #fff; - border: 1px solid #B9C3C8 !important; -} - -.cloud-servie-delete-button-radius { - border-radius: 20px !important; -} - -.week-button { - width: 60px !important; - border-radius: 0 !important; -} \ No newline at end of file diff --git a/dashboard/src/app/components/button/button.spec.ts b/dashboard/src/app/components/button/button.spec.ts deleted file mode 100644 index 77588b5a6..000000000 --- a/dashboard/src/app/components/button/button.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Button } from './button'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Button', () => { - - let button: Button; - let fixture: ComponentFixture - ` -}) -export class Button { - - @Input() type: string = 'button'; - - @Input() iconPos: string = 'left'; - - @Input() icon: string; - - @Input() label: string; - - @Input() disabled: boolean; - - @Input() style: any; - - @Input() styleClass: string; - - @Output() onClick: EventEmitter = new EventEmitter(); - - @Output() onFocus: EventEmitter = new EventEmitter(); - - @Output() onBlur: EventEmitter = new EventEmitter(); -} - -@NgModule({ - imports: [CommonModule], - exports: [ButtonDirective,Button], - declarations: [ButtonDirective,Button] -}) -export class ButtonModule { } diff --git a/dashboard/src/app/components/calendar/calendar.css b/dashboard/src/app/components/calendar/calendar.css deleted file mode 100644 index bd1b0db02..000000000 --- a/dashboard/src/app/components/calendar/calendar.css +++ /dev/null @@ -1,236 +0,0 @@ -.ui-calendar { - position: relative; - display: inline-block; -} - -.ui-calendar .ui-calendar-button { - position: absolute; - height: 100%; - border-top-left-radius: 0px; - border-bottom-left-radius: 0px; - width: 2em; - border-left: 0 none; -} - -.ui-calendar .ui-calendar-button:enabled:hover, -.ui-calendar .ui-calendar-button:focus { - border-left: 0 none; -} - -/* Fluid */ -.ui-fluid .ui-calendar { - width: 100%; -} - -.ui-fluid .ui-calendar-button { - width: 2em; -} - -.ui-fluid .ui-datepicker-buttonbar button { - width: auto; -} - -.ui-fluid .ui-calendar.ui-calendar-w-btn .ui-inputtext { - width: calc(100% - 2em); -} - -/* Datepicker */ -.ui-datepicker { - width: 17em; - padding: .2em; - display: none; - position: absolute; -} -.ui-datepicker.ui-datepicker-inline { - display: inline-block; - position: static; -} -.ui-datepicker .ui-datepicker-header { - position: relative; - padding: .2em 0; -} -.ui-datepicker .ui-datepicker-prev, -.ui-datepicker .ui-datepicker-next { - position: absolute; - top: .125em; - width: 1.8em; - height: 1.8em; -} - -.ui-datepicker .ui-datepicker-prev { - left: .125em; -} -.ui-datepicker .ui-datepicker-next { - right: .125em; -} -.ui-datepicker .ui-datepicker-prev span, -.ui-datepicker .ui-datepicker-next span { - display: block; - position: absolute; - left: 50%; - top: 50%; - margin-top: -.5em; -} -.ui-datepicker .ui-datepicker-prev span { - margin-left: -.25em; -} -.ui-datepicker .ui-datepicker-next span { - margin-left: -.125em; -} -.ui-datepicker .ui-datepicker-title { - margin: 0 2.3em; - line-height: 1.8em; - text-align: center; -} -.ui-datepicker .ui-datepicker-title select { - font-size: 1em; - margin: .125em 0; - vertical-align: middle; -} -.ui-datepicker select.ui-datepicker-month { - width: 55%; -} -.ui-datepicker select.ui-datepicker-year { - width: 35%; -} -.ui-datepicker select.ui-datepicker-month { - margin-right: .25em; -} -.ui-datepicker table { - width: 100%; - font-size: .9em; - border-collapse: collapse; - margin: 0 0 .4em; -} -.ui-datepicker th { - padding: .7em .3em; - text-align: center; - font-weight: bold; - border: 0; -} -.ui-datepicker td { - border: 0; - padding: .125em; -} -.ui-datepicker td span, -.ui-datepicker td a { - display: block; - padding: .2em; - text-align: right; - text-decoration: none; -} -.ui-datepicker .ui-datepicker-buttonpane { - background-image: none; - margin: .7em 0 0 0; - padding: 0 .2em; - border-left: 0; - border-right: 0; - border-bottom: 0; -} -.ui-datepicker .ui-datepicker-buttonpane button { - float: right; - margin: .5em .2em .4em; - cursor: pointer; - padding: .2em .6em .3em .6em; - width: auto; - overflow: visible; -} -.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { - float: left; -} - -/* with multiple calendars */ -.ui-datepicker.ui-datepicker-multi { - width: auto; -} -.ui-datepicker-multi .ui-datepicker-group { - float: left; -} -.ui-datepicker-multi .ui-datepicker-group table { - width: 95%; - margin: 0 auto .4em; -} -.ui-datepicker-multi-2 .ui-datepicker-group { - width: 50%; -} -.ui-datepicker-multi-3 .ui-datepicker-group { - width: 33.3%; -} -.ui-datepicker-multi-4 .ui-datepicker-group { - width: 25%; -} -.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header, -.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { - border-left-width: 0; -} -.ui-datepicker-multi .ui-datepicker-buttonpane { - clear: left; -} -.ui-datepicker-row-break { - clear: both; - width: 100%; - font-size: 0; -} - -.ui-datepicker .ui-datepicker-buttonbar { - border-left: 0 none; - border-right: 0 none; - border-bottom: 0 none; - padding: .2em; -} - -.ui-datepicker .ui-datepicker-buttonbar > .ui-g > div:last-child { - text-align: right; -} - -.ui-datepicker .ui-datepicker-buttonbar > .ui-g > div { - padding: 0; -} - -.ui-calendar.ui-calendar-w-btn input { - -moz-border-radius-topright: 0px; - -webkit-border-top-right-radius: 0px; - -khtml-border-top-right-radius: 0px; - border-top-right-radius: 0px; - -moz-border-radius-bottomright: 0px; - -webkit-border-bottom-right-radius: 0px; - -khtml-border-bottom-right-radius: 0px; - border-bottom-right-radius: 0px; -} - -.ui-timepicker { - text-align: center; - padding: .5em 0; -} - -.ui-timepicker > div { - display: inline-block; - margin-left: .5em; - min-width: 1.5em; -} - -.ui-timepicker > .ui-minute-picker, -.ui-timepicker > .ui-second-picker { - margin-left: 0; -} - -.ui-timepicker > .ui-separator { - margin-left: 0px; - min-width: .75em; -} - -.ui-timepicker > .ui-separator a { - visibility: hidden; -} - -.ui-timepicker > div a { - display: block; - opacity: 0.7; - filter:Alpha(Opacity=70); -} - -.ui-timepicker > div a:hover { - display: block; - opacity: 1; - filter:Alpha(Opacity=100); -} \ No newline at end of file diff --git a/dashboard/src/app/components/calendar/calendar.spec.ts b/dashboard/src/app/components/calendar/calendar.spec.ts deleted file mode 100644 index 68445f8de..000000000 --- a/dashboard/src/app/components/calendar/calendar.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Calendar } from './calendar'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Calendar', () => { - - let calendar: Calendar; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Calendar - ] - }); - - fixture = TestBed.createComponent(Calendar); - calendar = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/calendar/calendar.ts b/dashboard/src/app/components/calendar/calendar.ts deleted file mode 100644 index ff2fcb40b..000000000 --- a/dashboard/src/app/components/calendar/calendar.ts +++ /dev/null @@ -1,1777 +0,0 @@ -import {NgModule,Component,ElementRef,AfterViewInit,AfterViewChecked,OnDestroy,OnInit,Input,Output,SimpleChange,EventEmitter,forwardRef,Renderer2, - ViewChild,ChangeDetectorRef,TemplateRef,ContentChildren,QueryList} from '@angular/core'; -import {trigger,state,style,transition,animate} from '@angular/animations'; -import {CommonModule} from '@angular/common'; -import {ButtonModule} from '../button/button'; -import {DomHandler} from '../dom/domhandler'; -import {SharedModule,PrimeTemplate} from '../common/shared'; -import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; - -export const CALENDAR_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => Calendar), - multi: true -}; - -export interface LocaleSettings { - firstDayOfWeek?: number; - dayNames: string[]; - dayNamesShort: string[]; - dayNamesMin: string[]; - monthNames: string[]; - monthNamesShort: string[]; - today: string, - clear: string -} - -@Component({ - selector: 'p-calendar', - template: ` - - - - -
- -
- - - - - - - -
- {{locale.monthNames[currentMonth]}} - - - {{currentYear}} -
-
- - - - - - - - - - - -
- {{weekDay}} -
- - {{date.day}} - - -
-
-
- - - - 0{{currentHour}} - - - -
-
- - - - : - - - -
-
- - - - 0{{currentMinute}} - - - -
-
- - - - : - - - -
-
- - - - 0{{currentSecond}} - - - -
-
- - - - {{pm ? 'PM' : 'AM'}} - - - -
-
-
-
-
- -
-
- -
-
-
- -
-
- `, - animations: [ - trigger('overlayState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]) - ], - host: { - '[class.ui-inputwrapper-filled]': 'filled', - '[class.ui-inputwrapper-focus]': 'focus' - }, - providers: [DomHandler,CALENDAR_VALUE_ACCESSOR] -}) -export class Calendar implements AfterViewInit,AfterViewChecked,OnInit,OnDestroy,ControlValueAccessor { - - @Input() defaultDate: Date; - - @Input() style: string; - - @Input() styleClass: string; - - @Input() inputStyle: string; - - @Input() inputId: string; - - @Input() name: string; - - @Input() inputStyleClass: string; - - @Input() placeholder: string; - - @Input() disabled: any; - - @Input() dateFormat: string = 'mm/dd/yy'; - - @Input() inline: boolean = false; - - @Input() showOtherMonths: boolean = true; - - @Input() selectOtherMonths: boolean; - - @Input() showIcon: boolean; - - @Input() icon: string = 'fa-calendar'; - - @Input() appendTo: any; - - @Input() readonlyInput: boolean; - - @Input() shortYearCutoff: any = '+10'; - - @Input() monthNavigator: boolean; - - @Input() yearNavigator: boolean; - - @Input() yearRange: string; - - @Input() hourFormat: string = '24'; - - @Input() timeOnly: boolean; - - @Input() stepHour: number = 1; - - @Input() stepMinute: number = 1; - - @Input() stepSecond: number = 1; - - @Input() showSeconds: boolean = false; - - @Input() required: boolean; - - @Input() showOnFocus: boolean = true; - - @Input() dataType: string = 'date'; - - @Input() utc: boolean; - - @Input() selectionMode: string = 'single'; - - @Input() maxDateCount: number; - - @Input() showButtonBar: boolean; - - @Input() todayButtonStyleClass: string = 'ui-button-secondary'; - - @Input() clearButtonStyleClass: string = 'ui-button-secondary'; - - @Input() autoZIndex: boolean = true; - - @Input() baseZIndex: number = 0; - - @Input() panelStyleClass: string; - - @Input() keepInvalid: boolean = false; - - @Output() onFocus: EventEmitter = new EventEmitter(); - - @Output() onBlur: EventEmitter = new EventEmitter(); - - @Output() onClose: EventEmitter = new EventEmitter(); - - @Output() onSelect: EventEmitter = new EventEmitter(); - - @Output() onInput: EventEmitter = new EventEmitter(); - - @Output() onTodayClick: EventEmitter = new EventEmitter(); - - @Output() onClearClick: EventEmitter = new EventEmitter(); - - @Output() onMonthChange: EventEmitter = new EventEmitter(); - - @Output() onYearChange: EventEmitter = new EventEmitter(); - - @ContentChildren(PrimeTemplate) templates: QueryList; - - _locale: LocaleSettings = { - firstDayOfWeek: 0, - dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], - dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], - dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], - monthNames: [ "January","February","March","April","May","June","July","August","September","October","November","December" ], - monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun","Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], - today: 'Today', - clear: 'Clear' - }; - - @Input() tabindex: number; - - @ViewChild('datepicker') overlayViewChild: ElementRef; - - @ViewChild('inputfield') inputfieldViewChild: ElementRef; - - value: any; - - dates: any[]; - - weekDays: string[]; - - currentMonthText: string; - - currentMonth: number; - - currentYear: number; - - currentHour: number; - - currentMinute: number; - - currentSecond: number; - - pm: boolean; - - overlay: HTMLDivElement; - - overlayVisible: boolean; - - overlayShown: boolean; - - datepickerClick: boolean; - - onModelChange: Function = () => {}; - - onModelTouched: Function = () => {}; - - calendarElement: any; - - documentClickListener: any; - - ticksTo1970: number; - - yearOptions: number[]; - - focus: boolean; - - isKeydown: boolean; - - filled: boolean; - - inputFieldValue: string = null; - - _minDate: Date; - - _maxDate: Date; - - _showTime: boolean; - - preventDocumentListener: boolean; - - dateTemplate: TemplateRef; - - _disabledDates: Array; - - _disabledDays: Array; - - @Input() get minDate(): Date { - return this._minDate; - } - - set minDate(date: Date) { - this._minDate = date; - - if(this.currentMonth != undefined && this.currentMonth != null && this.currentYear) { - this.createMonth(this.currentMonth, this.currentYear); - } - } - - @Input() get maxDate(): Date { - return this._maxDate; - } - - set maxDate(date: Date) { - this._maxDate = date; - - if(this.currentMonth != undefined && this.currentMonth != null && this.currentYear) { - this.createMonth(this.currentMonth, this.currentYear); - } - } - - @Input() get disabledDates(): Date[] { - return this._disabledDates; - } - - set disabledDates(disabledDates: Date[]) { - this._disabledDates = disabledDates; - if(this.currentMonth != undefined && this.currentMonth != null && this.currentYear) { - - this.createMonth(this.currentMonth, this.currentYear); - } - } - - @Input() get disabledDays(): number[] { - return this._disabledDays; - } - - set disabledDays(disabledDays: number[]) { - this._disabledDays = disabledDays; - - if(this.currentMonth != undefined && this.currentMonth != null && this.currentYear) { - this.createMonth(this.currentMonth, this.currentYear); - } - } - - @Input() get showTime(): boolean { - return this._showTime; - } - - set showTime(showTime: boolean) { - this._showTime = showTime; - - if(this.currentHour === undefined) { - this.initTime(this.value||new Date()); - } - this.updateInputfield(); - } - - get locale() { - return this._locale; - } - - @Input() - set locale(newLocale: LocaleSettings) { - this._locale = newLocale; - this.createWeekDays(); - this.createMonth(this.currentMonth, this.currentYear); - } - - constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2, public cd: ChangeDetectorRef) {} - - ngOnInit() { - let date = this.defaultDate||new Date(); - this.createWeekDays(); - - this.currentMonth = date.getMonth(); - this.currentYear = date.getFullYear(); - this.initTime(date); - - this.createMonth(this.currentMonth, this.currentYear); - - this.ticksTo1970 = (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + - Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000); - - if(this.yearNavigator && this.yearRange) { - this.yearOptions = []; - let years = this.yearRange.split(':'), - yearStart = parseInt(years[0]), - yearEnd = parseInt(years[1]); - - for(let i = yearStart; i <= yearEnd; i++) { - this.yearOptions.push(i); - } - } - } - - ngAfterViewInit() { - if(!this.inline && this.appendTo) { - if(this.appendTo === 'body') - document.body.appendChild(this.overlayViewChild.nativeElement); - else - this.domHandler.appendChild(this.overlayViewChild.nativeElement, this.appendTo); - } - } - - ngAfterViewChecked() { - if(this.overlayShown) { - this.alignOverlay(); - this.overlayShown = false; - } - } - - ngAfterContentInit() { - this.templates.forEach((item) => { - switch(item.getType()) { - case 'date': - this.dateTemplate = item.template; - break; - - default: - this.dateTemplate = item.template; - break; - } - }); - } - - createWeekDays() { - this.weekDays = []; - let dayIndex = this.locale.firstDayOfWeek; - for(let i = 0; i < 7; i++) { - this.weekDays.push(this.locale.dayNamesMin[dayIndex]); - dayIndex = (dayIndex == 6) ? 0 : ++dayIndex; - } - } - - createMonth(month: number, year: number) { - this.dates = []; - this.currentMonth = month; - this.currentYear = year; - this.currentMonthText = this.locale.monthNames[month]; - let firstDay = this.getFirstDayOfMonthIndex(month, year); - let daysLength = this.getDaysCountInMonth(month, year); - let prevMonthDaysLength = this.getDaysCountInPrevMonth(month, year); - let sundayIndex = this.getSundayIndex(); - let dayNo = 1; - let today = new Date(); - - for(let i = 0; i < 6; i++) { - let week = []; - - if(i == 0) { - for(let j = (prevMonthDaysLength - firstDay + 1); j <= prevMonthDaysLength; j++) { - let prev = this.getPreviousMonthAndYear(month, year); - week.push({day: j, month: prev.month, year: prev.year, otherMonth: true, - today: this.isToday(today, j, prev.month, prev.year), selectable: this.isSelectable(j, prev.month, prev.year)}); - } - - let remainingDaysLength = 7 - week.length; - for(let j = 0; j < remainingDaysLength; j++) { - week.push({day: dayNo, month: month, year: year, today: this.isToday(today, dayNo, month, year), - selectable: this.isSelectable(dayNo, month, year)}); - dayNo++; - } - } - else { - for (let j = 0; j < 7; j++) { - if(dayNo > daysLength) { - let next = this.getNextMonthAndYear(month, year); - week.push({day: dayNo - daysLength, month: next.month, year: next.year, otherMonth:true, - today: this.isToday(today, dayNo - daysLength, next.month, next.year), - selectable: this.isSelectable((dayNo - daysLength), next.month, next.year)}); - } - else { - week.push({day: dayNo, month: month, year: year, today: this.isToday(today, dayNo, month, year), - selectable: this.isSelectable(dayNo, month, year)}); - } - - dayNo++; - } - } - - this.dates.push(week); - } - } - - initTime(date: Date) { - this.pm = (!this.utc) ? (date.getHours() > 11) : (date.getUTCHours() > 11); - if (this.showTime) { - if (this.utc) { - this.currentMinute = date.getUTCMinutes(); - this.currentSecond = date.getUTCSeconds(); - - if(this.hourFormat == '12') - this.currentHour = date.getUTCHours() == 0 ? 12 : date.getUTCHours() % 12; - else - this.currentHour = date.getUTCHours(); - } - else { - this.currentMinute = date.getMinutes(); - this.currentSecond = date.getSeconds(); - - if(this.hourFormat == '12') - this.currentHour = date.getHours() == 0 ? 12 : date.getHours() % 12; - else - this.currentHour = date.getHours(); - } - } - else if(this.timeOnly) { - this.currentMinute = 0; - this.currentHour = 0; - this.currentSecond = 0; - } - } - - prevMonth(event) { - if(this.disabled) { - event.preventDefault(); - return; - } - - if(this.currentMonth === 0) { - this.currentMonth = 11; - this.currentYear--; - - if(this.yearNavigator && this.currentYear < this.yearOptions[0]) { - this.currentYear = this.yearOptions[this.yearOptions.length - 1]; - } - } - else { - this.currentMonth--; - } - - this.onMonthChange.emit({ month: this.currentMonth + 1, year: this.currentYear }); - this.createMonth(this.currentMonth, this.currentYear); - event.preventDefault(); - } - - nextMonth(event) { - if(this.disabled) { - event.preventDefault(); - return; - } - - if(this.currentMonth === 11) { - this.currentMonth = 0; - this.currentYear++; - - if(this.yearNavigator && this.currentYear > this.yearOptions[this.yearOptions.length - 1]) { - this.currentYear = this.yearOptions[0]; - } - } - else { - this.currentMonth++; - } - - this.onMonthChange.emit({ month: this.currentMonth + 1, year: this.currentYear }); - this.createMonth(this.currentMonth, this.currentYear); - event.preventDefault(); - } - - onDateSelect(event, dateMeta) { - if(this.disabled || !dateMeta.selectable) { - event.preventDefault(); - return; - } - - if(this.isMultipleSelection() && this.isSelected(dateMeta)) { - this.value = this.value.filter((date, i) => { - return !this.isDateEquals(date, dateMeta); - }); - this.updateModel(this.value); - } - else { - if(this.shouldSelectDate(dateMeta)) { - if(dateMeta.otherMonth) { - if(this.selectOtherMonths) { - this.currentMonth = dateMeta.month; - this.currentYear = dateMeta.year; - this.createMonth(this.currentMonth, this.currentYear); - this.selectDate(dateMeta); - } - } - else { - this.selectDate(dateMeta); - } - } - } - - if(!this.showTime && this.isSingleSelection()) { - this.overlayVisible = false; - } - - this.updateInputfield(); - event.preventDefault(); - } - - shouldSelectDate(dateMeta) { - if(this.isMultipleSelection()) - return !this.maxDateCount || !this.value || this.maxDateCount > this.value.length; - else - return true; - } - - updateInputfield() { - let formattedValue = ''; - - if(this.value) { - if(this.isSingleSelection()) { - formattedValue = this.formatDateTime(this.value); - } - else if(this.isMultipleSelection()) { - for(let i = 0; i < this.value.length; i++) { - let dateAsString = this.formatDateTime(this.value[i]); - formattedValue += dateAsString; - if(i !== (this.value.length - 1)) { - formattedValue += ', '; - } - } - } - else if(this.isRangeSelection()) { - if(this.value && this.value.length) { - let startDate = this.value[0]; - let endDate = this.value[1]; - - formattedValue = this.formatDateTime(startDate); - if(endDate) { - formattedValue += ' - ' + this.formatDateTime(endDate); - } - } - } - } - - this.inputFieldValue = formattedValue; - this.updateFilledState(); - if(this.inputfieldViewChild && this.inputfieldViewChild.nativeElement) { - this.inputfieldViewChild.nativeElement.value = this.inputFieldValue; - } - } - - formatDateTime(date) { - let formattedValue = null; - if(date) { - if(this.timeOnly) { - formattedValue = this.formatTime(date); - } - else { - formattedValue = this.formatDate(date, this.dateFormat); - if(this.showTime) { - formattedValue += ' ' + this.formatTime(date); - } - } - } - - return formattedValue; - } - - selectDate(dateMeta) { - let date; - if(this.utc) - date = new Date(Date.UTC(dateMeta.year, dateMeta.month, dateMeta.day)); - else - date = new Date(dateMeta.year, dateMeta.month, dateMeta.day); - - if(this.showTime) { - if(this.utc) { - if(this.hourFormat === '12' && this.pm && this.currentHour != 12) - date.setUTCHours(this.currentHour + 12); - else - date.setUTCHours(this.currentHour); - - date.setUTCMinutes(this.currentMinute); - date.setUTCSeconds(this.currentSecond); - } - else { - if(this.hourFormat === '12' && this.pm && this.currentHour != 12) - date.setHours(this.currentHour + 12); - else - date.setHours(this.currentHour); - - date.setMinutes(this.currentMinute); - date.setSeconds(this.currentSecond); - } - } - - if(this.minDate && this.minDate > date) { - date = this.minDate; - } - - if(this.maxDate && this.maxDate < date) { - date = this.maxDate; - } - - if(this.isSingleSelection()) { - this.updateModel(date); - } - else if(this.isMultipleSelection()) { - this.updateModel(this.value ? [...this.value, date] : [date]); - } - else if(this.isRangeSelection()) { - if(this.value && this.value.length) { - let startDate = this.value[0]; - let endDate = this.value[1]; - - if(!endDate && date.getTime() >= startDate.getTime()) { - endDate = date; - } - else { - startDate = date; - endDate = null; - } - - this.updateModel([startDate, endDate]); - } - else { - this.updateModel([date, null]); - } - } - - this.onSelect.emit(date); - } - - updateModel(value) { - this.value = value; - - if(this.dataType == 'date') - this.onModelChange(this.value); - else if(this.dataType == 'string') - this.onModelChange(this.formatDateTime(this.value)); - } - - getFirstDayOfMonthIndex(month: number, year: number) { - let day = new Date(); - day.setDate(1); - day.setMonth(month); - day.setFullYear(year); - - let dayIndex = day.getDay() + this.getSundayIndex(); - return dayIndex >= 7 ? dayIndex - 7 : dayIndex; - } - - getDaysCountInMonth(month: number, year: number) { - return 32 - this.daylightSavingAdjust(new Date(year, month, 32)).getDate(); - } - - getDaysCountInPrevMonth(month: number, year: number) { - let prev = this.getPreviousMonthAndYear(month, year); - return this.getDaysCountInMonth(prev.month, prev.year); - } - - getPreviousMonthAndYear(month: number, year: number) { - let m, y; - - if(month === 0) { - m = 11; - y = year - 1; - } - else { - m = month - 1; - y = year; - } - - return {'month':m,'year':y}; - } - - getNextMonthAndYear(month: number, year: number) { - let m, y; - - if(month === 11) { - m = 0; - y = year + 1; - } - else { - m = month + 1; - y = year; - } - - return {'month':m,'year':y}; - } - - getSundayIndex() { - return this.locale.firstDayOfWeek > 0 ? 7 - this.locale.firstDayOfWeek : 0; - } - - isSelected(dateMeta): boolean { - if(this.value) { - if(this.isSingleSelection()) { - return this.isDateEquals(this.value, dateMeta); - } - else if(this.isMultipleSelection()) { - let selected = false; - for(let date of this.value) { - selected = this.isDateEquals(date, dateMeta); - if(selected) { - break; - } - } - - return selected; - } - else if(this.isRangeSelection()) { - if(this.value[1]) - return this.isDateEquals(this.value[0], dateMeta) || this.isDateEquals(this.value[1], dateMeta) || this.isDateBetween(this.value[0], this.value[1], dateMeta); - else - return this.isDateEquals(this.value[0], dateMeta) - } - } - else - return false; - } - - isDateEquals(value, dateMeta) { - if(value) - return value.getDate() === dateMeta.day && value.getMonth() === dateMeta.month && value.getFullYear() === dateMeta.year; - else - return false; - } - - isDateBetween(start, end, dateMeta) { - let between : boolean = false; - if(start && end) { - let date: Date = new Date(dateMeta.year, dateMeta.month, dateMeta.day); - return start.getTime() <= date.getTime() && end.getTime() >= date.getTime(); - } - - return between; - } - - isSingleSelection(): boolean { - return this.selectionMode === 'single'; - } - - isRangeSelection(): boolean { - return this.selectionMode === 'range'; - } - - isMultipleSelection(): boolean { - return this.selectionMode === 'multiple'; - } - - isToday(today, day, month, year): boolean { - return today.getDate() === day && today.getMonth() === month && today.getFullYear() === year; - } - - isSelectable(day, month, year): boolean { - let validMin = true; - let validMax = true; - let validDate = true; - let validDay = true; - - if(this.minDate) { - if(this.minDate.getFullYear() > year) { - validMin = false; - } - else if(this.minDate.getFullYear() === year) { - if(this.minDate.getMonth() > month) { - validMin = false; - } - else if(this.minDate.getMonth() === month) { - if(this.minDate.getDate() > day) { - validMin = false; - } - } - } - } - - if(this.maxDate) { - if(this.maxDate.getFullYear() < year) { - validMax = false; - } - else if(this.maxDate.getFullYear() === year) { - if(this.maxDate.getMonth() < month) { - validMax = false; - } - else if(this.maxDate.getMonth() === month) { - if(this.maxDate.getDate() < day) { - validMax = false; - } - } - } - } - - if(this.disabledDates) { - validDate = !this.isDateDisabled(day,month,year); - } - - if(this.disabledDays) { - validDay = !this.isDayDisabled(day,month,year) - } - - return validMin && validMax && validDate && validDay; - } - - isDateDisabled(day:number, month:number, year:number):boolean { - if(this.disabledDates) { - for(let disabledDate of this.disabledDates) { - if(disabledDate.getFullYear() === year && disabledDate.getMonth() === month && disabledDate.getDate() === day) { - return true; - } - } - } - - return false; - } - - isDayDisabled(day:number, month:number, year:number):boolean { - if(this.disabledDays) { - let weekday = new Date(year, month, day); - let weekdayNumber = weekday.getDay(); - return this.disabledDays.indexOf(weekdayNumber) !== -1; - } - return false; - } - - onInputFocus(event: Event) { - this.focus = true; - if(this.showOnFocus) { - this.showOverlay(); - } - this.onFocus.emit(event); - } - - onInputClick(event: Event) { - this.datepickerClick=true; - if(this.autoZIndex) { - this.overlayViewChild.nativeElement.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex)); - } - } - - onInputBlur(event: Event) { - this.focus = false; - this.onBlur.emit(event); - if(!this.keepInvalid) { - this.updateInputfield(); - } - this.onModelTouched(); - } - - onButtonClick(event,inputfield) { - if(!this.overlayViewChild.nativeElement.offsetParent || this.overlayViewChild.nativeElement.style.display === 'none') { - inputfield.focus(); - this.showOverlay(); - } - else - this.overlayVisible = false; - - this.datepickerClick = true; - } - - onInputKeydown(event) { - this.isKeydown = true; - if(event.keyCode === 9) { - this.overlayVisible = false; - } - } - - onMonthDropdownChange(m: string) { - this.currentMonth = parseInt(m); - this.onMonthChange.emit({ month: this.currentMonth + 1, year: this.currentYear }); - this.createMonth(this.currentMonth, this.currentYear); - } - - onYearDropdownChange(y: string) { - this.currentYear = parseInt(y); - this.onYearChange.emit({ month: this.currentMonth + 1, year: this.currentYear }); - this.createMonth(this.currentMonth, this.currentYear); - } - - incrementHour(event) { - const prevHour = this.currentHour; - const newHour = this.currentHour + this.stepHour; - - if(this.validateHour(newHour)) { - if(this.hourFormat == '24') - this.currentHour = (newHour >= 24) ? (newHour - 24) : newHour; - else if(this.hourFormat == '12') { - // Before the AM/PM break, now after - if (prevHour < 12 && newHour > 11) { - this.pm = !this.pm; - } - - this.currentHour = (newHour >= 13) ? (newHour - 12) : newHour; - } - - this.updateTime(); - } - - event.preventDefault(); - } - - decrementHour(event) { - const newHour = this.currentHour - this.stepHour; - - if(this.validateHour(newHour)) { - if(this.hourFormat == '24') - this.currentHour = (newHour < 0) ? (24 + newHour) : newHour; - else if(this.hourFormat == '12') { - // If we were at noon/midnight, then switch - if (this.currentHour === 12) { - this.pm = !this.pm; - } - this.currentHour = (newHour <= 0) ? (12 + newHour) : newHour; - } - - this.updateTime(); - } - - event.preventDefault(); - } - - validateHour(hour): boolean { - let valid: boolean = true; - let value = this.value; - if(this.isRangeSelection()) { - value = this.value[1] || this.value[0]; - } - if(this.isMultipleSelection()) { - value = this.value[this.value.length - 1]; - } - let valueDateString = value ? value.toDateString() : null; - - if(this.minDate && valueDateString && this.minDate.toDateString() === valueDateString) { - if(this.minDate.getHours() > hour) { - valid = false; - } - } - - if(this.maxDate && valueDateString && this.maxDate.toDateString() === valueDateString) { - if(this.maxDate.getHours() < hour) { - valid = false; - } - } - - return valid; - } - - incrementMinute(event) { - let newMinute = this.currentMinute + this.stepMinute; - if(this.validateMinute(newMinute)) { - this.currentMinute = (newMinute > 59) ? newMinute - 60 : newMinute; - this.updateTime(); - } - - event.preventDefault(); - } - - decrementMinute(event) { - let newMinute = this.currentMinute - this.stepMinute; - if(this.validateMinute(newMinute)) { - this.currentMinute = (newMinute < 0) ? 60 + newMinute : newMinute; - this.updateTime(); - } - - event.preventDefault(); - } - - validateMinute(minute): boolean { - let valid: boolean = true; - let value = this.value; - if(this.isRangeSelection()) { - value = this.value[1] || this.value[0]; - } - if(this.isMultipleSelection()) { - value = this.value[this.value.length - 1]; - } - let valueDateString = value ? value.toDateString() : null; - - if(this.minDate && valueDateString && this.minDate.toDateString() === valueDateString) { - if(this.minDate.getMinutes() > minute) { - valid = false; - } - } - - if(this.maxDate && valueDateString && this.maxDate.toDateString() === valueDateString) { - if(this.maxDate.getMinutes() < minute) { - valid = false; - } - } - - return valid; - } - - incrementSecond(event) { - let newSecond = this.currentSecond + this.stepSecond; - if(this.validateSecond(newSecond)) { - this.currentSecond = (newSecond > 59) ? newSecond - 60 : newSecond; - this.updateTime(); - } - - event.preventDefault(); - } - - decrementSecond(event) { - let newSecond = this.currentSecond - this.stepSecond; - if(this.validateSecond(newSecond)) { - this.currentSecond = (newSecond < 0) ? 60 + newSecond : newSecond; - this.updateTime(); - } - - event.preventDefault(); - } - - validateSecond(second): boolean { - let valid: boolean = true; - let value = this.value; - if(this.isRangeSelection()) { - value = this.value[1] || this.value[0]; - } - if(this.isMultipleSelection()) { - value = this.value[this.value.length - 1]; - } - let valueDateString = value ? value.toDateString() : null; - - if(this.minDate && valueDateString && this.minDate.toDateString() === valueDateString) { - if(this.minDate.getSeconds() > second) { - valid = false; - } - } - - if(this.maxDate && valueDateString && this.maxDate.toDateString() === valueDateString) { - if(this.maxDate.getSeconds() < second) { - valid = false; - } - } - - return valid; - } - - updateTime() { - let value = this.value; - if(this.isRangeSelection()) { - value = this.value[1] || this.value[0]; - } - if(this.isMultipleSelection()) { - value = this.value[this.value.length - 1]; - } - value = value ? new Date(value.getTime()) : new Date(); - - if (this.utc) { - if (this.hourFormat == '12') { - if (this.currentHour === 12) - value.setUTCHours(this.pm ? 12 : 0); - else - value.setUTCHours(this.pm ? this.currentHour + 12 : this.currentHour); - } - else { - value.setUTCHours(this.currentHour); - } - } - else { - if (this.hourFormat == '12') { - if (this.currentHour === 12) - value.setHours(this.pm ? 12 : 0); - else - value.setHours(this.pm ? this.currentHour + 12 : this.currentHour); - } - else { - value.setHours(this.currentHour); - } - } - - value.setMinutes(this.currentMinute); - value.setSeconds(this.currentSecond); - if(this.isRangeSelection()) { - if(this.value[1]) { - value = [this.value[0], value]; - } else { - value = [value, null]; - } - } - if(this.isMultipleSelection()){ - value = [...this.value.slice(0, -1), value]; - } - this.updateModel(value); - this.onSelect.emit(value); - this.updateInputfield(); - } - - toggleAMPM(event) { - this.pm = !this.pm; - this.updateTime(); - event.preventDefault(); - } - - onUserInput(event) { - // IE 11 Workaround for input placeholder : https://github.com/primefaces/primeng/issues/2026 - if(!this.isKeydown) { - return; - } - this.isKeydown = false; - - let val = event.target.value; - try { - let value = this.parseValueFromString(val); - this.updateModel(value); - this.updateUI(); - } - catch(err) { - //invalid date - this.updateModel(null); - } - - this.filled = val != null && val.length; - this.onInput.emit(event); - } - - parseValueFromString(text: string): Date { - if(!text || text.trim().length === 0) { - return null; - } - - let value: any; - - if(this.isSingleSelection()) { - value = this.parseDateTime(text); - } - else if(this.isMultipleSelection()) { - let tokens = text.split(','); - value = []; - for(let token of tokens) { - value.push(this.parseDateTime(token.trim())); - } - } - else if(this.isRangeSelection()) { - let tokens = text.split(' - '); - value = []; - for(let i = 0; i < tokens.length; i++) { - value[i] = this.parseDateTime(tokens[i].trim()); - } - } - - return value; - } - - parseDateTime(text): Date { - let date: Date; - let parts: string[] = text.split(' '); - - if(this.timeOnly) { - date = new Date(); - this.populateTime(date, parts[0], parts[1]); - } - else { - if(this.showTime) { - date = this.parseDate(parts[0], this.dateFormat); - this.populateTime(date, parts[1], parts[2]); - } - else { - date = this.parseDate(text, this.dateFormat); - } - } - - return date; - } - - populateTime(value, timeString, ampm) { - if(this.hourFormat == '12' && !ampm) { - throw 'Invalid Time'; - } - - this.pm = (ampm === 'PM' || ampm === 'pm'); - let time = this.parseTime(timeString); - if (!this.utc) - value.setHours(time.hour); - else - value.setUTCHours(time.hour); - - value.setMinutes(time.minute); - value.setSeconds(time.second); - } - - updateUI() { - let val = this.value||this.defaultDate||new Date(); - - if (Array.isArray(val)){ - val = val[0]; - } - - this.createMonth(val.getMonth(), val.getFullYear()); - - if(this.showTime||this.timeOnly) { - let hours = (this.utc) ? val.getUTCHours : val.getHours(); - - if(this.hourFormat == '12') { - this.pm = hours > 11; - - if(hours >= 12) { - this.currentHour = (hours == 12) ? 12 : hours - 12; - } - else { - this.currentHour = (hours == 0) ? 12 : hours; - } - } - else { - this.currentHour = (this.utc) ? val.getUTCHours() : val.getHours(); - } - - this.currentMinute = val.getMinutes(); - this.currentSecond = val.getSeconds(); - } - } - - onDatePickerClick(event) { - this.datepickerClick = true; - } - - showOverlay() { - this.overlayVisible = true; - this.overlayShown = true; - if(this.autoZIndex) { - this.overlayViewChild.nativeElement.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex)); - } - - this.bindDocumentClickListener(); - } - - alignOverlay() { - if(this.appendTo) - this.domHandler.absolutePosition(this.overlayViewChild.nativeElement, this.inputfieldViewChild.nativeElement); - else - this.domHandler.relativePosition(this.overlayViewChild.nativeElement, this.inputfieldViewChild.nativeElement); - } - - writeValue(value: any) : void { - this.value = value; - if(this.value && typeof this.value === 'string') { - this.value = this.parseValueFromString(this.value); - } - - this.updateInputfield(); - this.updateUI(); - } - - registerOnChange(fn: Function): void { - this.onModelChange = fn; - } - - registerOnTouched(fn: Function): void { - this.onModelTouched = fn; - } - - setDisabledState(val: boolean): void { - this.disabled = val; - } - - // Ported from jquery-ui datepicker formatDate - formatDate(date, format) { - if (!date) { - return ''; - } - - let iFormat; - const lookAhead = (match) => { - const matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); - if (matches) { - iFormat++; - } - return matches; - }, - formatNumber = (match, value, len) => { - let num = '' + value; - if (lookAhead(match)) { - while (num.length < len) { - num = '0' + num; - } - } - return num; - }, - formatName = (match, value, shortNames, longNames) => { - return (lookAhead(match) ? longNames[value] : shortNames[value]); - }; - let output = ''; - let literal = false; - - if (date) { - for (iFormat = 0; iFormat < format.length; iFormat++) { - if (literal) { - if (format.charAt(iFormat) === '\'' && !lookAhead('\'')) { - literal = false; - } else { - output += format.charAt(iFormat); - } - } else { - switch (format.charAt(iFormat)) { - case 'd': - output += formatNumber('d', this.utc ? date.getUTCDate() : date.getDate(), 2); - break; - case 'D': - output += formatName('D', this.utc ? date.getUTCDay() : date.getDay(), this.locale.dayNamesShort, this.locale.dayNames); - break; - case 'o': - if (this.utc) { - output += formatNumber('o', - Math.round(( - new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()).getTime() - - new Date(date.getUTCFullYear(), 0, 0).getTime()) / 86400000), 3); - } else { - output += formatNumber('o', - Math.round(( - new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); - } - break; - case 'm': - output += formatNumber('m', (this.utc ? date.getUTCMonth() : date.getMonth()) + 1, 2); - break; - case 'M': - output += formatName('M', this.utc ? date.getUTCMonth() : date.getMonth(), this.locale.monthNamesShort, this.locale.monthNames); - break; - case 'y': - output += (lookAhead('y') ? (this.utc ? date.getUTCFullYear() : date.getFullYear()) : - ((this.utc ? date.getUTCFullYear() : date.getFullYear()) % 100 < 10 ? '0' : '') + - (this.utc ? date.getUTCFullYear() : date.getFullYear()) % 100); - break; - case '@': - output += date.getTime(); - break; - case '!': - output += date.getTime() * 10000 + this.ticksTo1970; - break; - case '\'': - if (lookAhead('\'')) { - output += '\''; - } else { - literal = true; - } - break; - default: - output += format.charAt(iFormat); - } - } - } - } - return output; - } - - formatTime(date) { - if(!date) { - return ''; - } - - let output = ''; - let hours = (this.utc) ? date.getUTCHours() : date.getHours(); - let minutes = date.getMinutes(); - let seconds = date.getSeconds(); - - if(this.hourFormat == '12' && hours > 11 && hours != 12) { - hours-=12; - } - - output += (hours < 10) ? '0' + hours : hours; - output += ':'; - output += (minutes < 10) ? '0' + minutes : minutes; - - if(this.showSeconds) { - output += ':'; - output += (seconds < 10) ? '0' + seconds : seconds; - } - - if(this.hourFormat == '12') { - output += date.getHours() > 11 ? ' PM' : ' AM'; - } - - return output; - } - - parseTime(value) { - let tokens: string[] = value.split(':'); - let validTokenLength = this.showSeconds ? 3 : 2; - - if(tokens.length !== validTokenLength) { - throw "Invalid time"; - } - - let h = parseInt(tokens[0]); - let m = parseInt(tokens[1]); - let s = this.showSeconds ? parseInt(tokens[2]) : null; - - if(isNaN(h) || isNaN(m) || h > 23 || m > 59 || (this.hourFormat == '12' && h > 12) || (this.showSeconds && (isNaN(s) || s > 59))) { - throw "Invalid time"; - } - else { - if(this.hourFormat == '12' && h !== 12 && this.pm) { - h+= 12; - } - - return {hour: h, minute: m, second: s}; - } - } - - // Ported from jquery-ui datepicker parseDate - parseDate(value, format) { - if(format == null || value == null) { - throw "Invalid arguments"; - } - - value = (typeof value === "object" ? value.toString() : value + ""); - if(value === "") { - return null; - } - - let iFormat, dim, extra, - iValue = 0, - shortYearCutoff = (typeof this.shortYearCutoff !== "string" ? this.shortYearCutoff : new Date().getFullYear() % 100 + parseInt(this.shortYearCutoff, 10)), - year = -1, - month = -1, - day = -1, - doy = -1, - literal = false, - date, - lookAhead = (match) => { - let matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); - if(matches) { - iFormat++; - } - return matches; - }, - getNumber = (match) => { - let isDoubled = lookAhead(match), - size = (match === "@" ? 14 : (match === "!" ? 20 : - (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))), - minSize = (match === "y" ? size : 1), - digits = new RegExp("^\\d{" + minSize + "," + size + "}"), - num = value.substring(iValue).match(digits); - if(!num) { - throw "Missing number at position " + iValue; - } - iValue += num[ 0 ].length; - return parseInt(num[ 0 ], 10); - }, - getName = (match, shortNames, longNames) => { - let index = -1; - let arr = lookAhead(match) ? longNames : shortNames; - let names = []; - - for(let i = 0; i < arr.length; i++) { - names.push([i,arr[i]]); - } - names.sort((a,b) => { - return -(a[ 1 ].length - b[ 1 ].length); - }); - - for(let i = 0; i < names.length; i++) { - let name = names[i][1]; - if(value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) { - index = names[i][0]; - iValue += name.length; - break; - } - } - - if(index !== -1) { - return index + 1; - } else { - throw "Unknown name at position " + iValue; - } - }, - checkLiteral = () => { - if(value.charAt(iValue) !== format.charAt(iFormat)) { - throw "Unexpected literal at position " + iValue; - } - iValue++; - }; - - for (iFormat = 0; iFormat < format.length; iFormat++) { - if(literal) { - if(format.charAt(iFormat) === "'" && !lookAhead("'")) { - literal = false; - } else { - checkLiteral(); - } - } else { - switch (format.charAt(iFormat)) { - case "d": - day = getNumber("d"); - break; - case "D": - getName("D", this.locale.dayNamesShort, this.locale.dayNames); - break; - case "o": - doy = getNumber("o"); - break; - case "m": - month = getNumber("m"); - break; - case "M": - month = getName("M", this.locale.monthNamesShort, this.locale.monthNames); - break; - case "y": - year = getNumber("y"); - break; - case "@": - date = new Date(getNumber("@")); - year = date.getFullYear(); - month = date.getMonth() + 1; - day = date.getDate(); - break; - case "!": - date = new Date((getNumber("!") - this.ticksTo1970) / 10000); - year = date.getFullYear(); - month = date.getMonth() + 1; - day = date.getDate(); - break; - case "'": - if(lookAhead("'")) { - checkLiteral(); - } else { - literal = true; - } - break; - default: - checkLiteral(); - } - } - } - - if(iValue < value.length) { - extra = value.substr(iValue); - if(!/^\s+/.test(extra)) { - throw "Extra/unparsed characters found in date: " + extra; - } - } - - if(year === -1) { - year = new Date().getFullYear(); - } else if(year < 100) { - year += new Date().getFullYear() - new Date().getFullYear() % 100 + - (year <= shortYearCutoff ? 0 : -100); - } - - if(doy > -1) { - month = 1; - day = doy; - do { - dim = this.getDaysCountInMonth(year, month - 1); - if(day <= dim) { - break; - } - month++; - day -= dim; - } while (true); - } - - if (this.utc) { - date = new Date(Date.UTC(year, month - 1, day)); - if (date.getUTCFullYear() !== year || date.getUTCMonth() + 1 !== month || date.getUTCDate() !== day) { - throw "Invalid date"; // E.g. 31/02/00 - } - } else { - date = this.daylightSavingAdjust(new Date(year, month - 1, day)); - if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) { - throw "Invalid date"; // E.g. 31/02/00 - } - } - return date; - } - - daylightSavingAdjust(date) { - if(!date) { - return null; - } - - if(!this.utc) { - date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); - } - - return date; - } - - updateFilledState() { - this.filled = this.inputFieldValue && this.inputFieldValue != ''; - } - - onTodayButtonClick(event) { - let date: Date = new Date(); - let dateMeta = {day: date.getDate(), month: date.getMonth(), year: date.getFullYear(), today: true, selectable: true}; - - this.createMonth(dateMeta.month, dateMeta.year); - this.onDateSelect(event, dateMeta); - this.onTodayClick.emit(event); - } - - onClearButtonClick(event) { - this.updateModel(null); - this.updateInputfield(); - this.overlayVisible = false; - this.onClearClick.emit(event); - } - - bindDocumentClickListener() { - if(!this.documentClickListener) { - this.documentClickListener = this.renderer.listen('document', 'click', (event) => { - if(!this.datepickerClick&&this.overlayVisible) { - this.overlayVisible = false; - this.onClose.emit(event); - } - - this.datepickerClick = false; - this.cd.detectChanges(); - }); - } - } - - unbindDocumentClickListener() { - if(this.documentClickListener) { - this.documentClickListener(); - this.documentClickListener = null; - } - } - - ngOnDestroy() { - this.unbindDocumentClickListener(); - - if(!this.inline && this.appendTo) { - this.el.nativeElement.appendChild(this.overlayViewChild.nativeElement); - } - } -} - -@NgModule({ - imports: [CommonModule,ButtonModule,SharedModule], - exports: [Calendar,ButtonModule,SharedModule], - declarations: [Calendar] -}) -export class CalendarModule { } diff --git a/dashboard/src/app/components/captcha/captcha.spec.ts b/dashboard/src/app/components/captcha/captcha.spec.ts deleted file mode 100644 index b7f89b5cf..000000000 --- a/dashboard/src/app/components/captcha/captcha.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Captcha } from './captcha'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Captcha', () => { - - let captcha: Captcha; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Captcha - ] - }); - - fixture = TestBed.createComponent(Captcha); - captcha = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/captcha/captcha.ts b/dashboard/src/app/components/captcha/captcha.ts deleted file mode 100644 index 004330676..000000000 --- a/dashboard/src/app/components/captcha/captcha.ts +++ /dev/null @@ -1,92 +0,0 @@ -import {NgModule,AfterViewInit,Component,EventEmitter,Input,NgZone,OnDestroy,Output,ElementRef} from '@angular/core'; -import {CommonModule} from '@angular/common'; - -@Component({ - selector: 'p-captcha', - template: `
` -}) -export class Captcha implements AfterViewInit { - - @Input() siteKey: string = null; - - @Input() theme = 'light'; - - @Input() type = 'image'; - - @Input() size = 'normal'; - - @Input() tabindex = 0; - - @Input() language: string = null; - - @Input() initCallback = "initRecaptcha"; - - @Output() onResponse: EventEmitter = new EventEmitter(); - - @Output() onExpire: EventEmitter = new EventEmitter(); - - private _instance: any = null; - - constructor(public el: ElementRef, public _zone: NgZone) {} - - ngAfterViewInit() { - if((window).grecaptcha) { - this.init(); - } - else { - (window)[this.initCallback] = () => { - this.init(); - } - } - } - - init() { - this._instance = (window).grecaptcha.render(this.el.nativeElement.children[0], { - 'sitekey': this.siteKey, - 'theme': this.theme, - 'type': this.type, - 'size': this.size, - 'tabindex': this.tabindex, - 'hl': this.language, - 'callback': (response: string) => {this._zone.run(() => this.recaptchaCallback(response))}, - 'expired-callback': () => {this._zone.run(() => this.recaptchaExpiredCallback())} - }); - } - - reset() { - if(this._instance === null) - return; - - (window).grecaptcha.reset(this._instance); - } - - getResponse(): String { - if (this._instance === null) - return null; - - return (window).grecaptcha.getResponse(this._instance); - } - - recaptchaCallback(response: string) { - this.onResponse.emit({ - response: response - }); - } - - recaptchaExpiredCallback() { - this.onExpire.emit(); - } - - ngOnDestroy() { - if (this._instance != null) { - (window).grecaptcha.reset(this._instance); - } - } -} - -@NgModule({ - imports: [CommonModule], - exports: [Captcha], - declarations: [Captcha] -}) -export class CaptchaModule { } diff --git a/dashboard/src/app/components/card/card.css b/dashboard/src/app/components/card/card.css deleted file mode 100644 index c20fb9c3a..000000000 --- a/dashboard/src/app/components/card/card.css +++ /dev/null @@ -1,50 +0,0 @@ -.ui-card-header img { - width: 100%; -} - -.ui-card-body { - padding: 1em; -} - -.ui-card-title { - font-size: 1.5em; - font-weight: bold; - margin-bottom: .5em; -} - -.ui-card-subtitle { - opacity: .7; - margin-bottom: .5em; - margin-top: -.25em; - font-weight: bold; -} - -.ui-card-content { - line-height: 1.5; -} - -.ui-card-footer { - padding-top: 1em; -} - - -/* .ui-card-shadow { - box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 2px 1px -1px rgba(0, 0, 0, 0.12); - -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 2px 1px -1px rgba(0, 0, 0, 0.12); - -moz-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 2px 1px -1px rgba(0, 0, 0, 0.12); -} */ - -.ui-card-shadow { - box-shadow: 5px 5px 25px rgba(51, 59, 69, 0.149019607843137); - -webkit-box-shadow: 5px 5px 25px rgba(51, 59, 69, 0.149019607843137); - -moz-box-shadow: 5px 5px 25px rgba(51, 59, 69, 0.149019607843137); -} - -.new-card-class { - border: none !important; - border-radius: 12px; - -} -.ui-card-body{ - padding: .15rem .2rem; -} \ No newline at end of file diff --git a/dashboard/src/app/components/card/card.spec.ts b/dashboard/src/app/components/card/card.spec.ts deleted file mode 100644 index 9c5a95b84..000000000 --- a/dashboard/src/app/components/card/card.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Card } from './card'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Card', () => { - - let card: Card; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Card - ] - }); - - fixture = TestBed.createComponent(Card); - card = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/card/card.ts b/dashboard/src/app/components/card/card.ts deleted file mode 100644 index 14e8f4e24..000000000 --- a/dashboard/src/app/components/card/card.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { NgModule, Component, Input, Output, EventEmitter, ElementRef, ContentChild } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { SharedModule, Header, Footer } from '../common/shared'; -import { BlockableUI } from '../common/blockableui'; - -@Component({ - selector: 'p-card', - template: ` -
-
- -
-
-
{{title}}
-
{{subtitle}}
-
- -
- -
-
- ` -}) -export class Card implements BlockableUI { - - @Input() title: string; - - @Input() subtitle: string; - - @Input() style: any; - - @Input() styleClass: string; - - @ContentChild(Header) headerFacet; - - @ContentChild(Footer) footerFacet; - - constructor(private el: ElementRef) { } - - getBlockableElement(): HTMLElement  { - return this.el.nativeElement.children[0]; - } - -} - -@NgModule({ - imports: [CommonModule], - exports: [Card, SharedModule], - declarations: [Card] -}) -export class CardModule { } diff --git a/dashboard/src/app/components/carousel/carousel.css b/dashboard/src/app/components/carousel/carousel.css deleted file mode 100644 index a10453d83..000000000 --- a/dashboard/src/app/components/carousel/carousel.css +++ /dev/null @@ -1,85 +0,0 @@ -.ui-carousel { - position: relative; - padding: .063em; -} - -.ui-carousel .ui-carousel-viewport .ui-carousel-items { - list-style: none outside none; - margin: 0; - padding:0; - position: relative; - width: 32000px; - left: 0; -} - -.ui-carousel .ui-carousel-viewport .ui-carousel-items .ui-carousel-item { - margin: 1px; - padding: 0; - float: left; - box-sizing: border-box; -} - -.ui-carousel .ui-carousel-viewport { - overflow: hidden; - position: relative; - border: 0; -} - -.ui-carousel .ui-carousel-footer { - margin: 1px 1px 0px 1px; - padding: .5em; - overflow: hidden; -} - -.ui-carousel .ui-carousel-header { - margin: 0 1px; - overflow: hidden; - padding: .625em; -} - -.ui-carousel .ui-carousel-header .ui-carousel-header-title { - display: inline-block; - overflow: hidden; -} - -.ui-carousel .ui-carousel-dropdown, -.ui-carousel .ui-carousel-mobiledropdown { - float: right; - margin: 0px .625em; - background-image: none; -} - -.ui-carousel .ui-carousel-dropdown option, -.ui-carousel .ui-carousel-mobiledropdown option{ - background-image: none; - border: 0 none; - box-shadow: none; - -moz-box-shadow: none; - -webkit-box-shadow: none; -} - -.ui-carousel .ui-carousel-button { - float: right; - margin: .125em; -} - -.ui-carousel .ui-carousel-page-link { - float: left; - margin: 0 .125em; - text-decoration: none; -} - -.ui-carousel .ui-carousel-page-link, -.ui-carousel .ui-carousel-button { - cursor: pointer; -} - -.ui-carousel .ui-carousel-page-links { - margin: 0px .5em; - margin-top: .125em; - float: right; -} - -.ui-carousel .ui-carousel-mobiledropdown { - display: none; -} \ No newline at end of file diff --git a/dashboard/src/app/components/carousel/carousel.spec.ts b/dashboard/src/app/components/carousel/carousel.spec.ts deleted file mode 100644 index f51b1ca6d..000000000 --- a/dashboard/src/app/components/carousel/carousel.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Carousel } from './carousel'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Carousel', () => { - - let carousel: Carousel; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Carousel - ] - }); - - fixture = TestBed.createComponent(Carousel); - carousel = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/carousel/carousel.ts b/dashboard/src/app/components/carousel/carousel.ts deleted file mode 100644 index c190a405d..000000000 --- a/dashboard/src/app/components/carousel/carousel.ts +++ /dev/null @@ -1,327 +0,0 @@ -import {NgModule,Component,ElementRef,AfterViewInit,AfterViewChecked,AfterContentInit,EventEmitter,OnDestroy,Input,Output,TemplateRef,ContentChildren,QueryList,Renderer2,ViewChild,ChangeDetectorRef} from '@angular/core'; -import {DomHandler} from '../dom/domhandler'; -import {SharedModule,PrimeTemplate} from '../common/shared'; -import {CommonModule} from '@angular/common'; - -@Component({ - selector: 'p-carousel', - template: ` -
- - -
- `, - providers: [DomHandler] -}) -export class Carousel implements AfterViewChecked,AfterViewInit,OnDestroy{ - - @Input() numVisible: number = 3; - - @Input() firstVisible: number = 0; - - @Input() headerText: string; - - @Input() circular: boolean = false; - - @Input() breakpoint: number = 560; - - @Input() responsive: boolean = true; - - @Input() autoplayInterval: number = 0; - - @Input() effectDuration: any = '1s'; - - @Input() easing: string = 'ease-out'; - - @Input() pageLinks: number = 3; - - @Input() style: any; - - @Input() styleClass: string; - - @Output() onPage: EventEmitter = new EventEmitter(); - - @ContentChildren(PrimeTemplate) templates: QueryList; - - public _value: any[]; - - public itemTemplate: TemplateRef; - - public left: any = 0; - - public items: any; - - public columns: any; - - public page: number; - - public valuesChanged: any; - - public interval: any; - - public anchorPageLinks: any[]; - - public mobileDropdownOptions: any[]; - - public selectDropdownOptions: any[]; - - public shrinked: boolean; - - @ViewChild('container') containerViewChild: ElementRef; - - @ViewChild('viewport') viewportViewChild: ElementRef; - - @ViewChild('items') itemsViewChild: ElementRef; - - documentResponsiveListener: any; - - differ: any; - - constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2, public cd: ChangeDetectorRef) {} - - ngAfterContentInit() { - this.templates.forEach((item) => { - switch(item.getType()) { - case 'item': - this.itemTemplate = item.template; - break; - - default: - this.itemTemplate = item.template; - break; - } - }); - } - - @Input() get value(): any[] { - return this._value; - } - - set value(val:any[]) { - this._value = val; - this.handleDataChange(); - } - - handleDataChange() { - if(this.value && this.value.length) { - if(this.value.length && this.firstVisible >= this.value.length) { - this.setPage(this.totalPages - 1); - } - } - else { - this.setPage(0); - } - - this.valuesChanged = true; - } - - ngAfterViewChecked() { - if(this.valuesChanged && this.containerViewChild.nativeElement.offsetParent) { - this.render(); - this.valuesChanged = false; - } - } - - ngAfterViewInit() { - if(this.responsive) { - this.documentResponsiveListener = this.renderer.listen('window', 'resize', (event) => { - this.updateState(); - }); - } - } - - updateLinks() { - this.anchorPageLinks = []; - for (let i = 0; i < this.totalPages; i++) { - this.anchorPageLinks.push(i); - } - } - - updateDropdown() { - this.selectDropdownOptions = []; - for (let i = 0; i < this.totalPages; i++) { - this.selectDropdownOptions.push(i); - } - } - - updateMobileDropdown() { - this.mobileDropdownOptions = []; - if(this.value && this.value.length) { - for (let i = 0; i < this.value.length; i++) { - this.mobileDropdownOptions.push(i); - } - } - } - - render() { - if(this.autoplayInterval) { - this.stopAutoplay(); - } - - this.items = this.domHandler.find(this.itemsViewChild.nativeElement, 'li'); - this.calculateColumns(); - this.calculateItemWidths(); - - if(!this.responsive) { - this.containerViewChild.nativeElement.style.width = (this.domHandler.width(this.containerViewChild.nativeElement)) + 'px'; - } - - if(this.autoplayInterval) { - this.circular = true; - this.startAutoplay(); - } - - this.updateMobileDropdown(); - this.updateLinks(); - this.updateDropdown(); - this.cd.detectChanges(); - } - - calculateItemWidths () { - let firstItem = (this.items && this.items.length) ? this.items[0] : null; - if(firstItem) { - for (let i = 0; i < this.items.length; i++) { - this.items[i].style.width = ((this.domHandler.innerWidth(this.viewportViewChild.nativeElement) - (this.domHandler.getHorizontalMargin(firstItem) * this.columns)) / this.columns) + 'px'; - } - } - } - - calculateColumns() { - if(window.innerWidth <= this.breakpoint) { - this.shrinked = true; - this.columns = 1; - } - else { - this.shrinked = false; - this.columns = this.numVisible; - } - this.page = Math.floor(this.firstVisible / this.columns); - } - - onNextNav() { - let lastPage = (this.page === (this.totalPages - 1)); - - if(!lastPage) - this.setPage(this.page + 1); - else if(this.circular) - this.setPage(0); - } - - onPrevNav() { - if(this.page !== 0) - this.setPage(this.page - 1); - else if(this.circular) - this.setPage(this.totalPages - 1); - } - - setPageWithLink(event, p: number) { - this.setPage(p); - event.preventDefault(); - } - - setPage(p, enforce?: boolean) { - if(p !== this.page || enforce) { - this.page = p; - this.left = (-1 * (this.domHandler.innerWidth(this.viewportViewChild.nativeElement) * this.page)); - this.firstVisible = this.page * this.columns; - this.onPage.emit({ - page: this.page - }); - } - } - - onDropdownChange(val: string) { - this.setPage(parseInt(val)); - } - - get displayPageLinks(): boolean { - return (this.totalPages <= this.pageLinks && !this.shrinked); - } - - get displayPageDropdown(): boolean { - return (this.totalPages > this.pageLinks && !this.shrinked); - } - - get totalPages(): number { - return (this.value && this.value.length) ? Math.ceil(this.value.length / this.columns) : 0; - } - - routerDisplay () { - let win = window; - if(win.innerWidth <= this.breakpoint) - return true; - else - return false; - } - - updateState() { - let win = window; - if(win.innerWidth <= this.breakpoint) { - this.shrinked = true; - this.columns = 1; - } - else if(this.shrinked) { - this.shrinked = false; - this.columns = this.numVisible; - this.updateLinks(); - this.updateDropdown(); - } - - this.calculateItemWidths(); - this.setPage(Math.floor(this.firstVisible / this.columns), true); - } - - startAutoplay() { - this.interval = setInterval(() => { - if(this.page === (this.totalPages - 1)) - this.setPage(0); - else - this.setPage(this.page + 1); - }, - this.autoplayInterval); - } - - stopAutoplay() { - clearInterval(this.interval); - } - - ngOnDestroy() { - if(this.documentResponsiveListener) { - this.documentResponsiveListener(); - } - - if(this.autoplayInterval) { - this.stopAutoplay(); - } - } -} - -@NgModule({ - imports: [CommonModule,SharedModule], - exports: [Carousel,SharedModule], - declarations: [Carousel] -}) -export class CarouselModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/chart/chart.spec.ts b/dashboard/src/app/components/chart/chart.spec.ts deleted file mode 100644 index a3285939b..000000000 --- a/dashboard/src/app/components/chart/chart.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { UIChart } from './chart'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('UIChart', () => { - - let chart: UIChart; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - UIChart - ] - }); - - fixture = TestBed.createComponent(UIChart); - chart = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/chart/chart.ts b/dashboard/src/app/components/chart/chart.ts deleted file mode 100644 index c2e9e1981..000000000 --- a/dashboard/src/app/components/chart/chart.ts +++ /dev/null @@ -1,112 +0,0 @@ -import {NgModule,Component,ElementRef,AfterViewInit,OnDestroy,Input,Output,EventEmitter} from '@angular/core'; -import {CommonModule} from '@angular/common'; - -declare var Chart: any; - -@Component({ - selector: 'p-chart', - template: ` -
- -
- ` -}) -export class UIChart implements AfterViewInit, OnDestroy { - - @Input() type: string; - - @Input() options: any = {}; - - @Input() width: string; - - @Input() height: string; - - @Input() responsive: boolean = true; - - @Output() onDataSelect: EventEmitter = new EventEmitter(); - - initialized: boolean; - - _data: any; - - chart: any; - - constructor(public el: ElementRef) {} - - @Input() get data(): any { - return this._data; - } - - set data(val:any) { - this._data = val; - this.reinit(); - } - - ngAfterViewInit() { - this.initChart(); - this.initialized = true; - } - - onCanvasClick(event) { - if(this.chart) { - let element = this.chart.getElementAtEvent(event); - let dataset = this.chart.getDatasetAtEvent(event); - if(element&&element[0]&&dataset) { - this.onDataSelect.emit({originalEvent: event, element: element[0], dataset: dataset}); - } - } - } - - initChart() { - let opts = this.options||{}; - opts.responsive = this.responsive; - - this.chart = new Chart(this.el.nativeElement.children[0].children[0], { - type: this.type, - data: this.data, - options: this.options - }); - } - - getCanvas() { - return this.el.nativeElement.children[0].children[0]; - } - - getBase64Image() { - return this.chart.toBase64Image(); - } - - generateLegend() { - if(this.chart) { - this.chart.generateLegend(); - } - } - - refresh() { - if(this.chart) { - this.chart.update(); - } - } - - reinit() { - if(this.chart) { - this.chart.destroy(); - this.initChart(); - } - } - - ngOnDestroy() { - if(this.chart) { - this.chart.destroy(); - this.initialized = false; - this.chart = null; - } - } -} - -@NgModule({ - imports: [CommonModule], - exports: [UIChart], - declarations: [UIChart] -}) -export class ChartModule { } diff --git a/dashboard/src/app/components/checkbox/checkbox.css b/dashboard/src/app/components/checkbox/checkbox.css deleted file mode 100644 index ac3e56d4f..000000000 --- a/dashboard/src/app/components/checkbox/checkbox.css +++ /dev/null @@ -1,25 +0,0 @@ -.ui-chkbox { - display: inline-block; - cursor: pointer; - vertical-align: middle; - margin-right: .25em; -} - -.ui-chkbox .ui-chkbox-box { - width: 1.125em; - height: 1.125em; - line-height: 1.125em; - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; - text-align: center; -} - -.ui-chkbox .ui-chkbox-icon { - display: block; -} - -.ui-chkbox-label { - vertical-align: middle; -} - diff --git a/dashboard/src/app/components/checkbox/checkbox.spec.ts b/dashboard/src/app/components/checkbox/checkbox.spec.ts deleted file mode 100644 index 0d821c0ec..000000000 --- a/dashboard/src/app/components/checkbox/checkbox.spec.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Checkbox } from './checkbox'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Checkbox', () => { - - let checkbox: Checkbox; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Checkbox - ] - }); - - fixture = TestBed.createComponent(Checkbox); - checkbox = fixture.componentInstance; - }); - - it('should check the input on click', () => { - const boxEl = fixture.nativeElement.querySelector('.ui-chkbox-box'); - boxEl.click(); - fixture.detectChanges(); - - const input = fixture.nativeElement.querySelector('input'); - expect(input.checked).toBe(true); - }); -}); \ No newline at end of file diff --git a/dashboard/src/app/components/checkbox/checkbox.ts b/dashboard/src/app/components/checkbox/checkbox.ts deleted file mode 100644 index cc03b2ac3..000000000 --- a/dashboard/src/app/components/checkbox/checkbox.ts +++ /dev/null @@ -1,157 +0,0 @@ -import {NgModule,Component,Input,Output,EventEmitter,forwardRef,ChangeDetectorRef} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {NG_VALUE_ACCESSOR, ControlValueAccessor, FormControl} from '@angular/forms'; - -export const CHECKBOX_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => Checkbox), - multi: true -}; - -@Component({ - selector: 'p-checkbox', - template: ` -
-
- -
-
- -
-
- - `, - providers: [CHECKBOX_VALUE_ACCESSOR] -}) -export class Checkbox implements ControlValueAccessor { - - @Input() value: any; - - @Input() name: string; - - @Input() disabled: boolean; - - @Input() binary: string; - - @Input() label: string; - - @Input() tabindex: number; - - @Input() inputId: string; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() formControl: FormControl; - - @Output() onChange: EventEmitter = new EventEmitter(); - - model: any; - - onModelChange: Function = () => {}; - - onModelTouched: Function = () => {}; - - focused: boolean = false; - - checked: boolean = false; - - constructor(private cd: ChangeDetectorRef) {} - - onClick(event,checkbox,focus:boolean) { - event.preventDefault(); - - if(this.disabled) { - return; - } - - this.checked = !this.checked; - this.updateModel(); - - if(focus) { - checkbox.focus(); - } - } - - updateModel() { - if(!this.binary) { - if(this.checked) - this.addValue(); - else - this.removeValue(); - - this.onModelChange(this.model); - - if(this.formControl) { - this.formControl.setValue(this.model); - } - } - else { - this.onModelChange(this.checked); - } - - this.onChange.emit(this.checked); - } - - handleChange(event) { - this.checked = event.target.checked; - this.updateModel(); - } - - isChecked(): boolean { - if(this.binary) - return this.model; - else - return this.model && this.model.indexOf(this.value) > -1; - } - - removeValue() { - this.model = this.model.filter(val => val !== this.value); - } - - addValue() { - if(this.model) - this.model = [...this.model, this.value]; - else - this.model = [this.value]; - } - - onFocus(event) { - this.focused = true; - } - - onBlur(event) { - this.focused = false; - this.onModelTouched(); - } - - writeValue(model: any) : void { - this.model = model; - this.checked = this.isChecked(); - this.cd.markForCheck(); - } - - registerOnChange(fn: Function): void { - this.onModelChange = fn; - } - - registerOnTouched(fn: Function): void { - this.onModelTouched = fn; - } - - setDisabledState(val: boolean): void { - this.disabled = val; - } -} - -@NgModule({ - imports: [CommonModule], - exports: [Checkbox], - declarations: [Checkbox] -}) -export class CheckboxModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/chips/chips.css b/dashboard/src/app/components/chips/chips.css deleted file mode 100644 index ae3568a93..000000000 --- a/dashboard/src/app/components/chips/chips.css +++ /dev/null @@ -1,59 +0,0 @@ -.ui-chips > ul.ui-inputtext { - clear: left; - cursor: text; - list-style-type: none; - margin: 0; - overflow: hidden; - padding: 0 .25em; -} - -.ui-chips-token { - cursor: default; - display: inline-block; - vertical-align: middle; - overflow: hidden; - padding: .125em .5em; - white-space: nowrap; - position: relative; - margin-right: .125em; - border: 0 none; - font-size: .9em; -} - -.ui-chips-token .ui-chips-token-label { - display: block; - margin-right: 2em; -} - -.ui-chips > .ui-state-disabled .ui-chips-token-label { - margin-right: 0; -} - -.ui-chips-token .ui-chips-token-icon { - margin-top: -.5em; - position: absolute; - right: 0.2em; - top: 50%; - cursor: pointer; -} - -.ui-chips-input-token { - display: inline-block; - vertical-align: middle; - list-style-type: none; - margin: 0 0 0 .125em; - padding: .25em .25em .25em 0; -} - -.ui-chips-input-token input { - border: 0 none; - width: 10em; - outline: medium none; - background-color: transparent; - margin: 0; - padding: 0; - box-shadow: none; - -moz-border-radius: 0; - -webkit-border-radius: 0; - border-radius: 0; -} \ No newline at end of file diff --git a/dashboard/src/app/components/chips/chips.spec.ts b/dashboard/src/app/components/chips/chips.spec.ts deleted file mode 100644 index c473aa28f..000000000 --- a/dashboard/src/app/components/chips/chips.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Chips } from './chips'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Chips', () => { - - let chips: Chips; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Chips - ] - }); - - fixture = TestBed.createComponent(Chips); - chips = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/chips/chips.ts b/dashboard/src/app/components/chips/chips.ts deleted file mode 100644 index a02a4df74..000000000 --- a/dashboard/src/app/components/chips/chips.ts +++ /dev/null @@ -1,227 +0,0 @@ -import {NgModule,Component,ElementRef,Input,Output,EventEmitter,AfterContentInit,ContentChildren,QueryList,TemplateRef,IterableDiffers,forwardRef} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {SharedModule,PrimeTemplate} from '../common/shared'; -import {InputTextModule} from '../inputtext/inputtext'; -import {DomHandler} from '../dom/domhandler'; -import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; - -export const CHIPS_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => Chips), - multi: true -}; - -@Component({ - selector: 'p-chips', - template: ` -
-
    -
  • - - {{field ? resolveFieldData(item,field) : item}} - -
  • -
  • - -
  • -
-
- `, - providers: [DomHandler,CHIPS_VALUE_ACCESSOR] -}) -export class Chips implements AfterContentInit,ControlValueAccessor { - - @Input() style: any; - - @Input() styleClass: string; - - @Input() disabled: boolean; - - @Output() onAdd: EventEmitter = new EventEmitter(); - - @Output() onRemove: EventEmitter = new EventEmitter(); - - @Input() field: string; - - @Input() placeholder: string; - - @Input() max: number; - - @Input() tabindex: number; - - @Input() inputId: string; - - @Input() allowDuplicate: boolean = true; - - @Input() inputStyle: any; - - @Input() inputStyleClass: any; - - @Input() addOnTab: boolean; - - @Input() addOnBlur: boolean; - - @Output() onFocus: EventEmitter = new EventEmitter(); - - @Output() onBlur: EventEmitter = new EventEmitter(); - - @ContentChildren(PrimeTemplate) templates: QueryList; - - public itemTemplate: TemplateRef; - - value: any; - - onModelChange: Function = () => {}; - - onModelTouched: Function = () => {}; - - valueChanged: boolean; - - focus: boolean; - - constructor(public el: ElementRef, public domHandler: DomHandler) {} - - ngAfterContentInit() { - this.templates.forEach((item) => { - switch(item.getType()) { - case 'item': - this.itemTemplate = item.template; - break; - - default: - this.itemTemplate = item.template; - break; - } - }); - } - - writeValue(value: any) : void { - this.value = value; - } - - registerOnChange(fn: Function): void { - this.onModelChange = fn; - } - - registerOnTouched(fn: Function): void { - this.onModelTouched = fn; - } - - setDisabledState(val: boolean): void { - this.disabled = val; - } - - resolveFieldData(data: any, field: string): any { - if(data && field) { - if(field.indexOf('.') == -1) { - return data[field]; - } - else { - let fields: string[] = field.split('.'); - let value = data; - for(var i = 0, len = fields.length; i < len; ++i) { - value = value[fields[i]]; - } - return value; - } - } - else { - return null; - } - } - - onInputFocus(event: FocusEvent) { - this.focus = true; - this.onFocus.emit(event); - } - - onInputBlur(event: FocusEvent, inputEL: HTMLInputElement) { - this.focus = false; - if(this.addOnBlur && inputEL.value) { - this.addItem(event, inputEL.value); - inputEL.value = ''; - } - this.onModelTouched(); - this.onBlur.emit(event); - } - - removeItem(event: Event, index: number): void { - if(this.disabled) { - return; - } - - let removedItem = this.value[index]; - this.value = this.value.filter((val, i) => i!=index); - this.onModelChange(this.value); - this.onRemove.emit({ - originalEvent: event, - value: removedItem - }); - } - - addItem(event: Event, item: string): void { - this.value = this.value||[]; - if(item && item.trim().length && (!this.max||this.max > item.length)) { - if(this.allowDuplicate || this.value.indexOf(item) === -1) { - this.value = [...this.value, item]; - this.onModelChange(this.value); - this.onAdd.emit({ - originalEvent: event, - value: item - }); - } - } - } - - onKeydown(event: KeyboardEvent, inputEL: HTMLInputElement): void { - switch(event.which) { - //backspace - case 8: - if(inputEL.value.length === 0 && this.value && this.value.length > 0) { - this.value = [...this.value]; - let removedItem = this.value.pop(); - this.onModelChange(this.value); - this.onRemove.emit({ - originalEvent: event, - value: removedItem - }); - } - break; - - //enter - case 13: - this.addItem(event, inputEL.value); - inputEL.value = ''; - - event.preventDefault(); - break; - - case 9: - if(this.addOnTab && inputEL.value !== '') { - this.addItem(event, inputEL.value); - inputEL.value = ''; - - event.preventDefault(); - } - break; - - default: - if(this.max && this.value && this.max === this.value.length) { - event.preventDefault(); - } - break; - } - } - - get maxedOut(): boolean { - return this.max && this.value && this.max === this.value.length; - } -} - -@NgModule({ - imports: [CommonModule,InputTextModule,SharedModule], - exports: [Chips,InputTextModule,SharedModule], - declarations: [Chips] -}) -export class ChipsModule { } diff --git a/dashboard/src/app/components/codehighlighter/codehighlighter.spec.ts b/dashboard/src/app/components/codehighlighter/codehighlighter.spec.ts deleted file mode 100644 index 2ed65aa80..000000000 --- a/dashboard/src/app/components/codehighlighter/codehighlighter.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { CodeHighlighter } from './codehighlighter'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('CodeHighlighter', () => { - - let codehighlighter: CodeHighlighter; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - CodeHighlighter - ] - }); - - fixture = TestBed.createComponent(CodeHighlighter); - codehighlighter = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/codehighlighter/codehighlighter.ts b/dashboard/src/app/components/codehighlighter/codehighlighter.ts deleted file mode 100644 index c66262191..000000000 --- a/dashboard/src/app/components/codehighlighter/codehighlighter.ts +++ /dev/null @@ -1,25 +0,0 @@ -import {NgModule,Directive,ElementRef,OnInit} from '@angular/core'; -import {CommonModule} from '@angular/common'; - -@Directive({ - selector: '[pCode]' -}) -export class CodeHighlighter implements OnInit { - - constructor(public el: ElementRef) {} - - ngOnInit() { - if(window['Prism']) { - window['Prism'].highlightElement(this.el.nativeElement); - } - } -} - -@NgModule({ - imports: [CommonModule], - exports: [CodeHighlighter], - declarations: [CodeHighlighter] -}) -export class CodeHighlighterModule { } - - diff --git a/dashboard/src/app/components/colorpicker/colorpicker.css b/dashboard/src/app/components/colorpicker/colorpicker.css deleted file mode 100644 index af49f4b9b..000000000 --- a/dashboard/src/app/components/colorpicker/colorpicker.css +++ /dev/null @@ -1,87 +0,0 @@ -.ui-colorpicker { - display: inline-block; -} - -.ui-colorpicker-dragging { - cursor: pointer; -} - -.ui-colorpicker-overlay { - position: relative; -} - -.ui-colorpicker-panel { - position: relative; - width: 193px; - height: 166px; - background-color: #323232; - border-color: #191919; -} - -.ui-colorpicker-overlay-panel { - display: none; - position: absolute; -} - -.ui-colorpicker-preview { - width: 2em; - cursor: pointer; -} - -.ui-colorpicker-panel .ui-colorpicker-content { - position: relative; -} - -.ui-colorpicker-panel .ui-colorpicker-color-selector { - width: 150px; - height: 150px; - top: 8px; - left: 8px; - position: absolute; -} - -.ui-colorpicker-panel .ui-colorpicker-color { - width: 150px; - height: 150px; - background: transparent url("./images/color.png") no-repeat left top; -} - -.ui-colorpicker-panel .ui-colorpicker-color-handle { - position: absolute; - top: 0px; - left: 150px; - border-radius: 100%; - width: 10px; - height: 10px; - border: 1px solid #ffffff; - margin: -5px 0 0 -5px; - cursor: pointer; -} - -.ui-colorpicker-panel .ui-colorpicker-hue { - background: transparent url("./images/hue.png") no-repeat left top; - width: 17px; - height: 150px; - top: 8px; - left: 167px; - position: absolute; - opacity: .85; -} - -.ui-colorpicker-panel .ui-colorpicker-hue-handle { - position: absolute; - top: 150px; - left: 0px; - width: 21px; - margin-left: -2px; - margin-top: -5px; - height: 10px; - border: 2px solid #ffffff; - opacity: .85; - cursor: pointer; - } - - .ui-colorpicker-panel.ui-state-disabled .ui-colorpicker-hue-handle, - .ui-colorpicker-panel.ui-state-disabled .ui-colorpicker-color-handle { - opacity: .5; - } \ No newline at end of file diff --git a/dashboard/src/app/components/colorpicker/colorpicker.spec.ts b/dashboard/src/app/components/colorpicker/colorpicker.spec.ts deleted file mode 100644 index f8b09636f..000000000 --- a/dashboard/src/app/components/colorpicker/colorpicker.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { ColorPicker } from './colorpicker'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('ColorPicker', () => { - - let colorpicker: ColorPicker; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - ColorPicker - ] - }); - - fixture = TestBed.createComponent(ColorPicker); - colorpicker = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/colorpicker/colorpicker.ts b/dashboard/src/app/components/colorpicker/colorpicker.ts deleted file mode 100644 index 0d5fc6974..000000000 --- a/dashboard/src/app/components/colorpicker/colorpicker.ts +++ /dev/null @@ -1,507 +0,0 @@ -import { NgModule, Component, ElementRef, Input, Output, AfterViewInit, AfterViewChecked, OnDestroy, EventEmitter, forwardRef, Renderer2, ViewChild, ChangeDetectorRef } from '@angular/core'; -import { trigger, state, style, transition, animate } from '@angular/animations'; -import { CommonModule } from '@angular/common'; -import { DomHandler } from '../dom/domhandler'; -import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms'; - -export const COLORPICKER_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ColorPicker), - multi: true -}; - -@Component({ - selector: 'p-colorPicker', - template: ` -
- -
-
-
-
-
-
-
-
-
-
-
-
-
- `, - animations: [ - trigger('panelState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]) - ], - providers: [DomHandler,COLORPICKER_VALUE_ACCESSOR] -}) -export class ColorPicker implements ControlValueAccessor, AfterViewInit, AfterViewChecked, OnDestroy{ - - @Input() style: any; - - @Input() styleClass: string; - - @Input() inline: boolean; - - @Input() format: string = 'hex'; - - @Input() appendTo: string; - - @Input() disabled: boolean; - - @Input() tabindex: string; - - @Input() inputId: string; - - @Output() onChange: EventEmitter = new EventEmitter(); - - @ViewChild('panel') panelViewChild: ElementRef; - - @ViewChild('colorSelector') colorSelectorViewChild: ElementRef; - - @ViewChild('colorHandle') colorHandleViewChild: ElementRef; - - @ViewChild('hue') hueViewChild: ElementRef; - - @ViewChild('hueHandle') hueHandleViewChild: ElementRef; - - @ViewChild('input') inputViewChild: ElementRef; - - value: any; - - inputBgColor: string; - - shown: boolean; - - panelVisible: boolean; - - defaultColor: string = 'ff0000'; - - onModelChange: Function = () => {}; - - onModelTouched: Function = () => {}; - - documentClickListener: Function; - - documentMousemoveListener: Function; - - documentMouseupListener: Function; - - documentHueMoveListener: Function; - - selfClick: boolean; - - colorDragging: boolean; - - hueDragging: boolean; - - constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2, public cd: ChangeDetectorRef) {} - - ngAfterViewInit() { - if (this.appendTo) { - if (this.appendTo === 'body') - document.body.appendChild(this.panelViewChild.nativeElement); - else - this.domHandler.appendChild(this.panelViewChild.nativeElement, this.appendTo); - } - } - - ngAfterViewChecked() { - if(this.shown) { - this.onShow(); - this.shown = false; - } - } - - onHueMousedown(event: MouseEvent) { - if(this.disabled) { - return; - } - - this.bindDocumentMousemoveListener(); - this.bindDocumentMouseupListener(); - - this.hueDragging = true; - this.pickHue(event); - } - - pickHue(event: MouseEvent) { - let top: number = this.hueViewChild.nativeElement.getBoundingClientRect().top + (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0); - this.value = this.validateHSB({ - h: Math.floor(360 * (150 - Math.max(0, Math.min(150, (event.pageY - top)))) / 150), - s: this.value.s, - b: this.value.b - }); - - this.updateColorSelector(); - this.updateUI(); - this.updateModel(); - this.onChange.emit({originalEvent: event, value: this.getValueToUpdate()}); - } - - onColorMousedown(event: MouseEvent) { - if(this.disabled) { - return; - } - - this.bindDocumentMousemoveListener(); - this.bindDocumentMouseupListener(); - - this.colorDragging = true; - this.pickColor(event); - } - - pickColor(event: MouseEvent) { - let rect = this.colorSelectorViewChild.nativeElement.getBoundingClientRect(); - let top = rect.top + (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0); - let left = rect.left + document.body.scrollLeft; - let saturation = Math.floor(100 * (Math.max(0, Math.min(150, (event.pageX - left)))) / 150); - let brightness = Math.floor(100 * (150 - Math.max(0, Math.min(150, (event.pageY - top)))) / 150); - this.value = this.validateHSB({ - h: this.value.h, - s: saturation, - b: brightness - }); - - this.updateUI(); - this.updateModel(); - this.onChange.emit({originalEvent: event, value: this.getValueToUpdate()}); - } - - getValueToUpdate() { - let val: any; - switch(this.format) { - case 'hex': - val = '#' + this.HSBtoHEX(this.value); - break; - - case 'rgb': - val = this.HSBtoRGB(this.value); - break; - - case 'hsb': - val = this.value; - break; - } - - return val; - } - - updateModel(): void { - this.onModelChange(this.getValueToUpdate()); - } - - writeValue(value: any): void { - if(value) { - switch(this.format) { - case 'hex': - this.value = this.HEXtoHSB(value); - break; - - case 'rgb': - this.value = this.RGBtoHSB(value); - break; - - case 'hsb': - this.value = value; - break; - } - } - else { - this.value = this.HEXtoHSB(this.defaultColor); - } - - this.updateColorSelector(); - this.updateUI(); - } - - updateColorSelector() { - this.colorSelectorViewChild.nativeElement.style.backgroundColor = '#' + this.HSBtoHEX(this.value); - } - - updateUI() { - this.colorHandleViewChild.nativeElement.style.left = Math.floor(150 * this.value.s / 100) + 'px'; - this.colorHandleViewChild.nativeElement.style.top = Math.floor(150 * (100 - this.value.b) / 100) + 'px'; - this.hueHandleViewChild.nativeElement.style.top = Math.floor(150 - (150 * this.value.h / 360)) + 'px'; - this.inputBgColor = '#' + this.HSBtoHEX(this.value); - } - - onInputFocus() { - this.onModelTouched(); - } - - show() { - this.panelViewChild.nativeElement.style.zIndex = String(++DomHandler.zindex); - this.panelVisible = true; - this.shown = true; - } - - hide() { - this.panelVisible = false; - this.unbindDocumentClickListener(); - } - - onShow() { - this.alignPanel(); - this.bindDocumentClickListener(); - } - - alignPanel() { - if(this.appendTo) - this.domHandler.absolutePosition(this.panelViewChild.nativeElement, this.inputViewChild.nativeElement); - else - this.domHandler.relativePosition(this.panelViewChild.nativeElement, this.inputViewChild.nativeElement); - } - - onInputClick() { - this.selfClick = true; - this.togglePanel(); - } - - togglePanel() { - if(!this.panelVisible) - this.show(); - else - this.hide(); - } - - onInputKeydown(event: KeyboardEvent) { - switch(event.which) { - //space - case 32: - this.togglePanel(); - event.preventDefault(); - break; - - //escape and tab - case 27: - case 9: - this.hide(); - break; - } - } - - onPanelClick() { - this.selfClick = true; - } - - registerOnChange(fn: Function): void { - this.onModelChange = fn; - } - - registerOnTouched(fn: Function): void { - this.onModelTouched = fn; - } - - setDisabledState(val: boolean): void { - this.disabled = val; - } - - bindDocumentClickListener() { - if(!this.documentClickListener) { - this.documentClickListener = this.renderer.listen('document', 'click', () => { - if(!this.selfClick) { - this.panelVisible = false; - this.unbindDocumentClickListener(); - } - - this.selfClick = false; - this.cd.markForCheck(); - }); - } - } - - unbindDocumentClickListener() { - if(this.documentClickListener) { - this.documentClickListener(); - this.documentClickListener = null; - } - } - - bindDocumentMousemoveListener() { - if(!this.documentMousemoveListener) { - this.documentMousemoveListener = this.renderer.listen('document', 'mousemove', (event: MouseEvent) => { - if(this.colorDragging) { - this.pickColor(event); - } - - if(this.hueDragging) { - this.pickHue(event); - } - }); - } - } - - unbindDocumentMousemoveListener() { - if(this.documentMousemoveListener) { - this.documentMousemoveListener(); - this.documentMousemoveListener = null; - } - } - - bindDocumentMouseupListener() { - if(!this.documentMouseupListener) { - this.documentMouseupListener = this.renderer.listen('document', 'mouseup', () => { - this.colorDragging = false; - this.hueDragging = false; - this.unbindDocumentMousemoveListener(); - this.unbindDocumentMouseupListener(); - }); - } - } - - unbindDocumentMouseupListener() { - if(this.documentMouseupListener) { - this.documentMouseupListener(); - this.documentMouseupListener = null; - } - } - - validateHSB(hsb) { - return { - h: Math.min(360, Math.max(0, hsb.h)), - s: Math.min(100, Math.max(0, hsb.s)), - b: Math.min(100, Math.max(0, hsb.b)) - }; - } - - validateRGB(rgb) { - return { - r: Math.min(255, Math.max(0, rgb.r)), - g: Math.min(255, Math.max(0, rgb.g)), - b: Math.min(255, Math.max(0, rgb.b)) - }; - } - - validateHEX(hex) { - var len = 6 - hex.length; - if (len > 0) { - var o = []; - for (var i=0; i -1) ? hex.substring(1) : hex), 16); - return {r: hexValue >> 16, g: (hexValue & 0x00FF00) >> 8, b: (hexValue & 0x0000FF)}; - } - - HEXtoHSB(hex) { - return this.RGBtoHSB(this.HEXtoRGB(hex)); - } - - RGBtoHSB(rgb) { - var hsb = { - h: 0, - s: 0, - b: 0 - }; - var min = Math.min(rgb.r, rgb.g, rgb.b); - var max = Math.max(rgb.r, rgb.g, rgb.b); - var delta = max - min; - hsb.b = max; - if (max != 0) { - - } - hsb.s = max != 0 ? 255 * delta / max : 0; - if (hsb.s != 0) { - if (rgb.r == max) { - hsb.h = (rgb.g - rgb.b) / delta; - } else if (rgb.g == max) { - hsb.h = 2 + (rgb.b - rgb.r) / delta; - } else { - hsb.h = 4 + (rgb.r - rgb.g) / delta; - } - } else { - hsb.h = -1; - } - hsb.h *= 60; - if (hsb.h < 0) { - hsb.h += 360; - } - hsb.s *= 100/255; - hsb.b *= 100/255; - return hsb; - } - - HSBtoRGB(hsb) { - var rgb = { - r: null, g: null, b: null - }; - var h = Math.round(hsb.h); - var s = Math.round(hsb.s*255/100); - var v = Math.round(hsb.b*255/100); - if(s == 0) { - rgb = { - r: v, - g: v, - b: v - } - } - else { - var t1 = v; - var t2 = (255-s)*v/255; - var t3 = (t1-t2)*(h%60)/60; - if(h==360) h = 0; - if(h<60) {rgb.r=t1; rgb.b=t2; rgb.g=t2+t3} - else if(h<120) {rgb.g=t1; rgb.b=t2; rgb.r=t1-t3} - else if(h<180) {rgb.g=t1; rgb.r=t2; rgb.b=t2+t3} - else if(h<240) {rgb.b=t1; rgb.r=t2; rgb.g=t1-t3} - else if(h<300) {rgb.b=t1; rgb.g=t2; rgb.r=t2+t3} - else if(h<360) {rgb.r=t1; rgb.g=t2; rgb.b=t1-t3} - else {rgb.r=0; rgb.g=0; rgb.b=0} - } - return {r:Math.round(rgb.r), g:Math.round(rgb.g), b:Math.round(rgb.b)}; - } - - RGBtoHEX(rgb) { - var hex = [ - rgb.r.toString(16), - rgb.g.toString(16), - rgb.b.toString(16) - ]; - - for(var key in hex) { - if(hex[key].length == 1) { - hex[key] = '0' + hex[key]; - } - } - - return hex.join(''); - } - - HSBtoHEX(hsb) { - return this.RGBtoHEX(this.HSBtoRGB(hsb)); - } - - ngOnDestroy() { - this.unbindDocumentClickListener(); - - if (this.appendTo) { - this.el.nativeElement.appendChild(this.panelViewChild.nativeElement); - } - } -} - -@NgModule({ - imports: [CommonModule], - exports: [ColorPicker], - declarations: [ColorPicker] -}) -export class ColorPickerModule { } diff --git a/dashboard/src/app/components/colorpicker/images/color.png b/dashboard/src/app/components/colorpicker/images/color.png deleted file mode 100644 index 561cdd9c59a498b499cbfd1295dc4d2037e235ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10355 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 RdwKu>002ovPDHLkV1myV#+d*B diff --git a/dashboard/src/app/components/colorpicker/images/hue.png b/dashboard/src/app/components/colorpicker/images/hue.png deleted file mode 100644 index 8efa252578a2c8c513c6eeec7e183aa2f8355f5b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 293 zcmV+=0owkFP)~mb#^S1@C_)KRiU;6-7(0&`CkU5}4m1d7IrNET?{$U;Xcz`hnwej&DWF zNg$~*dY-BXbYh&&IgceyZD$ZX!DGwqgNG^>K$Xdp0aaYZAgeLA;Hi(t=#dVf1dn^3 zt$`})Egsa{HK>mTqbGRkX$8z7A4XUWOYr9AM47fD6s(AFz rLFy}o|N2Bt9oN*rQ}#A1Dtr3{xkh4EFufcl00000NkvXXu0mjf>=A&> diff --git a/dashboard/src/app/components/common/I18N.ts b/dashboard/src/app/components/common/I18N.ts deleted file mode 100644 index 6baa84ada..000000000 --- a/dashboard/src/app/components/common/I18N.ts +++ /dev/null @@ -1,12 +0,0 @@ -export class I18N { - static language = "en"; - static keyID = {}; - - static get(key, params = []) { - let str = this.keyID[key] || key; - params.forEach((param, index) => { - str = str.replace("{" + index + "}", param); - }); - return str; - } -} \ No newline at end of file diff --git a/dashboard/src/app/components/common/api.ts b/dashboard/src/app/components/common/api.ts deleted file mode 100644 index abac56dc5..000000000 --- a/dashboard/src/app/components/common/api.ts +++ /dev/null @@ -1,44 +0,0 @@ -export { DomHandler } from '../dom/domhandler'; -export { TreeNode } from './treenode'; -export { TreeDragDropService } from './treedragdropservice'; -export { TreeNodeDragEvent } from './treenodedragevent'; -export { BlockableUI } from './blockableui'; -export { Confirmation } from './confirmation'; -export { ConfirmationService } from './confirmationservice'; -export { FilterMetadata } from './filtermetadata'; -export { LazyLoadEvent } from './lazyloadevent'; -export { MenuItem } from './menuitem'; -export { Message } from './message'; -export { SelectItem } from './selectitem'; -export { SelectItemGroup } from './selectitemgroup'; -export { SortMeta } from './sortmeta'; -export { SortEvent } from './sortevent'; -export { I18N } from './I18N'; - -export { FormModule } from '../form/form'; -export { InputTextModule } from '../inputtext/inputtext'; -export { InputTextareaModule } from '../inputtextarea/inputtextarea'; -export { CheckboxModule } from '../checkbox/checkbox'; -export { ConfirmDialogModule } from '../confirmdialog/confirmdialog'; -export { ButtonModule } from '../button/button'; -export { BadgeModule } from '../badge/badge'; -export { TabViewModule } from '../tabview/tabview'; -export { DataTableModule } from '../datatable/datatable'; -export { SplitButtonModule } from '../splitbutton/splitbutton'; -export { DropMenuModule } from '../dropmenu/dropmenu'; -export { DialogModule } from '../dialog/dialog'; -export { DropdownModule } from '../dropdown/dropdown'; -export { PasswordModule } from '../password/password'; -export { CardModule } from '../card/card'; -export { ChartModule } from '../chart/chart'; -export { BreadcrumbModule } from '../breadcrumb/breadcrumb'; -export { TableModule } from '../table/table'; -export { MessageModule } from '../message/message'; -export { MsgBoxModule } from '../msgbox/msgbox'; -export { MultiSelectModule } from '../multiselect/multiselect'; -export { OverlayPanelModule } from '../overlaypanel/overlaypanel'; -export { RadioButtonModule } from '../radiobutton/radiobutton'; -export { SelectButtonModule } from '../selectbutton/selectbutton'; -export { GrowlModule } from '../growl/growl'; -export { PanelModule } from '../panel/panel'; -export { SpinnerModule } from '../spinner/spinner'; diff --git a/dashboard/src/app/components/common/blockableui.ts b/dashboard/src/app/components/common/blockableui.ts deleted file mode 100644 index fd62e1705..000000000 --- a/dashboard/src/app/components/common/blockableui.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface BlockableUI { - getBlockableElement(): HTMLElement; -} \ No newline at end of file diff --git a/dashboard/src/app/components/common/common.scss b/dashboard/src/app/components/common/common.scss deleted file mode 100644 index 51b19e6e9..000000000 --- a/dashboard/src/app/components/common/common.scss +++ /dev/null @@ -1,193 +0,0 @@ -.ui-widget, .ui-widget * { - box-sizing: border-box; -} -.ui-helper-hidden { - display: none !important; -} -.ui-helper-hidden-accessible { - border: 0; - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} -.ui-helper-hidden-accessible input, -.ui-helper-hidden-accessible select { - transform: scale(0); -} -.ui-helper-reset { - margin: 0; - padding: 0; - border: 0; - outline: 0; - line-height: 1.3; - text-decoration: none; - font-size: 100%; - list-style: none; -} -.ui-helper-clearfix::before, -.ui-helper-clearfix::after { - content: ""; - display: table; -} -.ui-helper-clearfix::after { - clear: both; -} -.ui-helper-clearfix { - zoom: 1; -} -.ui-helper-zfix { - width: 100%; - height: 100%; - top: 0; - left: 0; - position: absolute; - opacity: 0; - filter: Alpha(Opacity=0); -} -.ui-state-disabled { - cursor: default !important; -} -.ui-state-disabled a { - cursor: default !important; -} -.ui-icon { - display: block; - text-indent: -99999px; - overflow: hidden; - background-repeat: no-repeat; -} -.ui-widget-overlay { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; -} -.ui-resizable { - position: relative; -} -.ui-resizable-handle { - position: absolute; - font-size: 0.1px; - display: block; -} -.ui-resizable-disabled .ui-resizable-handle, -.ui-resizable-autohide .ui-resizable-handle { - display: none; -} -.ui-resizable-n { - cursor: n-resize; - height: 7px; - width: 100%; - top: -5px; - left: 0; -} -.ui-resizable-s { - cursor: s-resize; - height: 7px; - width: 100%; - bottom: -5px; - left: 0; -} -.ui-resizable-e { - cursor: e-resize; - width: 7px; - right: -5px; - top: 0; - height: 100%; -} -.ui-resizable-w { - cursor: w-resize; - width: 7px; - left: -5px; - top: 0; - height: 100%; -} -.ui-resizable-se { - cursor: se-resize; - width: 12px; - height: 12px; - right: 1px; - bottom: 1px; -} -.ui-resizable-sw { - cursor: sw-resize; - width: 9px; - height: 9px; - left: -5px; - bottom: -5px; -} -.ui-resizable-nw { - cursor: nw-resize; - width: 9px; - height: 9px; - left: -5px; - top: -5px; -} -.ui-resizable-ne { - cursor: ne-resize; - width: 9px; - height: 9px; - right: -5px; - top: -5px; -} -.ui-shadow { - -webkit-box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.3); - -moz-box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.3); - box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.3); -} -.ui-unselectable-text { - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -o-user-select: none; - user-select: none; -} -.ui-scrollbar-measure { - width: 100px; - height: 100px; - overflow: scroll; - position: absolute; - top: -9999px; -} -.ui-overflow-hidden { - overflow: hidden; -} - -::-webkit-input-placeholder { /* WebKit, Blink, Edge */ - color: #898989; -} -:-moz-placeholder { /* Mozilla Firefox 4 to 18 */ - color: #898989; - opacity: 1; -} -::-moz-placeholder { /* Mozilla Firefox 19+ */ - color: #898989; - opacity: 1; -} -:-ms-input-placeholder { /* Internet Explorer 10-11 */ - color: #898989; -} -::-ms-input-placeholder { /* Microsoft Edge */ - color: #898989; -} -.ui-placeholder { - color: #898989; -} - -input[type="button"], -input[type="submit"], -input[type="reset"], -input[type="file"]::-webkit-file-upload-button, -button { - // @include border-radius(all, small); - @extend .ui-corner-all-large; -} - -.fa{ - font-size: 0.16rem; -} \ No newline at end of file diff --git a/dashboard/src/app/components/common/confirmation.ts b/dashboard/src/app/components/common/confirmation.ts deleted file mode 100644 index 2988c510e..000000000 --- a/dashboard/src/app/components/common/confirmation.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { EventEmitter } from '@angular/core'; - -export interface Confirmation { - message: string; - key?: string; - icon?: string; - acceptLabel?: string; - rejectLabel?: string; - isWarning?: boolean; - header?: string; - accept?: Function; - reject?: Function; - acceptVisible?: boolean; - rejectVisible?: boolean; - acceptEvent?: EventEmitter; - rejectEvent?: EventEmitter; -} diff --git a/dashboard/src/app/components/common/confirmationservice.ts b/dashboard/src/app/components/common/confirmationservice.ts deleted file mode 100644 index c96f104c4..000000000 --- a/dashboard/src/app/components/common/confirmationservice.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Subject } from 'rxjs/Subject'; -import { Observable } from 'rxjs/Observable'; -import { Confirmation } from './confirmation'; - -@Injectable() -export class ConfirmationService { - - private requireConfirmationSource = new Subject(); - private acceptConfirmationSource = new Subject(); - - requireConfirmation$ = this.requireConfirmationSource.asObservable(); - accept = this.acceptConfirmationSource.asObservable(); - - confirm(confirmation: Confirmation) { - this.requireConfirmationSource.next(confirmation); - return this; - } - - onAccept() { - this.acceptConfirmationSource.next(); - } -} \ No newline at end of file diff --git a/dashboard/src/app/components/common/filtermetadata.ts b/dashboard/src/app/components/common/filtermetadata.ts deleted file mode 100644 index 2fc78e4f4..000000000 --- a/dashboard/src/app/components/common/filtermetadata.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface FilterMetadata { - value?: any; - matchMode?: string; -} \ No newline at end of file diff --git a/dashboard/src/app/components/common/keys.pipe.ts b/dashboard/src/app/components/common/keys.pipe.ts deleted file mode 100644 index 7a8a3f0ac..000000000 --- a/dashboard/src/app/components/common/keys.pipe.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Pipe, PipeTransform } from '@angular/core'; - -@Pipe({ name: "Keys", pure: false }) -export class Keys implements PipeTransform{ - transform(value: any, args: any[] = null): any{ - return Object.keys(value); - } -} \ No newline at end of file diff --git a/dashboard/src/app/components/common/lazyloadevent.ts b/dashboard/src/app/components/common/lazyloadevent.ts deleted file mode 100644 index fa962033a..000000000 --- a/dashboard/src/app/components/common/lazyloadevent.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { SortMeta } from './sortmeta'; -import { FilterMetadata } from './filtermetadata'; - -export interface LazyLoadEvent { - first?: number; - rows?: number; - sortField?: string; - sortOrder?: number; - multiSortMeta?: SortMeta[]; - filters?: {[s: string]: FilterMetadata;}; - globalFilter?: any; -} \ No newline at end of file diff --git a/dashboard/src/app/components/common/menuitem.ts b/dashboard/src/app/components/common/menuitem.ts deleted file mode 100644 index 1d46f24bc..000000000 --- a/dashboard/src/app/components/common/menuitem.ts +++ /dev/null @@ -1,24 +0,0 @@ -import {EventEmitter} from '@angular/core'; - -export interface MenuItem { - label?: string; - icon?: string; - command?: (event?: any) => void; - url?: string; - routerLink?: any; - queryParams?: { [k: string]: any }; - items?: MenuItem[]|MenuItem[][]; - expanded?: boolean; - disabled?: boolean; - visible?: boolean; - target?: string; - routerLinkActiveOptions?: any; - separator?: boolean; - badge?: string; - badgeStyleClass?: string; - style?:any; - styleClass?:string; - title?: string; - id?: string; - automationId?: any; -} diff --git a/dashboard/src/app/components/common/message.ts b/dashboard/src/app/components/common/message.ts deleted file mode 100644 index fe2ff526f..000000000 --- a/dashboard/src/app/components/common/message.ts +++ /dev/null @@ -1,7 +0,0 @@ -export interface Message { - severity?: string; - summary?: string; - detail?: string; - id?: any; - key?: string; -} \ No newline at end of file diff --git a/dashboard/src/app/components/common/messageservice.ts b/dashboard/src/app/components/common/messageservice.ts deleted file mode 100644 index fae5e0de1..000000000 --- a/dashboard/src/app/components/common/messageservice.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Subject } from 'rxjs/Subject'; -import { Observable } from 'rxjs/Observable'; -import { Message } from './message'; - -@Injectable() -export class MessageService { - - private messageSource = new Subject(); - - messageObserver = this.messageSource.asObservable(); - - add(message: Message) { - if(message) { - this.messageSource.next(message); - } - } - - addAll(messages: Message[]) { - if(messages && messages.length) { - this.messageSource.next(messages); - } - } - - clear() { - this.messageSource.next(null); - } -} \ No newline at end of file diff --git a/dashboard/src/app/components/common/selectitem.ts b/dashboard/src/app/components/common/selectitem.ts deleted file mode 100644 index 37f427ac6..000000000 --- a/dashboard/src/app/components/common/selectitem.ts +++ /dev/null @@ -1,7 +0,0 @@ -export interface SelectItem { - label?: string; - value: any; - styleClass?: string; - icon?: string; - title?: string; -} \ No newline at end of file diff --git a/dashboard/src/app/components/common/selectitemgroup.ts b/dashboard/src/app/components/common/selectitemgroup.ts deleted file mode 100644 index 73f01d2bf..000000000 --- a/dashboard/src/app/components/common/selectitemgroup.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { SelectItem } from './selectitem'; - -export interface SelectItemGroup { - label: string; - value?: any; - items: SelectItem[]; -} \ No newline at end of file diff --git a/dashboard/src/app/components/common/shared.ts b/dashboard/src/app/components/common/shared.ts deleted file mode 100644 index 949e8ba3e..000000000 --- a/dashboard/src/app/components/common/shared.ts +++ /dev/null @@ -1,153 +0,0 @@ -import {NgModule,EventEmitter,Directive,ViewContainerRef,Input,Output,ContentChildren,ContentChild,TemplateRef,OnInit,OnChanges,OnDestroy,AfterContentInit,QueryList,SimpleChanges,EmbeddedViewRef} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {Component} from '@angular/core'; - -@Component({ - selector: 'p-header', - template: '' -}) -export class Header {} - -@Component({ - selector: 'p-footer', - template: '' -}) -export class Footer {} - -@Directive({ - selector: '[pTemplate]', - host: { - } -}) -export class PrimeTemplate { - - @Input() type: string; - - @Input('pTemplate') name: string; - - constructor(public template: TemplateRef) {} - - getType(): string { - return this.name; - } -} - -/* Deprecated */ -@Component({ - selector: 'p-column', - template: '' -}) -export class Column implements AfterContentInit{ - @Input() field: string; - @Input() colId: string; - @Input() sortField: string; - @Input() filterField: string; - @Input() header: string; - @Input() footer: string; - @Input() sortable: any; - @Input() editable: boolean; - @Input() filter: boolean; - @Input() filterMatchMode: string; - @Input() filterType: string = 'text'; - @Input() excludeGlobalFilter: boolean; - @Input() rowspan: number; - @Input() colspan: number; - @Input() scope: string; - @Input() style: any; - @Input() styleClass: string; - @Input() exportable: boolean = true; - @Input() headerStyle: any; - @Input() headerStyleClass: string; - @Input() bodyStyle: any; - @Input() bodyStyleClass: string; - @Input() footerStyle: any; - @Input() footerStyleClass: string; - @Input() hidden: boolean; - @Input() expander: boolean; - @Input() selectionMode: string; - @Input() filterPlaceholder: string; - @Input() filterMaxlength: number; - @Input() frozen: boolean; - @Input() resizable: boolean = true; - @Output() sortFunction: EventEmitter = new EventEmitter(); - @ContentChildren(PrimeTemplate) templates: QueryList; - @ContentChild(TemplateRef) template: TemplateRef; - - public headerTemplate: TemplateRef; - public bodyTemplate: TemplateRef; - public footerTemplate: TemplateRef; - public filterTemplate: TemplateRef; - public editorTemplate: TemplateRef; - - ngAfterContentInit():void { - this.templates.forEach((item) => { - switch(item.getType()) { - case 'header': - this.headerTemplate = item.template; - break; - - case 'body': - this.bodyTemplate = item.template; - break; - - case 'footer': - this.footerTemplate = item.template; - break; - - case 'filter': - this.filterTemplate = item.template; - break; - - case 'editor': - this.editorTemplate = item.template; - break; - - default: - this.bodyTemplate = item.template; - break; - } - }); - } -} - -/* Deprecated */ -@Component({ - selector: 'p-row', - template: `` -}) -export class Row { - - @ContentChildren(Column) columns: QueryList; - -} - -/* Deprecated */ -@Component({ - selector: 'p-headerColumnGroup', - template: `` -}) -export class HeaderColumnGroup { - - @Input() frozen: boolean; - - @ContentChildren(Row) rows: QueryList; -} - -/* Deprecated */ -@Component({ - selector: 'p-footerColumnGroup', - template: `` -}) -export class FooterColumnGroup { - - @Input() frozen: boolean; - - @ContentChildren(Row) rows: QueryList; -} - -@NgModule({ - imports: [CommonModule], - exports: [Header,Footer,Column,PrimeTemplate,Row,HeaderColumnGroup,FooterColumnGroup], - declarations: [Header,Footer,Column,PrimeTemplate,Row,HeaderColumnGroup,FooterColumnGroup] -}) -export class SharedModule { } diff --git a/dashboard/src/app/components/common/sortevent.ts b/dashboard/src/app/components/common/sortevent.ts deleted file mode 100644 index 5064eedb8..000000000 --- a/dashboard/src/app/components/common/sortevent.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { SortMeta } from './sortmeta'; - -export interface SortEvent { - data?: any[]; - mode?: string; - field?: string; - order?: number; - multiSortMeta?: SortMeta[]; -} \ No newline at end of file diff --git a/dashboard/src/app/components/common/sortmeta.ts b/dashboard/src/app/components/common/sortmeta.ts deleted file mode 100644 index 7b2c7e22f..000000000 --- a/dashboard/src/app/components/common/sortmeta.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface SortMeta { - field: string; - order: number; -} \ No newline at end of file diff --git a/dashboard/src/app/components/common/treedragdropservice.ts b/dashboard/src/app/components/common/treedragdropservice.ts deleted file mode 100644 index d19bf4a80..000000000 --- a/dashboard/src/app/components/common/treedragdropservice.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Subject } from 'rxjs/Subject'; -import { Observable } from 'rxjs/Observable'; -import { TreeNode } from './treenode'; -import { TreeNodeDragEvent } from './treenodedragevent'; - -@Injectable() -export class TreeDragDropService { - - private dragStartSource = new Subject(); - private dragStopSource = new Subject(); - - dragStart$ = this.dragStartSource.asObservable(); - dragStop$ = this.dragStopSource.asObservable(); - - startDrag(event: TreeNodeDragEvent) { - this.dragStartSource.next(event); - } - - stopDrag(event: TreeNodeDragEvent) { - this.dragStopSource.next(event); - } -} \ No newline at end of file diff --git a/dashboard/src/app/components/common/treenode.ts b/dashboard/src/app/components/common/treenode.ts deleted file mode 100644 index 42016563c..000000000 --- a/dashboard/src/app/components/common/treenode.ts +++ /dev/null @@ -1,17 +0,0 @@ -export interface TreeNode { - label?: string; - data?: any; - icon?: any; - expandedIcon?: any; - collapsedIcon?: any; - children?: TreeNode[]; - leaf?: boolean; - expanded?: boolean; - type?: string; - parent?: TreeNode; - partialSelected?: boolean; - styleClass?: string; - draggable?: boolean; - droppable?: boolean; - selectable?: boolean; -} \ No newline at end of file diff --git a/dashboard/src/app/components/common/treenodedragevent.ts b/dashboard/src/app/components/common/treenodedragevent.ts deleted file mode 100644 index 0509cfa3b..000000000 --- a/dashboard/src/app/components/common/treenodedragevent.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { TreeNode } from './treenode'; - -export interface TreeNodeDragEvent { - tree?: any; - node?: TreeNode; - subNodes?: TreeNode[]; - index?: number; - scope?: any; -} \ No newline at end of file diff --git a/dashboard/src/app/components/confirmdialog/confirmdialog.spec.ts b/dashboard/src/app/components/confirmdialog/confirmdialog.spec.ts deleted file mode 100644 index 76dea012e..000000000 --- a/dashboard/src/app/components/confirmdialog/confirmdialog.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { ConfirmDialog } from './confirmdialog'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('ConfirmDialog', () => { - - let confirmdialog: ConfirmDialog; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - ConfirmDialog - ] - }); - - fixture = TestBed.createComponent(ConfirmDialog); - confirmdialog = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/confirmdialog/confirmdialog.ts b/dashboard/src/app/components/confirmdialog/confirmdialog.ts deleted file mode 100644 index e497c29bd..000000000 --- a/dashboard/src/app/components/confirmdialog/confirmdialog.ts +++ /dev/null @@ -1,314 +0,0 @@ -import {NgModule,Component,ElementRef,AfterViewInit,OnDestroy,Input,Output,AfterViewChecked,EventEmitter,Renderer2,ContentChild,NgZone} from '@angular/core'; -import {trigger,state,style,transition,animate} from '@angular/animations'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; -import {Header,Footer,SharedModule} from '../common/shared'; -import {ButtonModule} from '../button/button'; -import {Confirmation} from '../common/confirmation'; -import {ConfirmationService} from '../common/confirmationservice'; -import {Subscription} from 'rxjs/Subscription'; - -@Component({ - selector: 'p-confirmDialog', - template: ` -
-
- {{header}} - - - -
-
- -
-
- - -
- `, - animations: [ - trigger('dialogState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]) - ], - providers: [DomHandler] -}) -export class ConfirmDialog implements AfterViewInit,AfterViewChecked,OnDestroy { - - @Input() header: string; - - @Input() isWarning: boolean = false; - - @Input() icon: string = 'fa'; - - @Input() message: string; - - @Input() acceptIcon: string; - - @Input() acceptLabel: string = 'Confirm'; - - @Input() acceptVisible: boolean = true; - - @Input() rejectIcon: string; - - @Input() rejectLabel: string = 'Cancel'; - - @Input() rejectVisible: boolean = true; - - @Input() acceptButtonStyleClass: string; - - @Input() rejectButtonStyleClass: string; - - @Input() width: any; - - @Input() height: any; - - @Input() closeOnEscape: boolean = true; - - @Input() rtl: boolean; - - @Input() closable: boolean = true; - - @Input() responsive: boolean = true; - - @Input() appendTo: any; - - @Input() key: string; - - @ContentChild(Footer) footer; - - confirmation: Confirmation; - - _visible: boolean; - - documentEscapeListener: any; - - documentResponsiveListener: any; - - mask: any; - - contentContainer: any; - - positionInitialized: boolean; - - subscription: Subscription; - - executePostShowActions: boolean; - - constructor(public el: ElementRef, public domHandler: DomHandler, - public renderer: Renderer2, private confirmationService: ConfirmationService, public zone: NgZone) { - this.subscription = confirmationService.requireConfirmation$.subscribe(confirmation => { - if(confirmation.key === this.key) { - this.confirmation = confirmation; - this.message = this.confirmation.message||this.message; - this.icon = this.confirmation.icon||this.icon; - this.isWarning = this.confirmation.isWarning||this.isWarning; - this.acceptLabel = this.confirmation.acceptLabel||this.acceptLabel; - this.rejectLabel = this.confirmation.rejectLabel||this.rejectLabel; - this.header = this.confirmation.header||this.header; - this.rejectVisible = this.confirmation.rejectVisible == null ? this.rejectVisible : this.confirmation.rejectVisible; - this.acceptVisible = this.confirmation.acceptVisible == null ? this.acceptVisible : this.confirmation.acceptVisible; - - if(this.confirmation.accept) { - this.confirmation.acceptEvent = new EventEmitter(); - this.confirmation.acceptEvent.subscribe(this.confirmation.accept); - } - - if(this.confirmation.reject) { - this.confirmation.rejectEvent = new EventEmitter(); - this.confirmation.rejectEvent.subscribe(this.confirmation.reject); - } - - this.visible = true; - } - }); - } - - @Input() get visible(): boolean { - return this._visible; - } - - set visible(val:boolean) { - this._visible = val; - - if(this._visible) { - if(!this.positionInitialized) { - this.center(); - this.positionInitialized = true; - } - - this.el.nativeElement.children[0].style.zIndex = ++DomHandler.zindex; - this.bindGlobalListeners(); - this.executePostShowActions = true; - } - - if(this._visible) - this.enableModality(); - else - this.disableModality(); - } - - ngAfterViewInit() { - this.contentContainer = this.domHandler.findSingle(this.el.nativeElement, '.ui-dialog-content'); - - if(this.appendTo) { - if(this.appendTo === 'body') - document.body.appendChild(this.el.nativeElement); - else - this.domHandler.appendChild(this.el.nativeElement, this.appendTo); - } - } - - ngAfterViewChecked() { - if(this.executePostShowActions) { - this.domHandler.findSingle(this.el.nativeElement.children[0], 'button').focus(); - this.executePostShowActions = false; - } - } - - center() { - let container = this.el.nativeElement.children[0]; - let elementWidth = this.domHandler.getOuterWidth(container); - let elementHeight = this.domHandler.getOuterHeight(container); - if(elementWidth == 0 && elementHeight == 0) { - container.style.visibility = 'hidden'; - container.style.display = 'block'; - elementWidth = this.domHandler.getOuterWidth(container); - elementHeight = this.domHandler.getOuterHeight(container); - container.style.display = 'none'; - container.style.visibility = 'visible'; - } - let viewport = this.domHandler.getViewport(); - let x = (viewport.width - elementWidth) / 2; - let y = (viewport.height - elementHeight) / 2; - - container.style.left = x + 'px'; - container.style.top = y + 'px'; - } - - enableModality() { - if(!this.mask) { - this.mask = document.createElement('div'); - this.mask.style.zIndex = this.el.nativeElement.children[0].style.zIndex - 1; - this.domHandler.addMultipleClasses(this.mask, 'ui-widget-overlay ui-dialog-mask'); - document.body.appendChild(this.mask); - this.domHandler.addClass(document.body, 'ui-overflow-hidden'); - } - } - - disableModality() { - if(this.mask) { - document.body.removeChild(this.mask); - this.domHandler.removeClass(document.body, 'ui-overflow-hidden'); - this.mask = null; - } - } - - close(event: Event) { - if(this.confirmation.rejectEvent) { - this.confirmation.rejectEvent.emit(); - } - - this.hide(); - this.isWarning = false; - event.preventDefault(); - } - - hide() { - this.visible = false; - this.unbindGlobalListeners(); - } - - moveOnTop() { - this.el.nativeElement.children[0].style.zIndex = ++DomHandler.zindex; - } - - bindGlobalListeners() { - if(this.closeOnEscape && this.closable && !this.documentEscapeListener) { - this.documentEscapeListener = this.renderer.listen('document', 'keydown', (event) => { - if(event.which == 27) { - if(this.el.nativeElement.children[0].style.zIndex == DomHandler.zindex && this.visible) { - this.close(event); - } - } - }); - } - - if(this.responsive) { - this.zone.runOutsideAngular(() => { - this.documentResponsiveListener = this.center.bind(this); - window.addEventListener('resize', this.documentResponsiveListener); - }); - } - } - - unbindGlobalListeners() { - if(this.documentEscapeListener) { - this.documentEscapeListener(); - this.documentEscapeListener = null; - } - - if(this.documentResponsiveListener) { - window.removeEventListener('resize', this.documentResponsiveListener); - this.documentResponsiveListener = null; - } - } - - ngOnDestroy() { - this.disableModality(); - - if(this.documentResponsiveListener) { - this.documentResponsiveListener(); - } - - if(this.documentEscapeListener) { - this.documentEscapeListener(); - } - - if(this.appendTo && this.appendTo === 'body') { - document.body.removeChild(this.el.nativeElement); - } - - this.subscription.unsubscribe(); - } - - accept() { - if(this.confirmation.acceptEvent) { - this.confirmation.acceptEvent.emit(); - } - - this.hide(); - this.isWarning = false; - this.confirmation = null; - } - - reject() { - if(this.confirmation.rejectEvent) { - this.confirmation.rejectEvent.emit(); - } - - this.hide(); - this.isWarning = false; - this.confirmation = null; - } -} - -@NgModule({ - imports: [CommonModule,ButtonModule], - exports: [ConfirmDialog,ButtonModule,SharedModule], - declarations: [ConfirmDialog] -}) -export class ConfirmDialogModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/contextmenu/contextmenu.css b/dashboard/src/app/components/contextmenu/contextmenu.css deleted file mode 100644 index 67ca57665..000000000 --- a/dashboard/src/app/components/contextmenu/contextmenu.css +++ /dev/null @@ -1,44 +0,0 @@ -.ui-contextmenu { - width: 12.5em; - padding: .25em; - position: absolute; - display: none; -} - -.ui-contextmenu .ui-menu-separator { - border-width: 1px 0 0 0; -} - -.ui-contextmenu ul { - list-style: none; - margin: 0; - padding: 0; -} - -.ui-contextmenu .ui-submenu-list { - display: none; - position: absolute; - width: 12.5em; - padding: .25em; -} - -.ui-contextmenu .ui-menuitem-link { - padding: .25em; - display: block; - position: relative; -} - -.ui-contextmenu .ui-menuitem { - position: relative; -} - -.ui-contextmenu .ui-menuitem-link .ui-submenu-icon { - position: absolute; - margin-top: -.5em; - right: 0; - top: 50%; -} - -.ui-contextmenu .ui-menuitem-active > .ui-submenu > .ui-submenu-list { - display: block !important; -} \ No newline at end of file diff --git a/dashboard/src/app/components/contextmenu/contextmenu.spec.ts b/dashboard/src/app/components/contextmenu/contextmenu.spec.ts deleted file mode 100644 index f2cccb76e..000000000 --- a/dashboard/src/app/components/contextmenu/contextmenu.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { ContextMenu } from './contextmenu'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Accordion', () => { - - let contextmenu: ContextMenu; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - ContextMenu - ] - }); - - fixture = TestBed.createComponent(ContextMenu); - contextmenu = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/contextmenu/contextmenu.ts b/dashboard/src/app/components/contextmenu/contextmenu.ts deleted file mode 100644 index dfbc0024f..000000000 --- a/dashboard/src/app/components/contextmenu/contextmenu.ts +++ /dev/null @@ -1,284 +0,0 @@ -import {NgModule,Component,ElementRef,AfterViewInit,OnDestroy,Input,Output,Renderer2,Inject,forwardRef,ViewChild} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; -import {MenuItem} from '../common/menuitem'; -import {Location} from '@angular/common'; -import {RouterModule} from '@angular/router'; - -@Component({ - selector: 'p-contextMenuSub', - template: ` - - `, - providers: [DomHandler] -}) -export class ContextMenuSub { - - @Input() item: MenuItem; - - @Input() root: boolean; - - constructor(public domHandler: DomHandler, @Inject(forwardRef(() => ContextMenu)) public contextMenu: ContextMenu) {} - - activeItem: any; - - containerLeft: any; - - hideTimeout: any; - - onItemMouseEnter(event, item, menuitem) { - if(menuitem.disabled) { - return; - } - - if(this.hideTimeout) { - clearTimeout(this.hideTimeout); - this.hideTimeout = null; - } - - this.activeItem = item; - let nextElement = item.children[0].nextElementSibling; - if(nextElement) { - let sublist = nextElement.children[0]; - sublist.style.zIndex = ++DomHandler.zindex; - this.position(sublist, item); - } - } - - onItemMouseLeave(event, link) { - this.hideTimeout = setTimeout(() => { - this.activeItem = null; - }, 1000); - } - - itemClick(event, item: MenuItem) { - if(item.disabled) { - event.preventDefault(); - return; - } - - if(!item.url) { - event.preventDefault(); - } - - if(item.command) { - item.command({ - originalEvent: event, - item: item - }); - } - } - - listClick(event) { - this.activeItem = null; - } - - position(sublist, item) { - this.containerLeft = this.domHandler.getOffset(item.parentElement) - let viewport = this.domHandler.getViewport(); - let sublistWidth = sublist.offsetParent ? sublist.offsetWidth: this.domHandler.getHiddenElementOuterWidth(sublist); - let itemOuterWidth = this.domHandler.getOuterWidth(item.children[0]); - - sublist.style.top = '0px'; - - if((parseInt(this.containerLeft.left) + itemOuterWidth + sublistWidth) > (viewport.width - this.calculateScrollbarWidth())) { - sublist.style.left = -sublistWidth + 'px'; - } - else { - sublist.style.left = itemOuterWidth + 'px'; - } - } - - calculateScrollbarWidth(): number { - let scrollDiv = document.createElement("div"); - scrollDiv.className = "ui-scrollbar-measure"; - document.body.appendChild(scrollDiv); - - let scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; - document.body.removeChild(scrollDiv); - - return scrollbarWidth; - } -} - -@Component({ - selector: 'p-contextMenu', - template: ` -
- -
- `, - providers: [DomHandler] -}) -export class ContextMenu implements AfterViewInit,OnDestroy { - - @Input() model: MenuItem[]; - - @Input() global: boolean; - - @Input() target: any; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() appendTo: any; - - @Input() autoZIndex: boolean = true; - - @Input() baseZIndex: number = 0; - - @ViewChild('container') containerViewChild: ElementRef; - - documentClickListener: any; - - rightClickListener: any; - - constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2) {} - - ngAfterViewInit() { - if(this.global) { - this.rightClickListener = this.renderer.listen('document', 'contextmenu', (event) => { - this.show(event); - event.preventDefault(); - }); - } - else if(this.target) { - this.rightClickListener = this.renderer.listen(this.target, 'contextmenu', (event) => { - this.show(event); - event.preventDefault(); - event.stopPropagation(); - }); - } - - if(this.appendTo) { - if(this.appendTo === 'body') - document.body.appendChild( this.containerViewChild.nativeElement); - else - this.domHandler.appendChild(this.containerViewChild.nativeElement, this.appendTo); - } - } - - show(event?: MouseEvent) { - this.position(event); - this.moveOnTop(); - this.containerViewChild.nativeElement.style.display = 'block'; - this.domHandler.fadeIn(this.containerViewChild.nativeElement, 250); - this.bindDocumentClickListener(); - - if(event) { - event.preventDefault(); - } - } - - hide() { - this.containerViewChild.nativeElement.style.display = 'none'; - this.unbindDocumentClickListener(); - } - - moveOnTop() { - if(this.autoZIndex) { - this.containerViewChild.nativeElement.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex)); - } - } - - toggle(event?: MouseEvent) { - if(this.containerViewChild.nativeElement.offsetParent) - this.hide(); - else - this.show(event); - } - - position(event?: MouseEvent) { - if(event) { - let left = event.pageX + 1; - let top = event.pageY + 1; - let width = this.containerViewChild.nativeElement.offsetParent ? this.containerViewChild.nativeElement.offsetWidth: this.domHandler.getHiddenElementOuterWidth(this.containerViewChild.nativeElement); - let height = this.containerViewChild.nativeElement.offsetParent ? this.containerViewChild.nativeElement.offsetHeight: this.domHandler.getHiddenElementOuterHeight(this.containerViewChild.nativeElement); - let viewport = this.domHandler.getViewport(); - - //flip - if(left + width - document.body.scrollLeft > viewport.width) { - left -= width; - } - - //flip - if(top + height - document.body.scrollTop > viewport.height) { - top -= height; - } - - //fit - if(left < document.body.scrollLeft) { - left = document.body.scrollLeft; - } - - //fit - if(top < document.body.scrollTop) { - top = document.body.scrollTop; - } - - this.containerViewChild.nativeElement.style.left = left + 'px'; - this.containerViewChild.nativeElement.style.top = top + 'px'; - } - } - - bindDocumentClickListener() { - if(!this.documentClickListener) { - this.documentClickListener = this.renderer.listen('document', 'click', (event) => { - if (this.containerViewChild.nativeElement.offsetParent && event.button !== 2) { - this.hide(); - } - }); - } - } - - unbindDocumentClickListener() { - if(this.documentClickListener) { - this.documentClickListener(); - this.documentClickListener = null; - } - } - - ngOnDestroy() { - this.unbindDocumentClickListener(); - - if(this.rightClickListener) { - this.rightClickListener(); - } - - if(this.appendTo) { - this.el.nativeElement.appendChild(this.containerViewChild.nativeElement); - } - } - -} - -@NgModule({ - imports: [CommonModule,RouterModule], - exports: [ContextMenu,RouterModule], - declarations: [ContextMenu,ContextMenuSub] -}) -export class ContextMenuModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/datagrid/datagrid.css b/dashboard/src/app/components/datagrid/datagrid.css deleted file mode 100644 index 99cc3d41b..000000000 --- a/dashboard/src/app/components/datagrid/datagrid.css +++ /dev/null @@ -1,34 +0,0 @@ -.ui-datagrid .ui-paginator { - text-align: center; -} - -.ui-datagrid-column { - padding: .25em; -} - -.ui-datagrid-content-empty { - padding: .25em .625em; -} - -.ui-datagrid .ui-datagrid-header, -.ui-datagrid .ui-datagrid-footer { - text-align:center; - padding: .5em .75em; -} - -.ui-datagrid .ui-datagrid-header { - border-bottom: 0 none; -} - -.ui-datagrid .ui-datagrid-footer { - border-top: 0 none; -} - -.ui-datagrid .ui-paginator-top { - border-bottom: 0 none; -} - -.ui-datagrid .ui-paginator-bottom { - border-top: 0 none; -} - diff --git a/dashboard/src/app/components/datagrid/datagrid.spec.ts b/dashboard/src/app/components/datagrid/datagrid.spec.ts deleted file mode 100644 index 26fef3ec4..000000000 --- a/dashboard/src/app/components/datagrid/datagrid.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { DataGrid } from './datagrid'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('DataGrid', () => { - - let datagrid: DataGrid; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - DataGrid - ] - }); - - fixture = TestBed.createComponent(DataGrid); - datagrid = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/datagrid/datagrid.ts b/dashboard/src/app/components/datagrid/datagrid.ts deleted file mode 100644 index ab4da1b09..000000000 --- a/dashboard/src/app/components/datagrid/datagrid.ts +++ /dev/null @@ -1,205 +0,0 @@ -import {NgModule,Component,ElementRef,AfterViewInit,AfterContentInit,DoCheck,OnDestroy,Input,Output,SimpleChange,EventEmitter,ContentChild,ContentChildren,QueryList,TemplateRef,IterableDiffers} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {Header,Footer,PrimeTemplate,SharedModule} from '../common/shared'; -import {PaginatorModule} from '../paginator/paginator'; -import {BlockableUI} from '../common/blockableui'; - -@Component({ - selector: 'p-dataGrid', - template: ` -
-
- -
- -
-
- -
{{emptyMessage}}
-
-
- - -
- ` -}) -export class DataGrid implements AfterViewInit,AfterContentInit,DoCheck,BlockableUI { - - @Input() paginator: boolean; - - @Input() rows: number; - - @Input() totalRecords: number; - - @Input() pageLinks: number = 5; - - @Input() rowsPerPageOptions: number[]; - - @Input() lazy: boolean; - - @Input() emptyMessage: string = 'No records found'; - - @Output() onLazyLoad: EventEmitter = new EventEmitter(); - - @Input() style: any; - - @Input() styleClass: string; - - @Input() paginatorPosition: string = 'bottom'; - - @Input() alwaysShowPaginator: boolean = true; - - @Input() trackBy: Function = (index: number, item: any) => item; - - @Input() immutable: boolean = true; - - @Input() paginatorDropdownAppendTo: any; - - @Output() onPage: EventEmitter = new EventEmitter(); - - @ContentChild(Header) header; - - @ContentChild(Footer) footer; - - @ContentChildren(PrimeTemplate) templates: QueryList; - - _value: any[]; - - itemTemplate: TemplateRef; - - dataToRender: any[]; - - first: number = 0; - - page: number = 0; - - differ: any; - - constructor(public el: ElementRef, public differs: IterableDiffers) { - this.differ = differs.find([]).create(null); - } - - ngAfterViewInit() { - if(this.lazy) { - this.onLazyLoad.emit({ - first: this.first, - rows: this.rows - }); - } - } - - ngAfterContentInit() { - this.templates.forEach((item) => { - switch(item.getType()) { - case 'item': - this.itemTemplate = item.template; - break; - - default: - this.itemTemplate = item.template; - break; - } - }); - } - - @Input() get value(): any[] { - return this._value; - } - - set value(val:any[]) { - this._value = val; - - if(this.immutable) { - this.handleDataChange(); - } - } - - handleDataChange() { - if(this.paginator) { - this.updatePaginator(); - } - this.updateDataToRender(this.value); - } - - ngDoCheck() { - if(!this.immutable) { - let changes = this.differ.diff(this.value); - if(changes) { - this.handleDataChange(); - } - } - } - - updatePaginator() { - //total records - this.totalRecords = this.lazy ? this.totalRecords : (this.value ? this.value.length: 0); - - //first - if(this.totalRecords && this.first >= this.totalRecords) { - let numberOfPages = Math.ceil(this.totalRecords/this.rows); - this.first = Math.max((numberOfPages-1) * this.rows, 0); - } - } - - paginate(event) { - this.first = event.first; - this.rows = event.rows; - - if(this.lazy) { - this.onLazyLoad.emit(this.createLazyLoadMetadata()); - } - else { - this.updateDataToRender(this.value); - } - - this.onPage.emit({ - first: this.first, - rows: this.rows - }); - } - - updateDataToRender(datasource) { - if(this.paginator && datasource) { - this.dataToRender = []; - let startIndex = this.lazy ? 0 : this.first; - for(let i = startIndex; i < (startIndex+ this.rows); i++) { - if(i >= datasource.length) { - break; - } - - this.dataToRender.push(datasource[i]); - } - } - else { - this.dataToRender = datasource; - } - } - - isEmpty() { - return !this.dataToRender||(this.dataToRender.length == 0); - } - - createLazyLoadMetadata(): any { - return { - first: this.first, - rows: this.rows - }; - } - - getBlockableElement(): HTMLElement { - return this.el.nativeElement.children[0]; - } -} - -@NgModule({ - imports: [CommonModule,SharedModule,PaginatorModule], - exports: [DataGrid,SharedModule], - declarations: [DataGrid] -}) -export class DataGridModule { } diff --git a/dashboard/src/app/components/datalist/datalist.css b/dashboard/src/app/components/datalist/datalist.css deleted file mode 100644 index f24cdcab3..000000000 --- a/dashboard/src/app/components/datalist/datalist.css +++ /dev/null @@ -1,39 +0,0 @@ -.ui-datalist .ui-datalist-header, -.ui-datalist .ui-datalist-footer { - text-align:center; - padding: .5em .75em; -} - -.ui-datalist .ui-datalist-header { - border-bottom: 0 none; -} - -.ui-datalist .ui-datalist-footer { - border-top: 0 none; -} - -.ui-datalist .ui-datalist-data { - margin: 0; - padding: 0; -} - -.ui-datalist .ui-datalist-data > li { - list-style-type: none; - -} - -.ui-datalist .ui-datalist-emptymessage { - padding: .5em .75em; -} - -.ui-datalist.ui-datalist-scrollable .ui-datalist-content { - overflow: auto; -} - -.ui-datalist .ui-paginator-top { - border-bottom: 0 none; -} - -.ui-datalist .ui-paginator-bottom { - border-top: 0 none; -} diff --git a/dashboard/src/app/components/datalist/datalist.spec.ts b/dashboard/src/app/components/datalist/datalist.spec.ts deleted file mode 100644 index 00968f70c..000000000 --- a/dashboard/src/app/components/datalist/datalist.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { DataList } from './datalist'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('DataList', () => { - - let datalist: DataList; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - DataList - ] - }); - - fixture = TestBed.createComponent(DataList); - datalist = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/datalist/datalist.ts b/dashboard/src/app/components/datalist/datalist.ts deleted file mode 100644 index 2512372b1..000000000 --- a/dashboard/src/app/components/datalist/datalist.ts +++ /dev/null @@ -1,211 +0,0 @@ -import {NgModule,Component,ElementRef,AfterViewInit,AfterContentInit,DoCheck,OnDestroy,Input,Output,SimpleChange,EventEmitter,ContentChild,ContentChildren,TemplateRef,QueryList,IterableDiffers} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {SharedModule,Header,Footer,PrimeTemplate} from '../common/shared'; -import {PaginatorModule} from '../paginator/paginator'; -import {BlockableUI} from '../common/blockableui'; - -@Component({ - selector: 'p-dataList', - template: ` -
-
- -
- -
-
{{emptyMessage}}
-
    -
  • - -
  • -
-
- - -
- ` -}) -export class DataList implements AfterViewInit,AfterContentInit,DoCheck,BlockableUI { - - @Input() paginator: boolean; - - @Input() rows: number; - - @Input() totalRecords: number; - - @Input() pageLinks: number = 5; - - @Input() rowsPerPageOptions: number[]; - - @Input() lazy: boolean; - - @Output() onLazyLoad: EventEmitter = new EventEmitter(); - - @Input() style: any; - - @Input() styleClass: string; - - @Input() paginatorPosition: string = 'bottom'; - - @Input() emptyMessage: string = 'No records found'; - - @Input() alwaysShowPaginator: boolean = true; - - @Input() trackBy: Function = (index: number, item: any) => item; - - @Input() immutable: boolean = true; - - @Input() scrollable: boolean; - - @Input() scrollHeight: string; - - @Input() paginatorDropdownAppendTo: any; - - @Output() onPage: EventEmitter = new EventEmitter(); - - @ContentChild(Header) header; - - @ContentChild(Footer) footer; - - @ContentChildren(PrimeTemplate) templates: QueryList; - - public _value: any[]; - - public itemTemplate: TemplateRef; - - public dataToRender: any[]; - - public first: number = 0; - - public page: number = 0; - - differ: any; - - constructor(public el: ElementRef, public differs: IterableDiffers) { - this.differ = differs.find([]).create(null); - } - - ngAfterContentInit() { - this.templates.forEach((item) => { - switch(item.getType()) { - case 'item': - this.itemTemplate = item.template; - break; - - default: - this.itemTemplate = item.template; - break; - } - }); - } - - ngAfterViewInit() { - if(this.lazy) { - this.onLazyLoad.emit({ - first: this.first, - rows: this.rows - }); - } - } - - @Input() get value(): any[] { - return this._value; - } - - set value(val:any[]) { - this._value = val; - - if(this.immutable) { - this.handleDataChange(); - } - } - - handleDataChange() { - if(this.paginator) { - this.updatePaginator(); - } - this.updateDataToRender(this.value); - } - - ngDoCheck() { - if(!this.immutable) { - let changes = this.differ.diff(this.value); - if(changes) { - this.handleDataChange(); - } - } - } - - updatePaginator() { - //total records - this.totalRecords = this.lazy ? this.totalRecords : (this.value ? this.value.length: 0); - - //first - if(this.totalRecords && this.first >= this.totalRecords) { - let numberOfPages = Math.ceil(this.totalRecords/this.rows); - this.first = Math.max((numberOfPages-1) * this.rows, 0); - } - } - - paginate(event) { - this.first = event.first; - this.rows = event.rows; - - if(this.lazy) { - this.onLazyLoad.emit(this.createLazyLoadMetadata()); - } - else { - this.updateDataToRender(this.value); - } - - this.onPage.emit({ - first: this.first, - rows: this.rows - }); - } - - updateDataToRender(datasource) { - if(this.paginator && datasource) { - this.dataToRender = []; - let startIndex = this.lazy ? 0 : this.first; - for(let i = startIndex; i < (startIndex+ this.rows); i++) { - if(i >= datasource.length) { - break; - } - - this.dataToRender.push(datasource[i]); - } - } - else { - this.dataToRender = datasource; - } - } - - isEmpty() { - return !this.dataToRender||(this.dataToRender.length == 0); - } - - createLazyLoadMetadata(): any { - return { - first: this.first, - rows: this.rows - }; - } - - getBlockableElement(): HTMLElement { - return this.el.nativeElement.children[0]; - } -} - -@NgModule({ - imports: [CommonModule,PaginatorModule], - exports: [DataList,SharedModule], - declarations: [DataList] -}) -export class DataListModule { } diff --git a/dashboard/src/app/components/datascroller/datascroller.css b/dashboard/src/app/components/datascroller/datascroller.css deleted file mode 100644 index eefe766a8..000000000 --- a/dashboard/src/app/components/datascroller/datascroller.css +++ /dev/null @@ -1,28 +0,0 @@ -.ui-datascroller { -} - -.ui-datascroller .ui-datascroller-header { - text-align: center; - padding: .5em .75em; - border-bottom: 0 none; -} - -.ui-datascroller .ui-datascroller-footer { - text-align: center; - padding: .25em .625em; - border-top: 0px none; -} - -.ui-datascroller .ui-datascroller-content { - padding: .25em .625em; -} - -.ui-datascroller-inline .ui-datascroller-content { - overflow: auto; -} - -.ui-datascroller .ui-datascroller-list { - list-style-type: none; - margin: 0; - padding: 0; -} \ No newline at end of file diff --git a/dashboard/src/app/components/datascroller/datascroller.spec.ts b/dashboard/src/app/components/datascroller/datascroller.spec.ts deleted file mode 100644 index 90ef8659a..000000000 --- a/dashboard/src/app/components/datascroller/datascroller.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { DataScroller } from './datascroller'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('DataScroller', () => { - - let datascroller: DataScroller; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - DataScroller - ] - }); - - fixture = TestBed.createComponent(DataScroller); - datascroller = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/datascroller/datascroller.ts b/dashboard/src/app/components/datascroller/datascroller.ts deleted file mode 100644 index b1efd109f..000000000 --- a/dashboard/src/app/components/datascroller/datascroller.ts +++ /dev/null @@ -1,203 +0,0 @@ -import {NgModule,Component,ElementRef,OnInit,AfterViewInit,AfterContentInit,DoCheck,OnDestroy,Input,Output,Renderer2,NgZone,ViewChild,EventEmitter,ContentChild,ContentChildren,QueryList,TemplateRef} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {Header,Footer,PrimeTemplate,SharedModule} from '../common/shared'; -import {DomHandler} from '../dom/domhandler'; - -@Component({ - selector: 'p-dataScroller', - template:` -
-
- -
-
-
    -
  • - -
  • -
-
- -
- `, - providers: [DomHandler] -}) -export class DataScroller implements OnInit,AfterViewInit,OnDestroy { - - @Input() value: any[]; - - @Input() rows: number; - - @Input() lazy: boolean; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() buffer: number = 0.9; - - @Input() inline: boolean; - - @Input() scrollHeight: any; - - @Input() loader: any; - - @Input() totalRecords: number; - - @Input() trackBy: Function = (index: number, item: any) => item; - - @ContentChild(Header) header; - - @ContentChild(Footer) footer; - - @ContentChildren(PrimeTemplate) templates: QueryList; - - @ViewChild('content') contentViewChild: ElementRef; - - @Output() onLazyLoad: EventEmitter = new EventEmitter(); - - itemTemplate: TemplateRef; - - dataToRender: any[] = []; - - first: number = 0; - - contentElement: HTMLDivElement; - - inlineScrollListener: any; - - windowScrollListener: any; - - loaderClickListener: any; - - page: number = 0; - - constructor(public el: ElementRef, public renderer: Renderer2, public domHandler: DomHandler, public zone: NgZone) {} - - ngOnInit() { - this.load(); - } - - ngAfterViewInit() { - if(this.loader) { - this.loaderClickListener = this.renderer.listen(this.loader, 'click', () => { - this.load(); - }); - } - else { - this.bindScrollListener(); - } - } - - ngAfterContentInit() { - this.templates.forEach((item) => { - switch(item.getType()) { - case 'item': - this.itemTemplate = item.template; - break; - - default: - this.itemTemplate = item.template; - break; - } - }); - } - - load() { - if(this.lazy) { - this.onLazyLoad.emit({ - first: this.page * this.rows, - rows: this.rows - }); - } - - this.page = this.page + 1; - } - - shouldLoad() { - if(this.lazy) - return (this.rows * this.page < this.totalRecords); - else - return this.value && this.value.length && (this.rows * this.page < this.value.length); - } - - reset() { - this.page = 0; - } - - isEmpty() { - return !this.value||(this.value.length == 0); - } - - bindScrollListener() { - this.zone.runOutsideAngular(() => { - if(this.inline) { - this.inlineScrollListener = this.onInlineScroll.bind(this); - this.contentViewChild.nativeElement.addEventListener('scroll', this.inlineScrollListener); - } - else { - this.windowScrollListener = this.onWindowScroll.bind(this); - window.addEventListener('scroll', this.windowScrollListener); - } - }); - } - - unbindScrollListener() { - if(this.inlineScrollListener) { - this.contentViewChild.nativeElement.removeEventListener('scroll', this.inlineScrollListener); - } - - if(this.windowScrollListener) { - window.removeEventListener('scroll', this.windowScrollListener); - } - - if(this.loaderClickListener) { - this.loaderClickListener(); - this.loaderClickListener = null; - } - } - - onInlineScroll() { - let scrollTop = this.contentViewChild.nativeElement.scrollTop; - let scrollHeight = this.contentViewChild.nativeElement.scrollHeight; - let viewportHeight = this.contentViewChild.nativeElement.clientHeight; - - if((scrollTop >= ((scrollHeight * this.buffer) - (viewportHeight)))) { - if(this.shouldLoad()) { - this.zone.run(() => { - this.load(); - }); - } - } - } - - onWindowScroll() { - let docBody = document.body; - let docElement = document.documentElement; - let scrollTop = (window.pageYOffset||document.documentElement.scrollTop); - let winHeight = docElement.clientHeight; - let docHeight = Math.max(docBody.scrollHeight, docBody.offsetHeight, winHeight, docElement.scrollHeight, docElement.offsetHeight); - - if(scrollTop >= ((docHeight * this.buffer) - winHeight)) { - if(this.shouldLoad()) { - this.zone.run(() => { - this.load(); - }); - } - } - } - - ngOnDestroy() { - this.unbindScrollListener(); - } -} - -@NgModule({ - imports: [CommonModule], - exports: [DataScroller,SharedModule], - declarations: [DataScroller] -}) -export class DataScrollerModule { } - diff --git a/dashboard/src/app/components/datatable/datatable.scss b/dashboard/src/app/components/datatable/datatable.scss deleted file mode 100644 index 4252d7bc9..000000000 --- a/dashboard/src/app/components/datatable/datatable.scss +++ /dev/null @@ -1,404 +0,0 @@ -.ui-datatable { - position: relative; -} - -.ui-datatable table { - border-collapse:collapse; - width: 100%; - table-layout: fixed; -} - -.ui-datatable .ui-datatable-header, -.ui-datatable .ui-datatable-caption, -.ui-datatable .ui-datatable-footer { - text-align: center; - padding: .5em .75em; - box-sizing: border-box; -} - -.ui-datatable .ui-datatable-caption, -.ui-datatable .ui-datatable-header { - border-bottom: 0 none; -} - -.ui-datatable .ui-datatable-footer { - border-top: 0 none; -} - -.ui-datatable thead th, .ui-datatable tfoot td { - text-align: left; -} - -.ui-datatable thead tr { - border-width: 0; -} - -.ui-datatable thead th:not(:first-of-type) span.ui-column-title{ - border-left:1px solid #b4c3c9; - margin-left: -0.1rem; - padding-left: 0.1rem; -} - -.ui-datatable .ui-datatable-thead > tr > th, -.ui-datatable .ui-datatable-tfoot > tr > td, -.ui-datatable .ui-datatable-data > tr > td { - border-color: inherit; - box-sizing: border-box; - padding: .09rem .1rem; - border: none; -} -.ui-datatable .ui-datatable-thead > tr > th, -.ui-datatable .ui-datatable-tfoot > tr > td{ - padding: .1rem .1rem; -} - - -.ui-datatable.ui-datatable-resizable .ui-datatable-thead > tr > th, -.ui-datatable.ui-datatable-resizable .ui-datatable-tfoot > tr > td, -.ui-datatable.ui-datatable-resizable .ui-datatable-data > tr > td { - overflow: hidden; -} - -.ui-datatable .ui-datatable-thead > tr > th, -.ui-datatable .ui-datatable-tfoot > tr > td { - font-weight: normal; -} - -.ui-datatable tbody { - outline: 0; -} - -.ui-datatable tbody.ui-widget-content, -.ui-datatable tbody tr.ui-widget-content{ - border: 0; -} - -.ui-datatable tbody .ui-cell-data { - height: .32rem; - line-height: .32rem; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - display: block; -} - -.ui-datatable tbody .ui-cell-data > a{ - margin-right: 0.2rem; -} - -.ui-datatable tbody tr.ui-expanded-row-content { - background: #fbfdff; - border-bottom: 1px solid #ebf0f2; - border-top: 1px solid #ebf0f2; -} - -.ui-datatable .ui-sortable-column { - cursor: pointer; -} - -.ui-datatable .ui-sortable-column-icon { - display: inline-block; - margin-left: .125em; -} - -.ui-datatable tr.ui-state-highlight { - cursor: pointer; -} - -/* Scrollable */ -.ui-datatable-scrollable-body { - overflow: auto; - overflow-anchor: none; - min-height: 0%; -} - -.ui-datatable-scrollable-header, -.ui-datatable-scrollable-footer { - overflow: hidden; -} - -.ui-datatable-scrollable .ui-datatable-scrollable-header, -.ui-datatable-scrollable .ui-datatable-scrollable-footer { - position: relative; - border: 0 none; -} - -.ui-datatable-scrollable .ui-datatable-scrollable-header td { - font-weight: normal; -} - -.ui-datatable-scrollable-body .ui-datatable-data, -.ui-datatable-scrollable-body .ui-datatable-data > tr:first-child { - border-top-color: transparent; -} - -.ui-datatable .ui-datatable-data tr.ui-state-hover, -.ui-datatable .ui-datatable-data tr.ui-state-highlight { - border-color: inherit; - font-weight: inherit; - cursor: pointer; -} - -.ui-datatable .ui-datatable-data tr.ui-rowgroup-header td a, -.ui-datatable .ui-datatable-data tr.ui-rowgroup-header td span.ui-rowgroup-header-name { - display: inline-block; - vertical-align: middle; -} - -.ui-datatable-scrollable-theadclone { - height: 0; -} - -.ui-datatable-scrollable-theadclone tr { - height: 0; -} - -.ui-datatable-scrollable-theadclone th.ui-state-default { - height: 0; - border-bottom-width: 0; - border-top-width: 0; - padding-top: 0; - padding-bottom: 0; - outline: 0 none; -} - -.ui-datatable-scrollable-theadclone th span.ui-column-title { - display: block; - height: 0; -} - -.ui-datatable .ui-paginator { - padding: .125em; -} - -.ui-datatable .ui-paginator-top { - border-bottom-width: 0; -} - -.ui-datatable .ui-paginator-bottom { - border-top-width: 0; -} - -.ui-datatable-rtl { - direction: rtl; -} - -.ui-datatable-rtl.ui-datatable thead th, -.ui-datatable-rtl.ui-datatable tfoot td { - text-align: right; -} - -/* Row Toggler */ -.ui-row-toggler { - cursor: pointer; - font-size: .20rem; -} - -/* Resizable */ -.ui-datatable .ui-column-resizer { - display: block; - position: absolute !important; - top: 0; - right: 0; - margin: 0; - width: .5em; - height: 100%; - padding: 0px; - cursor:col-resize; - border: 1px solid transparent; -} - -.ui-datatable .ui-column-resizer-helper { - width: 1px; - position: absolute; - z-index: 10; - display: none; -} - -.ui-datatable-resizable { - padding-bottom: 1px; /*fix for webkit overlow*/ - overflow:auto; -} - -.ui-datatable-resizable thead th, -.ui-datatable-resizable tbody td, -.ui-datatable-resizable tfoot td { - white-space: nowrap; -} - -.ui-datatable-resizable th.ui-resizable-column { - background-clip: padding-box; - position: relative; -} - -/** Reflow **/ -.ui-datatable-reflow .ui-datatable-data td .ui-column-title { - display: none; -} - -/* Filter */ -.ui-datatable .ui-column-filter { - display: block; - width: 100%; - box-sizing: border-box; - margin-top: .25em; -} - -/* Editing */ -.ui-datatable .ui-editable-column input { - width: 100%; - outline: 0; -} - -.ui-datatable .ui-datatable-data > tr > td.ui-editable-column { - padding: .5em; -} - -.ui-datatable .ui-editable-column > .ui-cell-editor { - display: none; -} - -.ui-datatable .ui-datatable-data > tr > td.ui-editable-column.ui-cell-editing { - padding: 1px; -} - -.ui-datatable .ui-editable-column.ui-cell-editing > .ui-cell-editor { - display: block; -} - -.ui-datatable .ui-editable-column.ui-cell-editing > .ui-cell-data { - display: none; -} - -.ui-datatable-stacked thead th, -.ui-datatable-stacked tfoot td { - display: none !important; -} - -.ui-datatable.ui-datatable-stacked .ui-datatable-data > tr > td { - text-align: left; - display: block; - border: 0 none; - width: 100%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - float: left; - clear: left; -} - -.ui-datatable.ui-datatable-stacked .ui-datatable-data.ui-widget-content { - border: 0 none; -} - -.ui-datatable-stacked .ui-datatable-data tr.ui-widget-content { - border-left: 0 none; - border-right: 0 none; -} - -.ui-datatable-stacked .ui-datatable-data td .ui-column-title { - padding: .4em; - min-width: 30%; - display: inline-block; - margin: -.4em 1em -.4em -.4em; - font-weight: bold; -} - -.ui-datatable .ui-selection-column .ui-chkbox, -.ui-datatable .ui-selection-column .ui-radiobutton { - margin: 0; - display: block; -} - -.ui-datatable .ui-selection-column .ui-chkbox-box, -.ui-datatable .ui-selection-column .ui-radiobutton-box { - display: block; - box-sizing: border-box; - margin: 0; -} - -.ui-datatable-scrollable-wrapper { - position: relative; -} - -.ui-datatable-scrollable-view { - -} - -.ui-datatable-frozen-view .ui-datatable-scrollable-body { - overflow: hidden; -} - -.ui-datatable-unfrozen-view { - position: absolute; - top: 0px; -} - -.ui-datatable .ui-datatable-load-status { - width: 100%; - height: 100%; - top: 0px; - left: 0px; -} - -.ui-datatable .ui-datatable-virtual-table { - position: absolute; - top: 0px; - left: 0px; -} - -.ui-datatable .ui-datatable-loading { - position: absolute; - width: 100%; - height: 100%; - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=10)"; - opacity: 0.1; - z-index: 1; -} - -.ui-datatable .ui-datatable-loading-content { - position: absolute; - left: 50%; - top: 25%; - z-index: 2; -} - -@media ( max-width: 35em ) { - .ui-datatable-reflow thead th, - .ui-datatable-reflow tfoot td { - display: none !important; - } - - .ui-datatable-reflow .ui-datatable-data > tr > td { - text-align: left; - display: block; - border: 0 none; - width: 100% !important; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - float: left; - clear: left; - } - - .ui-datatable-reflow .ui-datatable-data.ui-widget-content { - border: 0 none; - } - - .ui-datatable-reflow .ui-datatable-data tr.ui-widget-content { - border-left: 0 none; - border-right: 0 none; - } - - .ui-datatable-reflow .ui-datatable-data td .ui-column-title { - padding: .4em; - min-width: 30%; - display: inline-block; - margin: -.4em 1em -.4em -.4em; - font-weight: bold; - } - - .ui-datatable-reflow.ui-datatable-scrollable .ui-datatable-scrollable-body colgroup { - display: block; - } -} \ No newline at end of file diff --git a/dashboard/src/app/components/datatable/datatable.spec.ts b/dashboard/src/app/components/datatable/datatable.spec.ts deleted file mode 100644 index 58d2368b0..000000000 --- a/dashboard/src/app/components/datatable/datatable.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { DataTable } from './datatable'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('DataTable', () => { - - let datatable: DataTable; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - DataTable - ] - }); - - fixture = TestBed.createComponent(DataTable); - datatable = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/datatable/datatable.ts b/dashboard/src/app/components/datatable/datatable.ts deleted file mode 100644 index 5c5a34851..000000000 --- a/dashboard/src/app/components/datatable/datatable.ts +++ /dev/null @@ -1,2671 +0,0 @@ -import {NgModule, Component, ElementRef, AfterContentInit, AfterViewInit, AfterViewChecked, OnInit, OnDestroy, Input, - ViewContainerRef, ViewChild, IterableDiffers, - Output, EventEmitter, ContentChild, ContentChildren, Renderer2, QueryList, TemplateRef, - ChangeDetectorRef, Inject, forwardRef, EmbeddedViewRef, NgZone -} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {FormsModule} from '@angular/forms' -import {SharedModule} from '../common/shared'; -import {PaginatorModule} from '../paginator/paginator'; -import {Column,Header,Footer,HeaderColumnGroup,FooterColumnGroup,PrimeTemplate} from '../common/shared'; -import {LazyLoadEvent} from '../common/lazyloadevent'; -import {FilterMetadata} from '../common/filtermetadata'; -import {SortMeta} from '../common/sortmeta'; -import {DomHandler} from '../dom/domhandler'; -import {ObjectUtils} from '../utils/objectutils'; -import {Subscription} from 'rxjs/Subscription'; -import {BlockableUI} from '../common/blockableui'; - -@Component({ - selector: 'p-dtRadioButton', - template: ` -
-
- -
-
- -
-
- ` -}) -export class DTRadioButton { - - @Input() checked: boolean; - - @Output() onClick: EventEmitter = new EventEmitter(); - - public hover: boolean; - - handleClick(event) { - this.onClick.emit(event); - } -} - -@Component({ - selector: 'p-dtCheckbox', - template: ` -
-
- -
-
- -
-
- ` -}) -export class DTCheckbox { - - @Input() checked: boolean; - - @Input() disabled: boolean; - - @Output() onChange: EventEmitter = new EventEmitter(); - - public hover: boolean; - - handleClick(event) { - if(!this.disabled) { - this.onChange.emit({originalEvent: event, checked: !this.checked}); - } - } -} - -@Component({ - selector: '[pColumnHeaders]', - template: ` - - - - {{col.header}} - - - - - - - - - - - - ` -}) -export class ColumnHeaders { - - constructor(@Inject(forwardRef(() => DataTable)) public dt:DataTable) {} - - @Input("pColumnHeaders") columns: Column[]; -} - -@Component({ - selector: '[pColumnFooters]', - template: ` - - {{col.footer}} - - - - - ` -}) -export class ColumnFooters { - - constructor(@Inject(forwardRef(() => DataTable)) public dt:DataTable) {} - - @Input("pColumnFooters") columns: Column[]; -} - -@Component({ - selector: '[pTableBody]', - template: ` - - - - - - - - - - - - - - - {{col.header}} - {{dt.resolveFieldData(rowData,col.field)}} - - - -
- - - - -
- - - - - - -
- - - - - - - - - -
- - - - {{dt.emptyMessage}} - - - - - - ` -}) -export class TableBody { - - constructor(@Inject(forwardRef(() => DataTable)) public dt:DataTable) {} - - @Input("pTableBody") columns: Column[]; - - @Input() data: any[]; - - visibleColumns() { - return this.columns ? this.columns.filter(c => !c.hidden): []; - } -} - -@Component({ - selector: '[pScrollableView]', - template: ` -
-
- - - - - - - - -
-
-
-
-
- - - - - -
-
-
- - ` -}) -export class ScrollableView implements AfterViewInit,AfterViewChecked,OnDestroy { - - constructor(@Inject(forwardRef(() => DataTable)) public dt:DataTable, public domHandler: DomHandler, public el: ElementRef, public renderer: Renderer2, public zone: NgZone) {} - - @Input("pScrollableView") columns: Column[]; - - @Input() headerColumnGroup: HeaderColumnGroup; - - @Input() footerColumnGroup: HeaderColumnGroup; - - @ViewChild('scrollHeader') scrollHeaderViewChild: ElementRef; - - @ViewChild('scrollHeaderBox') scrollHeaderBoxViewChild: ElementRef; - - @ViewChild('scrollBody') scrollBodyViewChild: ElementRef; - - @ViewChild('scrollTable') scrollTableViewChild: ElementRef; - - @ViewChild('scrollTableWrapper') scrollTableWrapperViewChild: ElementRef; - - @ViewChild('scrollFooter') scrollFooterViewChild: ElementRef; - - @ViewChild('scrollFooterBox') scrollFooterBoxViewChild: ElementRef; - - @Input() frozen: boolean; - - @Input() width: string; - - @Input() virtualScroll: boolean; - - @Output() onVirtualScroll: EventEmitter = new EventEmitter(); - - public scrollBody: HTMLDivElement; - - public scrollHeader: HTMLDivElement; - - public scrollHeaderBox: HTMLDivElement; - - public scrollTable: HTMLDivElement; - - public scrollTableWrapper: HTMLDivElement; - - public scrollFooter: HTMLDivElement; - - public scrollFooterBox: HTMLDivElement; - - public bodyScrollListener: Function; - - public headerScrollListener: Function; - - public scrollBodyMouseWheelListener: Function; - - public scrollFunction: Function; - - public rowHeight: number; - - public scrollTimeout: any; - - ngAfterViewInit() { - this.initScrolling(); - } - - ngAfterViewChecked() { - if(this.virtualScroll && !this.rowHeight) { - let row = this.domHandler.findSingle(this.scrollTable, 'tr.ui-widget-content:not(.ui-datatable-emptymessage-row)'); - if(row) { - this.rowHeight = this.domHandler.getOuterHeight(row); - } - } - - if(!this.frozen) { - this.zone.runOutsideAngular(() => { - setTimeout(() => { - this.alignScrollBar(); - }, 1); - }); - } - } - - initScrolling() { - this.scrollHeader = this.scrollHeaderViewChild.nativeElement; - this.scrollHeaderBox = this.scrollHeaderBoxViewChild.nativeElement; - this.scrollBody = this.scrollBodyViewChild.nativeElement; - this.scrollTable = this.scrollTableViewChild.nativeElement; - this.scrollTableWrapper = this.scrollTableWrapperViewChild.nativeElement; - this.scrollFooter = this.scrollFooterViewChild ? this.scrollFooterViewChild.nativeElement : null; - this.scrollFooterBox = this.scrollFooterBoxViewChild ? this.scrollFooterBoxViewChild.nativeElement : null; - - this.setScrollHeight(); - - if(!this.frozen) { - this.zone.runOutsideAngular(() => { - this.scrollHeader.addEventListener('scroll', this.onHeaderScroll.bind(this)); - this.scrollBody.addEventListener('scroll', this.onBodyScroll.bind(this)); - }); - } - - if(!this.frozen) { - this.alignScrollBar(); - } - else { - this.scrollBody.style.paddingBottom = this.domHandler.calculateScrollbarWidth() + 'px'; - } - } - - onBodyScroll(event) { - let frozenView = this.el.nativeElement.previousElementSibling; - if(frozenView) { - var frozenScrollBody = this.domHandler.findSingle(frozenView, '.ui-datatable-scrollable-body'); - } - - this.scrollHeaderBox.style.marginLeft = -1 * this.scrollBody.scrollLeft + 'px'; - if(this.scrollFooterBox) { - this.scrollFooterBox.style.marginLeft = -1 * this.scrollBody.scrollLeft + 'px'; - } - - if(frozenScrollBody) { - frozenScrollBody.scrollTop = this.scrollBody.scrollTop; - } - - if(this.virtualScroll) { - let viewport = this.domHandler.getOuterHeight(this.scrollBody); - let tableHeight = this.domHandler.getOuterHeight(this.scrollTable); - let pageHeight = this.rowHeight * this.dt.rows; - let virtualTableHeight = this.domHandler.getOuterHeight(this.scrollTableWrapper); - let pageCount = (virtualTableHeight / pageHeight)||1; - - if(this.scrollBody.scrollTop + viewport > parseFloat(this.scrollTable.style.top) + tableHeight || this.scrollBody.scrollTop < parseFloat(this.scrollTable.style.top)) { - let page = Math.floor((this.scrollBody.scrollTop * pageCount) / (this.scrollBody.scrollHeight)) + 1; - this.onVirtualScroll.emit({ - page: page, - callback: () => { - this.scrollTable.style.top = ((page - 1) * pageHeight) + 'px'; - } - }); - } - } - } - - setScrollHeight() { - if(this.dt.scrollHeight) { - if(this.dt.scrollHeight.indexOf('%') !== -1) { - this.scrollBody.style.visibility = 'hidden'; - this.scrollBody.style.height = '100px'; //temporary height to calculate static height - let containerHeight = this.domHandler.getOuterHeight(this.dt.el.nativeElement.children[0]); - let relativeHeight = this.domHandler.getOuterHeight(this.dt.el.nativeElement.parentElement) * parseInt(this.dt.scrollHeight) / 100; - let staticHeight = containerHeight - 100; //total height of headers, footers, paginators - let scrollBodyHeight = (relativeHeight - staticHeight); - - this.scrollBody.style.height = 'auto'; - this.scrollBody.style.maxHeight = scrollBodyHeight + 'px'; - this.scrollBody.style.visibility = 'visible'; - } - else { - this.scrollBody.style.maxHeight = this.dt.scrollHeight; - } - } - } - - onHeaderScroll(event) { - this.scrollHeader.scrollLeft = 0; - } - - hasVerticalOverflow() { - return this.domHandler.getOuterHeight(this.scrollTable) > this.domHandler.getOuterHeight(this.scrollBody); - } - - alignScrollBar() { - let scrollBarWidth = this.hasVerticalOverflow() ? this.domHandler.calculateScrollbarWidth() : 0; - this.scrollHeaderBox.style.marginRight = scrollBarWidth + 'px'; - if(this.scrollFooterBox) { - this.scrollFooterBox.style.marginRight = scrollBarWidth + 'px'; - } - } - - ngOnDestroy() { - this.scrollHeader.removeEventListener('scroll', this.onHeaderScroll); - this.scrollBody.removeEventListener('scroll', this.onBodyScroll); - } -} - -@Component({ - selector: 'p-dataTable', - template: ` -
-
-
- -
-
- -
- -
- - - - - - - - - - - - - - -
-
- - -
-
-
-
-
- - - - - - - -
- `, - providers: [DomHandler,ObjectUtils] -}) -export class DataTable implements AfterViewChecked,AfterViewInit,AfterContentInit,OnInit,OnDestroy,BlockableUI { - - @Input() paginator: boolean; - - @Input() rows: number; - - @Input() pageLinks: number = 5; - - @Input() rowsPerPageOptions: number[]; - - @Input() responsive: boolean; - - @Input() stacked: boolean; - - @Input() selectionMode: string; - - @Output() selectionChange: EventEmitter = new EventEmitter(); - - @Input() editable: boolean; - - @Input() showHeaderCheckbox: boolean = true; - - @Output() onRowClick: EventEmitter = new EventEmitter(); - - @Output() onRowSelect: EventEmitter = new EventEmitter(); - - @Output() onRowUnselect: EventEmitter = new EventEmitter(); - - @Output() onRowDblclick: EventEmitter = new EventEmitter(); - - @Output() onHeaderCheckboxToggle: EventEmitter = new EventEmitter(); - - @Input() headerCheckboxToggleAllPages: boolean; - - @Output() onContextMenuSelect: EventEmitter = new EventEmitter(); - - @Input() filterDelay: number = 300; - - @Input() lazy: boolean; - - @Output() onLazyLoad: EventEmitter = new EventEmitter(); - - @Input() resizableColumns: boolean; - - @Input() columnResizeMode: string = 'fit'; - - @Output() onColResize: EventEmitter = new EventEmitter(); - - @Input() reorderableColumns: boolean; - - @Output() onColReorder: EventEmitter = new EventEmitter(); - - @Input() scrollable: boolean; - - @Input() virtualScroll: boolean; - - @Input() scrollHeight: any; - - @Input() scrollWidth: any; - - @Input() frozenWidth: any; - - @Input() unfrozenWidth: any; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() tableStyle: any; - - @Input() tableStyleClass: string; - - @Input() globalFilter: any; - - @Input() sortMode: string = 'single'; - - @Input() defaultSortOrder: number = 1; - - @Input() groupField: string; - - @Input() contextMenu: any; - - @Input() csvSeparator: string = ','; - - @Input() exportFilename: string = 'download'; - - @Input() emptyMessage: string = 'No records found'; - - @Input() paginatorPosition: string = 'bottom'; - - @Input() alwaysShowPaginator: boolean = true; - - @Input() metaKeySelection: boolean = true; - - @Input() rowTrackBy: Function = (index: number, item: any) => item; - - @Input() immutable: boolean = true; - - @Input() frozenValue: any[]; - - @Input() compareSelectionBy: string = 'deepEquals'; - - @Output() onEditInit: EventEmitter = new EventEmitter(); - - @Output() onEditComplete: EventEmitter = new EventEmitter(); - - @Output() onEdit: EventEmitter = new EventEmitter(); - - @Output() onEditCancel: EventEmitter = new EventEmitter(); - - @Output() onPage: EventEmitter = new EventEmitter(); - - @Output() onSort: EventEmitter = new EventEmitter(); - - @Output() onFilter: EventEmitter = new EventEmitter(); - - @ContentChild(Header) header; - - @ContentChild(Footer) footer; - - @Input() expandableRows: boolean; - - @Input() expandedRows: any[]; - - @Input() expandableRowGroups: boolean; - - @Input() rowExpandMode: string = 'multiple'; - - @Input() public expandedRowsGroups: any[]; - - @Input() expandedIcon: string = 'fa-angle-down'; - - @Input() collapsedIcon: string = 'fa-angle-right'; - - @Input() tabindex: number = 1; - - @Input() rowStyleClass: Function; - - @Input() rowStyleMap: Object; - - @Input() rowGroupMode: string; - - @Input() sortableRowGroup: boolean = true; - - @Input() sortFile: string; - - @Input() rowHover: boolean; - - @Input() public filters: {[s: string]: FilterMetadata;} = {}; - - @Input() dataKey: string; - - @Input() loading: boolean; - - @Input() loadingIcon: string = 'fa-circle-o-notch'; - - @Input() virtualScrollDelay: number = 500; - - @Input() rowGroupExpandMode: string = 'multiple'; - - @Output() valueChange: EventEmitter = new EventEmitter(); - - @Output() firstChange: EventEmitter = new EventEmitter(); - - @Output() onRowExpand: EventEmitter = new EventEmitter(); - - @Output() onRowCollapse: EventEmitter = new EventEmitter(); - - @Output() onRowGroupExpand: EventEmitter = new EventEmitter(); - - @Output() onRowGroupCollapse: EventEmitter = new EventEmitter(); - - @ContentChildren(PrimeTemplate) templates: QueryList; - - @ContentChildren(Column) cols: QueryList; - - @ContentChildren(HeaderColumnGroup) headerColumnGroups: QueryList; - - @ContentChildren(FooterColumnGroup) footerColumnGroups: QueryList; - - public _value: any[]; - - public dataToRender: any[]; - - public page: number = 0; - - public filterTimeout: any; - - public filteredValue: any[]; - - public columns: Column[]; - - public frozenColumns: Column[]; - - public scrollableColumns: Column[]; - - public frozenHeaderColumnGroup: HeaderColumnGroup; - - public scrollableHeaderColumnGroup: HeaderColumnGroup; - - public frozenFooterColumnGroup: HeaderColumnGroup; - - public scrollableFooterColumnGroup: HeaderColumnGroup; - - public columnsChanged: boolean = false; - - public sortColumn: Column; - - public columnResizing: boolean; - - public lastResizerHelperX: number; - - public documentEditListener: Function; - - public documentColumnResizeEndListener: Function; - - public resizerHelper: any; - - public resizeColumn: any; - - public reorderIndicatorUp: any; - - public reorderIndicatorDown: any; - - public iconWidth: number; - - public iconHeight: number; - - public draggedColumn: any; - - public dropPosition: number; - - public tbody: any; - - public rowTouched: boolean; - - public rowGroupToggleClick: boolean; - - public editingCell: any; - - public virtualTableHeight: number; - - public rowGroupMetadata: any; - - public rowGroupHeaderTemplate: TemplateRef; - - public rowGroupFooterTemplate: TemplateRef; - - public rowExpansionTemplate: TemplateRef; - - public emptyMessageTemplate: TemplateRef; - - public paginatorLeftTemplate: TemplateRef; - - public paginatorRightTemplate: TemplateRef; - - public scrollBarWidth: number; - - public editorClick: boolean; - - public _first: number = 0; - - public selectionKeys: any; - - public preventSelectionKeysPropagation: boolean; - - public preventSortPropagation: boolean; - - public preventRowClickPropagation: boolean; - - _multiSortMeta: SortMeta[]; - - _sortField: string; - - _sortOrder: number = 1; - - differ: any; - - _selection: any; - - _totalRecords: number; - - globalFilterFunction: any; - - columnsSubscription: Subscription; - - totalRecordsChanged: boolean; - - anchorRowIndex: number; - - rangeRowIndex: number; - - initialized: boolean; - - virtualScrollTimer: any; - - virtualScrollableTableWrapper: HTMLDivElement; - - virtualScrollCallback: Function; - - editChanged: boolean; - - constructor(public el: ElementRef, public domHandler: DomHandler, public differs: IterableDiffers, - public renderer: Renderer2, public changeDetector: ChangeDetectorRef, public objectUtils: ObjectUtils, - public zone: NgZone) { - this.differ = differs.find([]).create(null); - } - - ngOnInit() { - if(this.lazy) { - this.onLazyLoad.emit(this.createLazyLoadMetadata()); - } - } - - ngAfterContentInit() { - this.initColumns(); - this.initColumnGroups(); - - this.columnsSubscription = this.cols.changes.subscribe(_ => { - this.initColumns(); - this.changeDetector.markForCheck(); - }); - - this.templates.forEach((item) => { - switch(item.getType()) { - case 'rowexpansion': - this.rowExpansionTemplate = item.template; - break; - - case 'rowgroupheader': - this.rowGroupHeaderTemplate = item.template; - break; - - case 'rowgroupfooter': - this.rowGroupFooterTemplate = item.template; - break; - - case 'emptymessage': - this.emptyMessageTemplate = item.template; - break; - - case 'paginatorLeft': - this.paginatorLeftTemplate = item.template; - break; - - case 'paginatorRight': - this.paginatorRightTemplate = item.template; - break; - } - }); - } - - ngAfterViewChecked() { - if(this.columnsChanged && this.el.nativeElement.offsetParent) { - if(this.resizableColumns) { - this.initResizableColumns(); - } - - if(this.reorderableColumns) { - this.initColumnReordering(); - } - - this.columnsChanged = false; - } - - if(this.totalRecordsChanged && this.virtualScroll && this.virtualScrollableTableWrapper && this.virtualScrollableTableWrapper.offsetParent) { - let row = this.domHandler.findSingle(this.virtualScrollableTableWrapper,'tr.ui-widget-content'); - let rowHeight = this.domHandler.getOuterHeight(row); - this.virtualTableHeight = this._totalRecords * rowHeight; - this.virtualScrollableTableWrapper.style.height = this.virtualTableHeight + 'px'; - this.totalRecordsChanged = false; - } - } - - ngAfterViewInit() { - if(this.globalFilter) { - this.globalFilterFunction = this.renderer.listen(this.globalFilter, 'keyup', () => { - if (this.filterTimeout) { - clearTimeout(this.filterTimeout); - } - this.filterTimeout = setTimeout(() => { - this._filter(); - this.filterTimeout = null; - }, this.filterDelay); - }); - } - - this.virtualScrollableTableWrapper = this.domHandler.findSingle(this.el.nativeElement, 'div.ui-datatable-scrollable-table-wrapper'); - - this.initialized = true; - } - - @Input() get multiSortMeta(): SortMeta[]{ - return this._multiSortMeta; - } - - set multiSortMeta(val: SortMeta[]){ - this._multiSortMeta = val; - if(this.sortMode === 'multiple') { - this.sortMultiple(); - } - } - - @Input() get sortField(): string{ - return this._sortField; - } - - set sortField(val: string){ - this._sortField = val; - if(this.sortMode === 'single') { - this.sortSingle(); - } - } - - @Input() get sortOrder(): number { - return this._sortOrder; - } - set sortOrder(val: number) { - this._sortOrder = val; - if(this.sortMode === 'single') { - this.sortSingle(); - } - } - - @Input() get value(): any[] { - return this._value; - } - set value(val:any[]) { - if(this.immutable) { - this._value = val ? [...val] : null; - this.handleDataChange(); - } - else { - this._value = val; - } - - this.valueChange.emit(this.value); - } - - @Input() get first(): number { - return this._first; - } - - set first(val:number) { - let shouldPaginate = this.initialized && this._first !== val; - - this._first = val; - - if(shouldPaginate) { - this.paginate(); - } - } - - @Input() get totalRecords(): number { - return this._totalRecords; - } - - set totalRecords(val:number) { - this._totalRecords = val; - this.totalRecordsChanged = true; - } - - @Input() get selection(): any { - return this._selection; - } - - set selection(val: any) { - this._selection = val; - - if(this.dataKey && !this.preventSelectionKeysPropagation) { - this.selectionKeys = {}; - if(this._selection) { - if(Array.isArray(this._selection)) { - for(let data of this._selection) { - this.selectionKeys[String(this.objectUtils.resolveFieldData(data, this.dataKey))] = 1; - } - } - else { - this.selectionKeys[String(this.objectUtils.resolveFieldData(this._selection, this.dataKey))] = 1; - } - } - } - this.preventSelectionKeysPropagation = false; - } - - ngDoCheck() { - if(!this.immutable) { - let changes = this.differ.diff(this.value); - if(changes) { - this.handleDataChange(); - } - } - } - - handleDataChange() { - if(this.paginator) { - this.updatePaginator(); - } - - if(this.virtualScroll && this.virtualScrollCallback) { - this.virtualScrollCallback(); - } - - if(!this.lazy) { - if(this.hasFilter()) { - this._filter(); - } - - if(this.preventSortPropagation) { - this.preventSortPropagation = false; - } - else if(this.sortField||this.multiSortMeta) { - if(!this.sortColumn && this.columns) { - this.sortColumn = this.columns.find(col => col.field === this.sortField && col.sortable === 'custom'); - } - - if(this.sortMode == 'single') - this.sortSingle(); - else if(this.sortMode == 'multiple') - this.sortMultiple(); - } - } - - this.updateDataToRender(this.filteredValue||this.value); - } - - initColumns(): void { - this.columns = this.cols.toArray(); - this.initScrollableColumns(); - - this.columnsChanged = true; - } - - initScrollableColumns() { - this.scrollableColumns = []; - this.frozenColumns = []; - - for(let col of this.columns) { - if(col.frozen) - this.frozenColumns.push(col); - else - this.scrollableColumns.push(col); - } - } - - initColumnGroups(): void { - let headerColumnsGroups = this.headerColumnGroups.toArray(); - let footerColumnsGroups = this.footerColumnGroups.toArray(); - - for(let columnGroup of headerColumnsGroups) { - if(columnGroup.frozen) - this.frozenHeaderColumnGroup = columnGroup; - else - this.scrollableHeaderColumnGroup = columnGroup; - } - - for(let columnGroup of footerColumnsGroups) { - if(columnGroup.frozen) - this.frozenFooterColumnGroup = columnGroup; - else - this.scrollableFooterColumnGroup = columnGroup; - } - } - - resolveFieldData(data: any, field: string): any { - return this.objectUtils.resolveFieldData(data, field); - } - - updateRowGroupMetadata() { - this.rowGroupMetadata = {}; - if(this.dataToRender) { - for(let i = 0; i < this.dataToRender.length; i++) { - let rowData = this.dataToRender[i]; - let group = this.resolveFieldData(rowData, this.sortField); - if(i == 0) { - this.rowGroupMetadata[group] = {index:0, size: 1}; - } - else { - let previousRowData = this.dataToRender[i-1]; - let previousRowGroup = this.resolveFieldData(previousRowData, this.sortField); - if(group === previousRowGroup) { - this.rowGroupMetadata[group].size++; - } - else { - this.rowGroupMetadata[group] = {index:i, size: 1}; - } - } - } - } - } - - updatePaginator() { - //total records - this.updateTotalRecords(); - - //first - if(this.totalRecords && this.first >= this.totalRecords) { - let numberOfPages = Math.ceil(this.totalRecords/this.rows); - this._first = Math.max((numberOfPages-1) * this.rows, 0); - } - } - - updateTotalRecords() { - this.totalRecords = this.lazy ? this.totalRecords : (this.value ? this.value.length: 0); - } - - onPageChange(event) { - this._first = event.first; - this.firstChange.emit(this.first); - this.rows = event.rows; - this.paginate(); - } - - paginate() { - if(this.lazy) - this.onLazyLoad.emit(this.createLazyLoadMetadata()); - else - this.updateDataToRender(this.filteredValue||this.value); - - this.onPage.emit({ - first: this.first, - rows: this.rows - }); - } - - updateDataToRender(datasource) { - if((this.paginator || this.virtualScroll) && datasource) { - this.dataToRender = []; - let startIndex: number = this.lazy ? 0 : this.first; - let endIndex: number = this.virtualScroll ? this.first + this.rows * 2 : startIndex + this.rows; - - for(let i = startIndex; i < endIndex; i++) { - if(i >= datasource.length) { - break; - } - - this.dataToRender.push(datasource[i]); - } - } - else { - this.dataToRender = datasource; - } - - if(this.rowGroupMode) { - this.updateRowGroupMetadata(); - } - - this.changeDetector.markForCheck(); - } - - onVirtualScroll(event) { - this._first = (event.page - 1) * this.rows; - this.virtualScrollCallback = event.callback; - - this.zone.run(() => { - if(this.virtualScrollTimer) { - clearTimeout(this.virtualScrollTimer); - } - - this.virtualScrollTimer = setTimeout(() => { - if(this.lazy) - this.onLazyLoad.emit(this.createLazyLoadMetadata()); - else - this.updateDataToRender(this.filteredValue||this.value); - }, this.virtualScrollDelay); - }); - } - - onHeaderKeydown(event, column: Column) { - if(event.keyCode == 13) { - this.sort(event, column); - event.preventDefault(); - } - } - - onHeaderMousedown(event, header: any) { - if(this.reorderableColumns) { - if(event.target.nodeName !== 'INPUT') { - header.draggable = true; - } else if(event.target.nodeName === 'INPUT') { - header.draggable = false; - } - } - } - - sort(event, column: Column) { - if(!column.sortable) { - return; - } - let targetNode = event.target; - if(this.domHandler.hasClass(targetNode, 'ui-sortable-column') || this.domHandler.hasClass(targetNode, 'ui-column-title') || this.domHandler.hasClass(targetNode, 'ui-sortable-column-icon')) { - if(!this.immutable) { - this.preventSortPropagation = true; - } - - let columnSortField = column.sortField||column.field; - this._sortOrder = (this.sortField === columnSortField) ? this.sortOrder * -1 : this.defaultSortOrder; - this._sortField = columnSortField; - this.sortColumn = column; - let metaKey = event.metaKey||event.ctrlKey; - - if(this.sortMode == 'multiple') { - if(!this.multiSortMeta||!metaKey) { - this._multiSortMeta = []; - } - - this.addSortMeta({field: this.sortField, order: this.sortOrder}); - } - - if(this.lazy) { - this._first = 0; - this.onLazyLoad.emit(this.createLazyLoadMetadata()); - } - else { - if(this.sortMode == 'multiple') - this.sortMultiple(); - else - this.sortSingle(); - } - - this.onSort.emit({ - field: this.sortField, - order: this.sortOrder, - multisortmeta: this.multiSortMeta - }); - } - - this.updateDataToRender(this.filteredValue||this.value); - } - - sortSingle() { - if(this.value) { - if(this.sortColumn && this.sortColumn.sortable === 'custom') { - this.preventSortPropagation = true; - this.sortColumn.sortFunction.emit({ - field: this.sortField, - order: this.sortOrder - }); - } - else { - this.value.sort((data1, data2) => { - let value1 = this.resolveFieldData(data1, this.sortField); - let value2 = this.resolveFieldData(data2, this.sortField); - let result = null; - - if (value1 == null && value2 != null) - result = -1; - else if (value1 != null && value2 == null) - result = 1; - else if (value1 == null && value2 == null) - result = 0; - else if (typeof value1 === 'string' && typeof value2 === 'string') - result = value1.localeCompare(value2); - else - result = (value1 < value2) ? -1 : (value1 > value2) ? 1 : 0; - - return (this.sortOrder * result); - }); - } - - this._first = 0; - - if(this.hasFilter()) { - this._filter(); - } - } - } - - sortMultiple() { - if(this.value) { - this.value.sort((data1,data2) => { - return this.multisortField(data1, data2, this.multiSortMeta, 0); - }); - - if(this.hasFilter()) { - this._filter(); - } - } - } - - multisortField(data1,data2,multiSortMeta,index) { - let value1 = this.resolveFieldData(data1, multiSortMeta[index].field); - let value2 = this.resolveFieldData(data2, multiSortMeta[index].field); - let result = null; - - if (typeof value1 == 'string' || value1 instanceof String) { - if (value1.localeCompare && (value1 != value2)) { - return (multiSortMeta[index].order * value1.localeCompare(value2)); - } - } - else { - result = (value1 < value2) ? -1 : 1; - } - - if(value1 == value2) { - return (multiSortMeta.length - 1) > (index) ? (this.multisortField(data1, data2, multiSortMeta, index + 1)) : 0; - } - - return (multiSortMeta[index].order * result); - } - - addSortMeta(meta) { - var index = -1; - for(var i = 0; i < this.multiSortMeta.length; i++) { - if(this.multiSortMeta[i].field === meta.field) { - index = i; - break; - } - } - - if(index >= 0) - this.multiSortMeta[index] = meta; - else - this.multiSortMeta.push(meta); - } - - isSorted(column: Column) { - if(!column.sortable) { - return false; - } - - let columnSortField = column.sortField||column.field; - - if(this.sortMode === 'single') { - return (this.sortField && columnSortField === this.sortField); - } - else if(this.sortMode === 'multiple') { - let sorted = false; - if(this.multiSortMeta) { - for(let i = 0; i < this.multiSortMeta.length; i++) { - if(this.multiSortMeta[i].field == columnSortField) { - sorted = true; - break; - } - } - } - return sorted; - } - } - - getSortOrder(column: Column) { - let order = 0; - let columnSortField = column.sortField||column.field; - - if(this.sortMode === 'single') { - if(this.sortField && columnSortField === this.sortField) { - order = this.sortOrder; - } - } - else if(this.sortMode === 'multiple') { - if(this.multiSortMeta) { - for(let i = 0; i < this.multiSortMeta.length; i++) { - if(this.multiSortMeta[i].field == columnSortField) { - order = this.multiSortMeta[i].order; - break; - } - } - } - } - return order; - } - - onRowGroupClick(event) { - if(this.rowGroupToggleClick) { - this.rowGroupToggleClick = false; - return; - } - - if(this.sortableRowGroup) { - let targetNode = event.target.nodeName; - if((targetNode == 'TD' || (targetNode == 'SPAN' && !this.domHandler.hasClass(event.target, 'ui-clickable')))) { - if(this.sortField != this.groupField) { - this._sortField = this.groupField; - this.sortSingle(); - } - else { - this._sortOrder = -1 * this.sortOrder; - this.sortSingle(); - } - } - } - } - - clearSelectionRange(event: MouseEvent) { - let rangeStart, rangeEnd; - - if(this.rangeRowIndex > this.anchorRowIndex) { - rangeStart = this.anchorRowIndex; - rangeEnd = this.rangeRowIndex; - } - else if(this.rangeRowIndex < this.anchorRowIndex) { - rangeStart = this.rangeRowIndex; - rangeEnd = this.anchorRowIndex; - } - else { - rangeStart = this.rangeRowIndex; - rangeEnd = this.rangeRowIndex; - } - - for(let i = rangeStart; i <= rangeEnd; i++) { - let rangeRowData = this.dataToRender[i]; - let selectionIndex = this.findIndexInSelection(rangeRowData); - this._selection = this.selection.filter((val,i) => i!=selectionIndex); - let dataKeyValue: string = this.dataKey ? String(this.resolveFieldData(rangeRowData, this.dataKey)) : null; - if(dataKeyValue) { - delete this.selectionKeys[dataKeyValue]; - } - this.onRowUnselect.emit({originalEvent: event, data: rangeRowData, type: 'row'}); - } - } - - selectRange(event: MouseEvent, rowIndex: number) { - let rangeStart, rangeEnd; - - if(this.anchorRowIndex > rowIndex) { - rangeStart = rowIndex; - rangeEnd = this.anchorRowIndex; - } - else if(this.anchorRowIndex < rowIndex) { - rangeStart = this.anchorRowIndex; - rangeEnd = rowIndex; - } - else { - rangeStart = rowIndex; - rangeEnd = rowIndex; - } - - for(let i = rangeStart; i <= rangeEnd; i++) { - let rangeRowData = this.dataToRender[i]; - this._selection = [...this.selection, rangeRowData]; - this.selectionChange.emit(this.selection); - let dataKeyValue: string = this.dataKey ? String(this.resolveFieldData(rangeRowData, this.dataKey)) : null; - if(dataKeyValue) { - this.selectionKeys[dataKeyValue] = 1; - } - this.onRowSelect.emit({originalEvent: event, data: rangeRowData, type: 'row'}); - } - } - - handleRowClick(event: MouseEvent, rowData: any, index: number) { - if(this.preventRowClickPropagation) { - this.preventRowClickPropagation = false; - return; - } - - let targetNode = ( event.target).nodeName; - - if(targetNode == 'INPUT' || targetNode == 'BUTTON' || targetNode == 'A' || (this.domHandler.hasClass(event.target, 'ui-clickable'))) { - return; - } - - this.onRowClick.next({originalEvent: event, data: rowData}); - - if(this.selectionMode) { - if(this.isMultipleSelectionMode() && event.shiftKey && this.anchorRowIndex != null) { - this.domHandler.clearSelection(); - if(this.rangeRowIndex != null) { - this.clearSelectionRange(event); - } - - this.rangeRowIndex = index; - this.selectRange(event, index); - } - else { - let selected = this.isSelected(rowData); - let metaSelection = this.rowTouched ? false : this.metaKeySelection; - let dataKeyValue: string = this.dataKey ? String(this.resolveFieldData(rowData, this.dataKey)) : null; - this.anchorRowIndex = index; - this.rangeRowIndex = index; - - if(metaSelection) { - let metaKey = event.metaKey||event.ctrlKey; - - if(selected && metaKey) { - if(this.isSingleSelectionMode()) { - this._selection = null; - this.selectionKeys = {}; - this.selectionChange.emit(null); - } - else { - let selectionIndex = this.findIndexInSelection(rowData); - this._selection = this.selection.filter((val,i) => i!=selectionIndex); - this.selectionChange.emit(this.selection); - if(dataKeyValue) { - delete this.selectionKeys[dataKeyValue]; - } - } - - this.onRowUnselect.emit({originalEvent: event, data: rowData, type: 'row'}); - } - else { - if(this.isSingleSelectionMode()) { - this._selection = rowData; - this.selectionChange.emit(rowData); - if(dataKeyValue) { - this.selectionKeys = {}; - this.selectionKeys[dataKeyValue] = 1; - } - } - else if(this.isMultipleSelectionMode()) { - if(metaKey) { - this._selection = this.selection||[]; - } - else { - this._selection = []; - this.selectionKeys = {}; - } - - if(!rowData.disabled){ - this._selection = [...this.selection,rowData]; - } - - this.selectionChange.emit(this.selection); - if(dataKeyValue) { - this.selectionKeys[dataKeyValue] = 1; - } - } - - this.onRowSelect.emit({originalEvent: event, data: rowData, type: 'row'}); - } - } - else { - if(this.isSingleSelectionMode()) { - if(selected) { - this._selection = null; - this.selectionKeys = {}; - this.selectionChange.emit(this.selection); - this.onRowUnselect.emit({originalEvent: event, data: rowData, type: 'row'}); - } - else { - this._selection = rowData; - this.selectionChange.emit(this.selection); - this.onRowSelect.emit({originalEvent: event, data: rowData, type: 'row'}); - if(dataKeyValue) { - this.selectionKeys = {}; - this.selectionKeys[dataKeyValue] = 1; - } - } - } - else { - if(selected) { - let selectionIndex = this.findIndexInSelection(rowData); - this._selection = this.selection.filter((val,i) => i!=selectionIndex); - this.selectionChange.emit(this.selection); - this.onRowUnselect.emit({originalEvent: event, data: rowData, type: 'row'}); - if(dataKeyValue) { - delete this.selectionKeys[dataKeyValue]; - } - } - else { - this._selection = [...this.selection||[],rowData]; - this.selectionChange.emit(this.selection); - this.onRowSelect.emit({originalEvent: event, data: rowData, type: 'row'}); - if(dataKeyValue) { - this.selectionKeys[dataKeyValue] = 1; - } - } - } - - } - } - - this.preventSelectionKeysPropagation = true; - } - - this.rowTouched = false; - } - - handleRowTouchEnd(event: Event) { - this.rowTouched = true; - } - - selectRowWithRadio(event: Event, rowData:any) { - if(this.selection != rowData) { - this._selection = rowData; - this.selectionChange.emit(this.selection); - this.onRowSelect.emit({originalEvent: event, data: rowData, type: 'radiobutton'}); - - if(this.dataKey) { - this.selectionKeys = {}; - this.selectionKeys[String(this.resolveFieldData(rowData, this.dataKey))] = 1; - } - } - else { - this._selection = null; - this.selectionChange.emit(this.selection); - this.onRowUnselect.emit({originalEvent: event, data: rowData, type: 'radiobutton'}); - } - - this.preventSelectionKeysPropagation = true; - this.preventRowClickPropagation = true; - } - - toggleRowWithCheckbox(event, rowData: any) { - let selectionIndex = this.findIndexInSelection(rowData); - this.selection = this.selection||[]; - let dataKeyValue: string = this.dataKey ? String(this.resolveFieldData(rowData, this.dataKey)) : null; - - if(selectionIndex != -1) { - this._selection = this.selection.filter((val,i) => i!=selectionIndex); - this.selectionChange.emit(this.selection); - this.onRowUnselect.emit({originalEvent: event, data: rowData, type: 'checkbox'}); - if(dataKeyValue) { - delete this.selectionKeys[dataKeyValue]; - } - } - else { - if(!rowData.disabled){ - this._selection = [...this.selection,rowData]; - } - - this.selectionChange.emit(this.selection); - this.onRowSelect.emit({originalEvent: event, data: rowData, type: 'checkbox'}); - if(dataKeyValue) { - this.selectionKeys[dataKeyValue] = 1; - } - } - - this.preventSelectionKeysPropagation = true; - this.preventRowClickPropagation = true; - } - - toggleRowsWithCheckbox(event) { - if(event.checked){ - this.selection = this.headerCheckboxToggleAllPages ? this.value.slice() : this.dataToRender.slice(); - let [...selectionTemp] = this.selection; - this.selection.forEach((ele, i)=>{ - if(ele.disabled){ - let index = selectionTemp.findIndex((value, index, arr)=>{ - return value === ele; - }) - selectionTemp.splice(index, 1); - } - }) - this.selection = selectionTemp; - }else{ - this.selection = []; - } - this.selectionChange.emit(this.selection); - - this.onHeaderCheckboxToggle.emit({originalEvent: event, checked: event.checked}); - } - - onRowRightClick(event, rowData) { - if(this.contextMenu) { - let selectionIndex = this.findIndexInSelection(rowData); - let selected = selectionIndex != -1; - let dataKeyValue: string = this.dataKey ? String(this.resolveFieldData(rowData, this.dataKey)) : null; - - if(!selected) { - if(this.isSingleSelectionMode()) { - this.selection = rowData; - this.selectionChange.emit(rowData); - } - else if(this.isMultipleSelectionMode()) { - this.selection = [rowData]; - this.selectionChange.emit(this.selection); - } - - if(this.dataKey) { - this.selectionKeys[String(this.resolveFieldData(rowData, this.dataKey))] = 1; - this.preventSelectionKeysPropagation = true; - } - } - - this.contextMenu.show(event); - this.onContextMenuSelect.emit({originalEvent: event, data: rowData}); - } - } - - rowDblclick(event, rowData) { - this.onRowDblclick.emit({originalEvent: event, data: rowData}); - } - - isSingleSelectionMode() { - return this.selectionMode === 'single'; - } - - isMultipleSelectionMode() { - return this.selectionMode === 'multiple'; - } - - findIndexInSelection(rowData: any) { - let index: number = -1; - if(this.selection) { - for(let i = 0; i < this.selection.length; i++) { - if(this.equals(rowData, this.selection[i])) { - index = i; - break; - } - } - } - - return index; - } - - isSelected(rowData) { - if(rowData && this.selection) { - if(this.dataKey) { - return this.selectionKeys[this.objectUtils.resolveFieldData(rowData, this.dataKey)] !== undefined; - } - else { - if(this.selection instanceof Array) - return this.findIndexInSelection(rowData) > -1; - else - return this.equals(rowData, this.selection); - } - } - - return false; - } - - equals(data1, data2) { - return this.compareSelectionBy === 'equals' ? (data1 === data2) : this.objectUtils.equals(data1, data2, this.dataKey); - } - - get allSelected() { - if(this.headerCheckboxToggleAllPages) { - return this.selection && this.value && this.selection.length === this.value.length; - } - else { - let val = true; - let num = 0; - this.dataToRender && this.dataToRender.map(ele=>{ - if(ele.disabled) - num++; - }) - - if(this.dataToRender && this.selection && (this.dataToRender.length <= (this.selection.length + num))) { - for(let data of this.dataToRender) { - if(!this.isSelected(data) && !data.disabled) { - val = false; - break; - } - } - } - else { - val = false; - } - - if(this.selection.length == 0){ - val = false; - } - - return val; - } - } - - onFilterKeyup(value, field, matchMode) { - if(this.filterTimeout) { - clearTimeout(this.filterTimeout); - } - - this.filterTimeout = setTimeout(() => { - this.filter(value, field, matchMode); - this.filterTimeout = null; - }, this.filterDelay); - } - - filter(value, field, matchMode) { - if(!this.isFilterBlank(value)) - this.filters[field] = {value: value, matchMode: matchMode}; - else if(this.filters[field]) - delete this.filters[field]; - - this._filter(); - } - - isFilterBlank(filter: any): boolean { - if(filter !== null && filter !== undefined) { - if((typeof filter === 'string' && filter.trim().length == 0) || (filter instanceof Array && filter.length == 0)) - return true; - else - return false; - } - return true; - } - - _filter() { - this._first = 0; - - if(this.lazy) { - this.onLazyLoad.emit(this.createLazyLoadMetadata()); - } - else { - if(!this.value || !this.columns) { - return; - } - - this.filteredValue = []; - - for(let i = 0; i < this.value.length; i++) { - let localMatch = true; - let globalMatch = false; - - for(let j = 0; j < this.columns.length; j++) { - let col = this.columns[j], - filterMeta = this.filters[col.filterField||col.field]; - - //local - if(filterMeta) { - let filterValue = filterMeta.value, - filterField = col.filterField||col.field, - filterMatchMode = filterMeta.matchMode||'startsWith', - dataFieldValue = this.resolveFieldData(this.value[i], filterField); - let filterConstraint = this.filterConstraints[filterMatchMode]; - - if(!filterConstraint(dataFieldValue, filterValue)) { - localMatch = false; - } - - if(!localMatch) { - break; - } - } - - //global - if(!col.excludeGlobalFilter && this.globalFilter && !globalMatch) { - globalMatch = this.filterConstraints['contains'](this.resolveFieldData(this.value[i], col.filterField||col.field), this.globalFilter.value); - } - } - - let matches = localMatch; - if(this.globalFilter) { - matches = localMatch&&globalMatch; - } - - if(matches) { - this.filteredValue.push(this.value[i]); - } - } - - if(this.filteredValue.length === this.value.length) { - this.filteredValue = null; - } - - if(this.paginator) { - this.totalRecords = this.filteredValue ? this.filteredValue.length: this.value ? this.value.length: 0; - } - - this.updateDataToRender(this.filteredValue||this.value); - } - - this.onFilter.emit({ - filters: this.filters, - filteredValue: this.filteredValue||this.value - }); - } - - hasFilter() { - let empty = true; - for(let prop in this.filters) { - if(this.filters.hasOwnProperty(prop)) { - empty = false; - break; - } - } - - return !empty || (this.globalFilter && this.globalFilter.value && this.globalFilter.value.trim().length); - } - - onFilterInputClick(event) { - event.stopPropagation(); - } - - filterConstraints = { - - startsWith(value, filter): boolean { - if(filter === undefined || filter === null || filter.trim() === '') { - return true; - } - - if(value === undefined || value === null) { - return false; - } - - let filterValue = filter.toLowerCase(); - return value.toString().toLowerCase().slice(0, filterValue.length) === filterValue; - }, - - contains(value, filter): boolean { - if(filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) { - return true; - } - - if(value === undefined || value === null) { - return false; - } - - return value.toString().toLowerCase().indexOf(filter.toLowerCase()) !== -1; - }, - - endsWith(value, filter): boolean { - if(filter === undefined || filter === null || filter.trim() === '') { - return true; - } - - if(value === undefined || value === null) { - return false; - } - - let filterValue = filter.toString().toLowerCase(); - return value.toString().toLowerCase().indexOf(filterValue, value.toString().length - filterValue.length) !== -1; - }, - - equals(value, filter): boolean { - if(filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) { - return true; - } - - if(value === undefined || value === null) { - return false; - } - - return value.toString().toLowerCase() == filter.toString().toLowerCase(); - }, - - notEquals(value, filter): boolean { - if(filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) { - return false; - } - - if(value === undefined || value === null) { - return true; - } - - return value.toString().toLowerCase() != filter.toString().toLowerCase(); - }, - - in(value, filter: any[]): boolean { - if(filter === undefined || filter === null || filter.length === 0) { - return true; - } - - if(value === undefined || value === null) { - return false; - } - - for(let i = 0; i < filter.length; i++) { - if(filter[i] === value) - return true; - } - - return false; - } - } - - switchCellToEditMode(cell: any, column: Column, rowData: any) { - if(!this.selectionMode && this.editable && column.editable) { - this.editorClick = true; - this.bindDocumentEditListener(); - - if(cell != this.editingCell) { - if(this.editingCell && this.domHandler.find(this.editingCell, '.ng-invalid.ng-dirty').length == 0) { - this.domHandler.removeClass(this.editingCell, 'ui-cell-editing'); - } - - this.editingCell = cell; - this.onEditInit.emit({column: column, data: rowData}); - this.domHandler.addClass(cell, 'ui-cell-editing'); - let focusable = this.domHandler.findSingle(cell, '.ui-cell-editor input, .ui-cell-editor textarea'); - if(focusable) { - setTimeout(() => this.domHandler.invokeElementMethod(focusable, 'focus'), 50); - } - } - } - } - - switchCellToViewMode(element: any) { - this.editingCell = null; - let cell = this.findCell(element); - this.domHandler.removeClass(cell, 'ui-cell-editing'); - this.unbindDocumentEditListener(); - } - - closeCell() { - if(this.editingCell) { - this.domHandler.removeClass(this.editingCell, 'ui-cell-editing'); - this.editingCell = null; - this.unbindDocumentEditListener(); - } - } - - bindDocumentEditListener() { - if(!this.documentEditListener) { - this.documentEditListener = this.renderer.listen('document', 'click', (event) => { - if(!this.editorClick) { - this.closeCell(); - } - this.editorClick = false; - }); - } - } - - unbindDocumentEditListener() { - if(this.documentEditListener) { - this.documentEditListener(); - this.documentEditListener = null; - } - } - - onCellEditorKeydown(event, column: Column, rowData: any, rowIndex: number) { - if(this.editable) { - //enter - if(event.keyCode == 13) { - if(this.domHandler.find(this.editingCell, '.ng-invalid.ng-dirty').length == 0) { - this.switchCellToViewMode(event.target); - event.preventDefault(); - } - } - - //escape - else if(event.keyCode == 27) { - this.switchCellToViewMode(event.target); - event.preventDefault(); - } - - //tab - else if(event.keyCode == 9) { - if(event.shiftKey) - this.moveToPreviousCell(event); - else - this.moveToNextCell(event); - } - } - } - - onCellEditorInput(event, column: Column, rowData: any, rowIndex: number) { - if(this.editable) { - this.onEdit.emit({originalEvent: event, column: column, data: rowData, index: rowIndex}); - } - } - - onCellEditorChange(event, column: Column, rowData: any, rowIndex: number) { - if(this.editable) { - this.editChanged = true; - - this.onEditComplete.emit({column: column, data: rowData, index: rowIndex}); - } - } - - onCellEditorBlur(event, column: Column, rowData: any, rowIndex: number) { - if(this.editable) { - if(this.editChanged) - this.editChanged = false; - else - this.onEditCancel.emit({column: column, data: rowData, index: rowIndex}); - } - } - - moveToPreviousCell(event: KeyboardEvent) { - let currentCell = this.findCell(event.target); - let row = currentCell.parentElement; - let targetCell = this.findPreviousEditableColumn(currentCell); - - if(targetCell) { - this.domHandler.invokeElementMethod(targetCell, 'click'); - event.preventDefault(); - } - } - - moveToNextCell(event: KeyboardEvent) { - let currentCell = this.findCell(event.target); - let row = currentCell.parentElement; - let targetCell = this.findNextEditableColumn(currentCell); - - if(targetCell) { - this.domHandler.invokeElementMethod(targetCell, 'click'); - event.preventDefault(); - } - } - - findPreviousEditableColumn(cell: Element) { - let prevCell = cell.previousElementSibling; - - if(!prevCell) { - let previousRow = cell.parentElement.previousElementSibling; - if(previousRow) { - prevCell = previousRow.lastElementChild; - } - } - - if(prevCell) { - if(this.domHandler.hasClass(prevCell, 'ui-editable-column')) - return prevCell; - else - return this.findPreviousEditableColumn(prevCell); - } - else { - return null; - } - } - - findNextEditableColumn(cell: Element) { - let nextCell = cell.nextElementSibling; - - if(!nextCell) { - let nextRow = cell.parentElement.nextElementSibling; - if(nextRow) { - nextCell = nextRow.firstElementChild; - } - } - - if(nextCell) { - if(this.domHandler.hasClass(nextCell, 'ui-editable-column')) - return nextCell; - else - return this.findNextEditableColumn(nextCell); - } - else { - return null; - } - } - - onCustomEditorFocusPrev(event: KeyboardEvent) { - this.moveToPreviousCell(event); - } - - onCustomEditorFocusNext(event: KeyboardEvent) { - this.moveToNextCell(event); - } - - findCell(element) { - if(element) { - let cell = element; - while(cell && cell.tagName != 'TD') { - cell = cell.parentElement; - } - - return cell; - } - else { - return null; - } - } - - initResizableColumns() { - this.tbody = this.domHandler.findSingle(this.el.nativeElement, 'tbody.ui-datatable-data'); - this.resizerHelper = this.domHandler.findSingle(this.el.nativeElement, 'div.ui-column-resizer-helper'); - this.fixColumnWidths(); - } - - onDocumentMouseMove(event) { - if(this.columnResizing) { - this.onColumnResize(event); - } - } - - onDocumentMouseUp(event) { - if(this.columnResizing) { - this.columnResizing = false; - this.onColumnResizeEnd(event); - } - } - - bindColumnResizeEvents() { - this.zone.runOutsideAngular(() => { - window.document.addEventListener('mousemove', this.onDocumentMouseMove.bind(this)); - }); - - this.documentColumnResizeEndListener = this.renderer.listen('document', 'mouseup', (event) => { - if(this.columnResizing) { - this.columnResizing = false; - this.onColumnResizeEnd(event); - } - }); - } - - unbindColumnResizeEvents() { - window.document.removeEventListener('mousemove', this.onDocumentMouseMove); - - if(this.documentColumnResizeEndListener) { - this.documentColumnResizeEndListener(); - this.documentColumnResizeEndListener = null; - } - } - - initColumnResize(event) { - this.bindColumnResizeEvents(); - - let container = this.el.nativeElement.children[0]; - let containerLeft = this.domHandler.getOffset(container).left; - this.resizeColumn = event.target.parentElement; - this.columnResizing = true; - this.lastResizerHelperX = (event.pageX - containerLeft + container.scrollLeft); - } - - onColumnResize(event) { - let container = this.el.nativeElement.children[0]; - let containerLeft = this.domHandler.getOffset(container).left; - this.domHandler.addClass(container, 'ui-unselectable-text'); - this.resizerHelper.style.height = container.offsetHeight + 'px'; - this.resizerHelper.style.top = 0 + 'px'; - this.resizerHelper.style.left = (event.pageX - containerLeft + container.scrollLeft) + 'px'; - - this.resizerHelper.style.display = 'block'; - } - - onColumnResizeEnd(event) { - let delta = this.resizerHelper.offsetLeft - this.lastResizerHelperX; - let columnWidth = this.resizeColumn.offsetWidth; - let newColumnWidth = columnWidth + delta; - let minWidth = this.resizeColumn.style.minWidth||15; - - if(columnWidth + delta > parseInt(minWidth)) { - if(this.columnResizeMode === 'fit') { - let nextColumn = this.resizeColumn.nextElementSibling; - while (this.domHandler.hasClass(nextColumn, 'ui-helper-hidden')) { - nextColumn = nextColumn.nextElementSibling; - } - - if(nextColumn) { - let nextColumnWidth = nextColumn.offsetWidth - delta; - let nextColumnMinWidth = nextColumn.style.minWidth || 15; - - if (newColumnWidth > 15 && nextColumnWidth > parseInt(nextColumnMinWidth)) { - this.resizeColumn.style.width = newColumnWidth + 'px'; - if (nextColumn) { - nextColumn.style.width = nextColumnWidth + 'px'; - } - - if (this.scrollable) { - let colGroup = this.domHandler.findSingle(this.el.nativeElement, 'colgroup.ui-datatable-scrollable-colgroup'); - let resizeColumnIndex = this.domHandler.index(this.resizeColumn); - colGroup.children[resizeColumnIndex].style.width = newColumnWidth + 'px'; - - if (nextColumn) { - colGroup.children[resizeColumnIndex + 1].style.width = nextColumnWidth + 'px'; - } - } - } - } - } - else if(this.columnResizeMode === 'expand') { - this.tbody.parentElement.style.width = this.tbody.parentElement.offsetWidth + delta + 'px'; - this.resizeColumn.style.width = newColumnWidth + 'px'; - let containerWidth = this.tbody.parentElement.style.width; - - if(this.scrollable) { - this.domHandler.findSingle(this.el.nativeElement, '.ui-datatable-scrollable-header-box').children[0].style.width = containerWidth; - let colGroup = this.domHandler.findSingle(this.el.nativeElement, 'colgroup.ui-datatable-scrollable-colgroup'); - let resizeColumnIndex = this.domHandler.index(this.resizeColumn); - colGroup.children[resizeColumnIndex].style.width = newColumnWidth + 'px'; - } - else { - this.el.nativeElement.children[0].style.width = containerWidth; - } - } - - this.onColResize.emit({ - element: this.resizeColumn, - delta: delta - }); - } - - this.resizerHelper.style.display = 'none'; - this.resizeColumn = null; - this.domHandler.removeClass(this.el.nativeElement.children[0], 'ui-unselectable-text'); - this.unbindColumnResizeEvents(); - } - - fixColumnWidths() { - let columns = this.domHandler.find(this.el.nativeElement, 'th.ui-resizable-column'); - let bodyCols; - - for(let i = 0; i < columns.length; i++) { - columns[i].style.width = columns[i].offsetWidth + 'px'; - } - - if(this.scrollable) { - let colGroup = this.domHandler.findSingle(this.el.nativeElement, 'colgroup.ui-datatable-scrollable-colgroup'); - bodyCols = colGroup.children; - - if(bodyCols) { - for (let i = 0; i < bodyCols.length; i++) { - bodyCols[i].style.width = columns[i].offsetWidth + 'px'; - } - } - } - } - - onColumnDragStart(event) { - if (this.columnResizing) { - event.preventDefault(); - return; - } - - this.draggedColumn = this.findParentHeader(event.target); - event.dataTransfer.setData('text', 'b'); // Firefox requires this to make dragging possible - this.zone.runOutsideAngular(() => { - window.document.addEventListener('dragover', this.onColumnDragover.bind(this)); - }); - } - - onColumnDragover(event) { - let dropHeader = this.findParentHeader(event.target); - if(this.reorderableColumns && this.draggedColumn && dropHeader) { - event.preventDefault(); - let container = this.el.nativeElement.children[0]; - let containerOffset = this.domHandler.getOffset(container); - let dropHeaderOffset = this.domHandler.getOffset(dropHeader); - - if(this.draggedColumn != dropHeader) { - let targetLeft = dropHeaderOffset.left - containerOffset.left; - let targetTop = containerOffset.top - dropHeaderOffset.top; - let columnCenter = dropHeaderOffset.left + dropHeader.offsetWidth / 2; - - this.reorderIndicatorUp.style.top = dropHeaderOffset.top - containerOffset.top - (this.iconHeight - 1) + 'px'; - this.reorderIndicatorDown.style.top = dropHeaderOffset.top - containerOffset.top + dropHeader.offsetHeight + 'px'; - - if(event.pageX > columnCenter) { - this.reorderIndicatorUp.style.left = (targetLeft + dropHeader.offsetWidth - Math.ceil(this.iconWidth / 2)) + 'px'; - this.reorderIndicatorDown.style.left = (targetLeft + dropHeader.offsetWidth - Math.ceil(this.iconWidth / 2))+ 'px'; - this.dropPosition = 1; - } - else { - this.reorderIndicatorUp.style.left = (targetLeft - Math.ceil(this.iconWidth / 2)) + 'px'; - this.reorderIndicatorDown.style.left = (targetLeft - Math.ceil(this.iconWidth / 2))+ 'px'; - this.dropPosition = -1; - } - - this.reorderIndicatorUp.style.display = 'block'; - this.reorderIndicatorDown.style.display = 'block'; - } - else { - event.dataTransfer.dropEffect = 'none'; - } - } - } - - onColumnDragleave(event) { - if(this.reorderableColumns && this.draggedColumn) { - event.preventDefault(); - this.reorderIndicatorUp.style.display = 'none'; - this.reorderIndicatorDown.style.display = 'none'; - window.document.removeEventListener('dragover', this.onColumnDragover); - } - } - - onColumnDrop(event) { - event.preventDefault(); - if(this.draggedColumn) { - let dragIndex = this.domHandler.index(this.draggedColumn); - let dropIndex = this.domHandler.index(this.findParentHeader(event.target)); - let allowDrop = (dragIndex != dropIndex); - if(allowDrop && ((dropIndex - dragIndex == 1 && this.dropPosition === -1) || (dragIndex - dropIndex == 1 && this.dropPosition === 1))) { - allowDrop = false; - } - - if(allowDrop) { - this.objectUtils.reorderArray(this.columns, dragIndex, dropIndex); - if(this.scrollable) { - this.initScrollableColumns(); - } - - this.onColReorder.emit({ - dragIndex: dragIndex, - dropIndex: dropIndex, - columns: this.columns - }); - } - - this.reorderIndicatorUp.style.display = 'none'; - this.reorderIndicatorDown.style.display = 'none'; - this.draggedColumn.draggable = false; - this.draggedColumn = null; - this.dropPosition = null; - } - } - - initColumnReordering() { - this.reorderIndicatorUp = this.domHandler.findSingle(this.el.nativeElement.children[0], 'span.ui-datatable-reorder-indicator-up'); - this.reorderIndicatorDown = this.domHandler.findSingle(this.el.nativeElement.children[0], 'span.ui-datatable-reorder-indicator-down'); - this.iconWidth = this.domHandler.getHiddenElementOuterWidth(this.reorderIndicatorUp); - this.iconHeight = this.domHandler.getHiddenElementOuterHeight(this.reorderIndicatorUp); - } - - findParentHeader(element) { - if(element.nodeName == 'TH') { - return element; - } - else { - let parent = element.parentElement; - while(parent.nodeName != 'TH') { - parent = parent.parentElement; - if(!parent) break; - } - return parent; - } - } - - hasFooter() { - if(this.footerColumnGroups && this.footerColumnGroups.first) { - return true; - } - else { - if(this.columns) { - for(let i = 0; i < this.columns.length; i++) { - if(this.columns[i].footer || this.columns[i].footerTemplate) { - return true; - } - } - } - - } - return false; - } - - isEmpty() { - return !this.dataToRender||(this.dataToRender.length == 0); - } - - createLazyLoadMetadata(): LazyLoadEvent { - return { - first: this.first, - rows: this.virtualScroll ? this.rows * 2 : this.rows, - sortField: this.sortField, - sortOrder: this.sortOrder, - filters: this.filters, - globalFilter: this.globalFilter ? this.globalFilter.value : null, - multiSortMeta: this.multiSortMeta - }; - } - - toggleRow(row: any, event?: Event) { - if(!this.expandedRows) { - this.expandedRows = []; - } - - let expandedRowIndex = this.findExpandedRowIndex(row); - - if(expandedRowIndex != -1) { - this.expandedRows.splice(expandedRowIndex, 1); - this.onRowCollapse.emit({ - originalEvent: event, - data: row - }); - } - else { - if(this.rowExpandMode === 'single') { - this.expandedRows = []; - } - - this.expandedRows.push(row); - this.onRowExpand.emit({ - originalEvent: event, - data: row - }); - } - - if(event) { - event.preventDefault(); - } - } - - findExpandedRowIndex(row: any): number { - let index = -1; - if(this.expandedRows) { - for(let i = 0; i < this.expandedRows.length; i++) { - if(this.expandedRows[i] == row) { - index = i; - break; - } - } - } - return index; - } - - isRowExpanded(row: any): boolean { - return this.findExpandedRowIndex(row) != -1; - } - - findExpandedRowGroupIndex(row: any): number { - let index = -1; - if(this.expandedRowsGroups && this.expandedRowsGroups.length) { - for(let i = 0; i < this.expandedRowsGroups.length; i++) { - let group = this.expandedRowsGroups[i]; - let rowGroupField = this.resolveFieldData(row, this.groupField); - if(rowGroupField === group) { - index = i; - break; - } - } - } - return index; - } - - isRowGroupExpanded(row: any): boolean { - return this.findExpandedRowGroupIndex(row) != -1; - } - - toggleRowGroup(event: Event, row: any): void { - - if(!this.expandedRowsGroups) { - this.expandedRowsGroups = []; - } - - this.rowGroupToggleClick = true; - let index = this.findExpandedRowGroupIndex(row); - let rowGroupField = this.resolveFieldData(row, this.groupField); - if(index >= 0) { - this.expandedRowsGroups.splice(index, 1); - this.onRowGroupCollapse.emit({ - originalEvent: event, - group: rowGroupField - }); - } - else { - - if(this.rowGroupExpandMode === 'single') { - this.expandedRowsGroups = []; - } - - this.expandedRowsGroups.push(rowGroupField); - this.onRowGroupExpand.emit({ - originalEvent: event, - group: rowGroupField - }); - } - event.preventDefault(); - } - - public reset() { - this._sortField = null; - this._sortOrder = 1; - - this.filteredValue = null; - this.filters = {}; - - this._first = 0; - this.firstChange.emit(this._first); - this.updateTotalRecords(); - - if(this.lazy) - this.onLazyLoad.emit(this.createLazyLoadMetadata()); - else - this.updateDataToRender(this.value); - } - - public exportCSV(options?:any) { - let data = this.filteredValue||this.value; - let csv = '\ufeff'; - - if(options && options.selectionOnly) { - data = this.selection||[]; - } - - //headers - for(let i = 0; i < this.columns.length; i++) { - let column = this.columns[i]; - if(column.exportable && column.field) { - csv += '"' + (column.header || column.field) + '"'; - - if(i < (this.columns.length - 1)) { - csv += this.csvSeparator; - } - } - } - - //body - data.forEach((record, i) => { - csv += '\n'; - for(let i = 0; i < this.columns.length; i++) { - let column = this.columns[i]; - if(column.exportable && column.field) { - let cellData = this.resolveFieldData(record, column.field); - - if(cellData != null) - cellData = String(cellData).replace(/"/g, '""'); - else - cellData = ''; - - csv += '"' + cellData + '"'; - - if(i < (this.columns.length - 1)) { - csv += this.csvSeparator; - } - } - } - }); - - let blob = new Blob([csv],{ - type: 'text/csv;charset=utf-8;' - }); - - if(window.navigator.msSaveOrOpenBlob) { - navigator.msSaveOrOpenBlob(blob, this.exportFilename + '.csv'); - } - else { - let link = document.createElement("a"); - link.style.display = 'none'; - document.body.appendChild(link); - if(link.download !== undefined) { - link.setAttribute('href', URL.createObjectURL(blob)); - link.setAttribute('download', this.exportFilename + '.csv'); - link.click(); - } - else { - csv = 'data:text/csv;charset=utf-8,' + csv; - window.open(encodeURI(csv)); - } - document.body.removeChild(link); - } - } - - getBlockableElement(): HTMLElement { - return this.el.nativeElement.children[0]; - } - - getRowStyleClass(rowData: any, rowIndex: number) { - let styleClass = 'ui-widget-content'; - if(this.rowStyleClass) { - let rowClass = this.rowStyleClass.call(this, rowData, rowIndex); - if(rowClass) { - styleClass += ' ' + rowClass; - } - } - else if (this.rowStyleMap && this.dataKey) { - let rowClass = this.rowStyleMap[rowData[this.dataKey]]; - if (rowClass) { - styleClass += ' ' + rowClass; - } - } - - return styleClass; - } - - visibleColumns() { - return this.columns ? this.columns.filter(c => !c.hidden): []; - } - - get containerWidth() { - if(this.scrollable) { - if(this.scrollWidth) { - return this.scrollWidth; - } - else if(this.frozenWidth && this.unfrozenWidth) { - return parseFloat(this.frozenWidth) + parseFloat(this.unfrozenWidth) + 'px'; - } - } - else { - return this.style ? this.style.width : null; - } - } - - hasFrozenColumns() { - return this.frozenColumns && this.frozenColumns.length > 0; - } - - ngOnDestroy() { - //remove event listener - if(this.globalFilterFunction) { - this.globalFilterFunction(); - } - - if(this.resizableColumns) { - this.unbindColumnResizeEvents(); - } - - this.unbindDocumentEditListener(); - - if(this.columnsSubscription) { - this.columnsSubscription.unsubscribe(); - } - - if(this.virtualScrollCallback) { - this.virtualScrollCallback = null; - } - } -} - -@NgModule({ - imports: [CommonModule,SharedModule,PaginatorModule,FormsModule], - exports: [DataTable,SharedModule], - declarations: [DataTable,DTRadioButton,DTCheckbox,ColumnHeaders,ColumnFooters,TableBody,ScrollableView] -}) -export class DataTableModule { } diff --git a/dashboard/src/app/components/dataview/dataview.css b/dashboard/src/app/components/dataview/dataview.css deleted file mode 100644 index c811ae704..000000000 --- a/dashboard/src/app/components/dataview/dataview.css +++ /dev/null @@ -1,37 +0,0 @@ -.ui-dataview .ui-paginator { - text-align: center; -} - -.ui-dataview-column { - padding: .25em; -} - -.ui-dataview-content-empty { - padding: .25em .625em; -} - -.ui-dataview .ui-dataview-header, -.ui-dataview .ui-dataview-footer { - padding: .5em .75em; -} - -.ui-dataview .ui-dataview-header { - border-bottom: 0 none; -} - -.ui-dataview .ui-dataview-footer { - border-top: 0 none; -} - -.ui-dataview .ui-paginator-top { - border-bottom: 0 none; -} - -.ui-dataview .ui-paginator-bottom { - border-top: 0 none; -} - -.ui-dataview.ui-dataview-list > .ui-dataview-content > div.ui-g > div { - width: 100%; -} - diff --git a/dashboard/src/app/components/dataview/dataview.ts b/dashboard/src/app/components/dataview/dataview.ts deleted file mode 100644 index 40689c85d..000000000 --- a/dashboard/src/app/components/dataview/dataview.ts +++ /dev/null @@ -1,293 +0,0 @@ -import {NgModule,Component,ElementRef,OnInit,AfterContentInit,DoCheck,OnDestroy,Input,Output,SimpleChange,EventEmitter,ContentChild,ContentChildren,QueryList,TemplateRef} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {ObjectUtils} from '../utils/objectutils'; -import {Header,Footer,PrimeTemplate,SharedModule} from '../common/shared'; -import {PaginatorModule} from '../paginator/paginator'; -import {BlockableUI} from '../common/blockableui'; -import {SelectItem} from '../common/selectitem'; - -@Component({ - selector: 'p-dataView', - template: ` -
-
- -
- -
-
- - - -
{{emptyMessage}}
-
-
- - -
- `, - providers: [ObjectUtils] -}) -export class DataView implements OnInit,AfterContentInit,BlockableUI { - - @Input() layout: string = 'list'; - - @Input() paginator: boolean; - - @Input() rows: number; - - @Input() totalRecords: number; - - @Input() pageLinks: number = 5; - - @Input() rowsPerPageOptions: number[]; - - @Input() paginatorPosition: string = 'bottom'; - - @Input() alwaysShowPaginator: boolean = true; - - @Input() paginatorDropdownAppendTo: any; - - @Input() lazy: boolean; - - @Input() emptyMessage: string = 'No records found'; - - @Output() onLazyLoad: EventEmitter = new EventEmitter(); - - @Input() style: any; - - @Input() styleClass: string; - - @Input() trackBy: Function = (index: number, item: any) => item; - - @Input() filterBy: string; - - @Output() onPage: EventEmitter = new EventEmitter(); - - @Output() onSort: EventEmitter = new EventEmitter(); - - @ContentChild(Header) header; - - @ContentChild(Footer) footer; - - @ContentChildren(PrimeTemplate) templates: QueryList; - - _value: any[]; - - listItemTemplate: TemplateRef; - - gridItemTemplate: TemplateRef; - - itemTemplate: TemplateRef; - - first: number = 0; - - filteredValue: any[]; - - _sortField: string; - - _sortOrder: number = 1; - - initialized: boolean; - - constructor(public el: ElementRef, public objectUtils: ObjectUtils) {} - - ngOnInit() { - if(this.lazy) { - this.onLazyLoad.emit(this.createLazyLoadMetadata()); - } - this.initialized = true; - } - - @Input() get sortField(): string { - return this._sortField; - } - - set sortField(val: string) { - this._sortField = val; - - //avoid triggering lazy load prior to lazy initialization at onInit - if ( !this.lazy || this.initialized ) { - this.sort(); - } - } - - @Input() get sortOrder(): number { - return this._sortOrder; - } - set sortOrder(val: number) { - this._sortOrder = val; - - //avoid triggering lazy load prior to lazy initialization at onInit - if ( !this.lazy || this.initialized ) { - this.sort(); - } - } - - ngAfterContentInit() { - this.templates.forEach((item) => { - switch(item.getType()) { - case 'listItem': - this.listItemTemplate = item.template; - break; - - case 'gridItem': - this.gridItemTemplate = item.template; - break; - } - }); - - this.updateItemTemplate(); - } - - updateItemTemplate() { - switch(this.layout) { - case 'list': - this.itemTemplate = this.listItemTemplate; - break; - - case 'grid': - this.itemTemplate = this.gridItemTemplate; - break; - } - } - - @Input() get value(): any[] { - return this._value; - } - - set value(val:any[]) { - this._value = val; - this.updateTotalRecords(); - } - - changeLayout(layout: string) { - this.layout = layout; - this.updateItemTemplate(); - } - - updateTotalRecords() { - this.totalRecords = this.lazy ? this.totalRecords : (this._value ? this._value.length : 0); - } - - paginate(event) { - this.first = event.first; - this.rows = event.rows; - - if (this.lazy) { - this.onLazyLoad.emit(this.createLazyLoadMetadata()); - } - - this.onPage.emit({ - first: this.first, - rows: this.rows - }); - } - - sort() { - this.first = 0; - - if(this.lazy) { - this.onLazyLoad.emit(this.createLazyLoadMetadata()); - } - else if (this.value) { - this.value.sort((data1, data2) => { - let value1 = this.objectUtils.resolveFieldData(data1, this.sortField); - let value2 = this.objectUtils.resolveFieldData(data2, this.sortField); - let result = null; - - if (value1 == null && value2 != null) - result = -1; - else if (value1 != null && value2 == null) - result = 1; - else if (value1 == null && value2 == null) - result = 0; - else if (typeof value1 === 'string' && typeof value2 === 'string') - result = value1.localeCompare(value2); - else - result = (value1 < value2) ? -1 : (value1 > value2) ? 1 : 0; - - return (this.sortOrder * result); - }); - } - - this.onSort.emit({ - sortField: this.sortField, - sortOrder: this.sortOrder - }); - } - - isEmpty() { - let data = this.filteredValue||this.value; - return data == null || data.length == 0; - } - - createLazyLoadMetadata(): any { - return { - first: this.first, - rows: this.rows - }; - } - - getBlockableElement(): HTMLElement { - return this.el.nativeElement.children[0]; - } - - filter(value: string) { - if (this.value && this.value.length) { - let searchFields = this.filterBy.split(','); - this.filteredValue = this.objectUtils.filter(this.value, searchFields, value); - - if (this.filteredValue.length === this.value.length ) { - this.filteredValue = null; - } - - if (this.paginator) { - this.totalRecords = this.filteredValue ? this.filteredValue.length : this.value ? this.value.length : 0; - } - } - - } -} - -@Component({ - selector: 'p-dataViewLayoutOptions', - template: ` - - ` -}) -export class DataViewLayoutOptions { - - @Input() style: any; - - @Input() styleClass: string; - - constructor(public dv: DataView) {} - - changeLayout(event: Event, layout: string) { - this.dv.changeLayout(layout); - event.preventDefault(); - } -} -@NgModule({ - imports: [CommonModule,SharedModule,PaginatorModule], - exports: [DataView,SharedModule,DataViewLayoutOptions], - declarations: [DataView,DataViewLayoutOptions] -}) -export class DataViewModule { } diff --git a/dashboard/src/app/components/defer/defer.ts b/dashboard/src/app/components/defer/defer.ts deleted file mode 100644 index c90e31ed9..000000000 --- a/dashboard/src/app/components/defer/defer.ts +++ /dev/null @@ -1,66 +0,0 @@ -import {NgModule,Directive,ElementRef,AfterViewInit,OnDestroy,Input,TemplateRef,EmbeddedViewRef, - ViewContainerRef,Renderer2,EventEmitter,Output,ContentChild} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; - -@Directive({ - selector: '[pDefer]', - host: { - }, - providers: [DomHandler] -}) -export class DeferredLoader implements AfterViewInit,OnDestroy { - - @Output() onLoad: EventEmitter = new EventEmitter(); - - @ContentChild(TemplateRef) template: TemplateRef; - - documentScrollListener: Function; - - view: EmbeddedViewRef; - - constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2, public viewContainer: ViewContainerRef) {} - - ngAfterViewInit() { - if(this.shouldLoad()) { - this.load(); - } - - this.documentScrollListener = this.renderer.listen('window', 'scroll', () => { - if(this.shouldLoad()) { - this.load(); - this.documentScrollListener(); - this.documentScrollListener = null; - } - }); - } - - shouldLoad(): boolean { - let rect = this.el.nativeElement.getBoundingClientRect(); - let docElement = document.documentElement; - let scrollTop = (window.pageYOffset||document.documentElement.scrollTop); - let winHeight = docElement.clientHeight; - - return (winHeight >= rect.top); - } - - load(): void { - this.view = this.viewContainer.createEmbeddedView(this.template); - this.onLoad.emit(); - } - - ngOnDestroy() { - this.view = null; - - if(this.documentScrollListener) { - this.documentScrollListener(); - } - } -} - -@NgModule({ - imports: [CommonModule], - exports: [DeferredLoader], - declarations: [DeferredLoader] -}) -export class DeferModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/dialog/dialog.scss b/dashboard/src/app/components/dialog/dialog.scss deleted file mode 100644 index a1832fa30..000000000 --- a/dashboard/src/app/components/dialog/dialog.scss +++ /dev/null @@ -1,165 +0,0 @@ -.ui-dialog { - position: fixed; - padding: 0; - background: #f3f6f7; - border: none; - box-shadow: 0px 5px 20px 0px rgba(0, 0, 0, 0.3); - @extend .ui-corner-all-small; -} - -.ui-dialog.ui-widget .ui-dialog-titlebar{ - padding: .3rem .4rem .2rem; - position: relative; - border: 0; - background: none; - @extend .ui-corner-top-small; - .ui-dialog-title{ - font-size: .24rem; - } -} - -.ui-dialog.ui-widget .ui-dialog-content { - position: relative; - border: 0; - padding: .1rem .4rem .3rem; - background: none; - overflow: auto; - zoom: 1; -} -.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { - float: right; -} - -.ui-dialog .ui-dialog-buttonpane button { - margin: .5em .4em .5em 0; - cursor: pointer; - float: right; -} -.ui-dialog .ui-resizable-se { - width: 14px; - height: 14px; - right: 3px; - bottom: 3px; -} -.ui-draggable .ui-dialog-titlebar { - cursor: move; -} -.ui-dialog .ui-dialog-titlebar-icon { - text-decoration: none -} -.ui-dialog .ui-dialog-titlebar-close { - float: right; - width: .24rem; - height: .24rem; - padding: .03rem .01rem 0.05rem; - margin: -.12rem -.22rem 0 0; - background: #9ba9b7; - cursor: pointer; - @extend .ui-corner-all-large; - &:hover{ - background: map-get($map: $color-primary, $key: hover); - box-shadow: 0px 4px 8px #e3e3e3; - } -} -.ui-dialog .ui-dialog-titlebar-close span { - display: block; - margin: 0; - color: #fff; - width: .22rem; - font-size: .14rem; - line-height: .16rem; -} - -.ui-dialog-footer { - padding: .18rem 0 .20rem 0; - text-align: center; - background: #e6edef; - @extend .ui-corner-bottom-small; -} -.ui-dialog .ui-dialog-footer { - border: none; -} - -.ui-dialog-mask { - position: fixed; - width: 100%; - height: 100%; -} - -/* ConfirmDialog */ -.ui-confirmdialog { - width: 5.00rem; -} - -.ui-confirmdialog.ui-dialog .ui-dialog-content { - display: flex; - display: -webkit-flex; - justify-content: flex-start; - align-items: center; -} -.ui-confirmdialog.ui-dialog .ui-dialog-content h3{ - margin-top: .10rem; -} -.ui-confirmdialog .ui-dialog-content .fa { - font-size: .48rem; - vertical-align: middle; - margin-right: .2rem; - color: #438bd3; -} -.ui-confirmdialog.ui-confirmdialog-warning .ui-dialog-content .fa { - color:#FF8833; -} - -/* Fluid */ -.ui-fluid .ui-dialog-footer .ui-button { - width: auto; -} - -/* RTL */ -.ui-rtl .ui-dialog .ui-dialog-titlebar-close { - float: left; -} - -.ui-rtl .ui-dialog .ui-dialog-buttonpane button { - text-align: right; -} - -@media screen and (max-width: 40em) { - .ui-confirmdialog { - width: 90%; - } -} - - - -/*增加msgBox样式*/ -.ui-dialog .ui-dialog-content .msgbox >div{ - display: table-cell; -} -.ui-dialog .ui-dialog-content .msgbox div:first-child{ - vertical-align: top; -} -.ui-dialog .ui-dialog-content .msgbox div:last-child{ - vertical-align: middle; - padding-left: 20px; -} -.ui-dialog .ui-dialog-content .msgbox .fa { - font-size: .48rem; - color: #438bd3; - &.error{ - color: #FF8833; - } - &.success{ - color: #3DCCA6; - } -} -.ui-dialog .ui-dialog-content .msgbox h3{ - margin-bottom: 5px; -} -.ui-dialog .ui-dialog-content .msgbox .success-title{ - color: #3DCCA6; -} -.ui-dialog .ui-dialog-content .msgbox .error-title{ - color: #FF8833; -} - diff --git a/dashboard/src/app/components/dialog/dialog.spec.ts b/dashboard/src/app/components/dialog/dialog.spec.ts deleted file mode 100644 index 39c13b21f..000000000 --- a/dashboard/src/app/components/dialog/dialog.spec.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { TestBed, ComponentFixture, fakeAsync, tick } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Dialog } from './dialog'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Dialog', () => { - - let dialog: Dialog; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Dialog - ] - }); - - fixture = TestBed.createComponent(Dialog); - dialog = fixture.componentInstance; - }); - - it('should display the header', () => { - dialog.header = 'PrimeNG Dialog Header'; - fixture.detectChanges(); - const headerEl = fixture.debugElement.query(By.css('.ui-dialog-title')); - expect(headerEl.nativeElement.textContent).toContain('PrimeNG Dialog Header') - }); - - it('should display close icon when closable', () => { - fixture.detectChanges(); - const closeEl = fixture.debugElement.query(By.css('.ui-dialog-titlebar-close')); - expect(closeEl).not.toBeNull(); - }); - - it('should display resizer when resizable', () => { - fixture.detectChanges(); - const resizeEl = fixture.debugElement.query(By.css('.ui-resizable-handle')); - expect(resizeEl).not.toBeNull(); - }); - - it('should be hidden by default', () => { - fixture.detectChanges(); - expect(fixture.debugElement.children[0].styles.display).toEqual('none'); - }); - - it('should add rtl class when rtl is enabled', () => { - dialog.rtl = true; - fixture.detectChanges(); - expect(fixture.debugElement.children[0].classes['ui-dialog-rtl']).toEqual(true); - }); - - it('should add draggable class when dragging is enabled', () => { - fixture.detectChanges(); - expect(fixture.debugElement.children[0].classes['ui-dialog-draggable']).toEqual(true); - }); - - it('should show the dialog when visible is true', () => { - spyOn(dialog, 'show'); - dialog.visible = true; - fixture.detectChanges(); - expect(fixture.debugElement.children[0].styles.display).toEqual('block'); - expect(dialog.show).toHaveBeenCalled(); - }); - - it('should call hide if visible is true and dialog gets hidden', () => { - dialog.visible = true; - fixture.detectChanges(); - - spyOn(dialog, 'hide'); - dialog.visible = false; - fixture.detectChanges(); - - expect(fixture.debugElement.children[0].styles.display).toEqual('none'); - expect(dialog.hide).toHaveBeenCalled(); - }); - - it('should update visible as false binding when close icon is clicked', () => { - let show = true; - dialog.visible = show; - fixture.detectChanges(); - dialog.visibleChange.subscribe(value => show = value); - - const closeEl = fixture.nativeElement.querySelector('.ui-dialog-titlebar-close'); - closeEl.click(); - - expect(show).toEqual(false); - }); - -}); diff --git a/dashboard/src/app/components/dialog/dialog.ts b/dashboard/src/app/components/dialog/dialog.ts deleted file mode 100644 index 6af43786a..000000000 --- a/dashboard/src/app/components/dialog/dialog.ts +++ /dev/null @@ -1,593 +0,0 @@ -import {NgModule,Component,ElementRef,AfterViewInit,AfterViewChecked,OnDestroy,Input,Output,EventEmitter,Renderer2, - ContentChildren,QueryList,ViewChild,NgZone} from '@angular/core'; -import {trigger,state,style,transition,animate} from '@angular/animations'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; -import {Header,Footer,SharedModule} from '../common/shared'; -import {ButtonModule } from '../button/button'; - -let idx: number = 0; - -@Component({ - selector: 'p-dialog', - template: ` -
-
- {{header}} - - - - - - -
-
- -
- - -
-
- `, - animations: [ - trigger('dialogState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]) - ], - providers: [DomHandler] -}) -export class Dialog implements AfterViewInit,AfterViewChecked,OnDestroy { - - @Input() header: string; - - @Input() draggable: boolean = true; - - @Input() resizable: boolean = true; - - @Input() minWidth: number = 150; - - @Input() minHeight: number = 150; - - @Input() width: any; - - @Input() height: any; - - @Input() positionLeft: number; - - @Input() positionTop: number; - - @Input() contentStyle: any; - - @Input() modal: boolean; - - @Input() closeOnEscape: boolean = true; - - @Input() dismissableMask: boolean; - - @Input() rtl: boolean; - - @Input() closable: boolean = true; - - @Input() responsive: boolean = true; - - @Input() isMsgBox: boolean = false; - - @Input() appendTo: any; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() showHeader: boolean = true; - - @Input() showCloseBtn: boolean = true; - - @Input() closeBtnLabel: string = "Close"; - - @Input() breakpoint: number = 640; - - @Input() blockScroll: boolean = false; - - @Input() autoZIndex: boolean = true; - - @Input() baseZIndex: number = 0; - - @Input() minX: number = 0; - - @Input() minY: number = 0; - - @Input() autoAlign: boolean = true; - - @ContentChildren(Header, {descendants: false}) headerFacet: QueryList
; - - @ContentChildren(Footer, {descendants: false}) footerFacet: QueryList
; - - @ViewChild('container') containerViewChild: ElementRef; - - @ViewChild('titlebar') headerViewChild: ElementRef; - - @ViewChild('content') contentViewChild: ElementRef; - - @Output() onShow: EventEmitter = new EventEmitter(); - - @Output() onHide: EventEmitter = new EventEmitter(); - - @Output() visibleChange:EventEmitter = new EventEmitter(); - - @Output() onOk: EventEmitter = new EventEmitter(); - - _visible: boolean; - - dragging: boolean; - - documentDragListener: any; - - documentDragEndListener: any; - - resizing: boolean; - - documentResizeListener: any; - - documentResizeEndListener: any; - - documentResponsiveListener: any; - - documentEscapeListener: Function; - - maskClickListener: Function; - - lastPageX: number; - - lastPageY: number; - - mask: HTMLDivElement; - - closeIconMouseDown: boolean; - - preWidth: number; - - preventVisibleChangePropagation: boolean; - - executePostDisplayActions: boolean; - - initialized: boolean; - - currentHeight: number; - - id: string = `ui-dialog-${idx++}`; - - constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2, public zone: NgZone) {} - - @Input() get visible(): boolean { - return this._visible; - } - - set visible(val:boolean) { - this._visible = val; - - if(this.initialized && this.containerViewChild && this.containerViewChild.nativeElement) { - if(this._visible) - this.show(); - else { - if(this.preventVisibleChangePropagation) - this.preventVisibleChangePropagation = false; - else - this.hide(); - } - } - } - - ngAfterViewChecked() { - if(this.executePostDisplayActions) { - this.onShow.emit({}); - this.positionOverlay(); - this.focus(); - this.currentHeight = this.domHandler.getOuterHeight(this.containerViewChild.nativeElement); - this.executePostDisplayActions = false; - } - else if(this.autoAlign && this.visible) { - this.zone.runOutsideAngular(() => { - setTimeout(() => { - let height = this.domHandler.getOuterHeight(this.containerViewChild.nativeElement); - - if(height !== this.currentHeight) { - this.currentHeight = height; - this.positionOverlay(); - } - }, 50); - }); - } - } - - focus() { - let focusable = this.domHandler.findSingle(this.containerViewChild.nativeElement, 'button'); - if(focusable) { - focusable.focus(); - } - } - - show() { - this.executePostDisplayActions = true; - this.moveOnTop(); - this.bindGlobalListeners(); - - if(this.modal) { - this.enableModality(); - } - } - - positionOverlay() { - let viewport = this.domHandler.getViewport(); - if(this.domHandler.getOuterHeight(this.containerViewChild.nativeElement) > viewport.height) { - this.contentViewChild.nativeElement.style.height = (viewport.height * .75) + 'px'; - } - - if(this.positionLeft >= 0 && this.positionTop >= 0) { - this.containerViewChild.nativeElement.style.left = this.positionLeft + 'px'; - this.containerViewChild.nativeElement.style.top = this.positionTop + 'px'; - } - else if (this.positionTop >= 0) { - this.center(); - this.containerViewChild.nativeElement.style.top = this.positionTop + 'px'; - } - else{ - this.center(); - } - } - - hide() { - this.onHide.emit({}); - this.unbindMaskClickListener(); - this.unbindGlobalListeners(); - this.dragging = false; - - if(this.modal) { - this.disableModality(); - } - } - - close(event: Event) { - this.preventVisibleChangePropagation = true; - this.hide(); - this.visibleChange.emit(false); - event.preventDefault(); - } - - ngAfterViewInit() { - this.initialized = true; - - if(this.appendTo) { - if(this.appendTo === 'body') - document.body.appendChild(this.containerViewChild.nativeElement); - else - this.domHandler.appendChild(this.containerViewChild.nativeElement, this.appendTo); - } - - if(this.visible) { - this.show(); - } - } - - center() { - let elementWidth = this.domHandler.getOuterWidth(this.containerViewChild.nativeElement); - let elementHeight = this.domHandler.getOuterHeight(this.containerViewChild.nativeElement); - if(elementWidth == 0 && elementHeight == 0) { - this.containerViewChild.nativeElement.style.visibility = 'hidden'; - this.containerViewChild.nativeElement.style.display = 'block'; - elementWidth = this.domHandler.getOuterWidth(this.containerViewChild.nativeElement); - elementHeight = this.domHandler.getOuterHeight(this.containerViewChild.nativeElement); - this.containerViewChild.nativeElement.style.display = 'none'; - this.containerViewChild.nativeElement.style.visibility = 'visible'; - } - let viewport = this.domHandler.getViewport(); - let x = Math.max((viewport.width - elementWidth) / 2, 0); - let y = Math.max((viewport.height - elementHeight) / 2, 0); - - this.containerViewChild.nativeElement.style.left = x + 'px'; - this.containerViewChild.nativeElement.style.top = y + 'px'; - } - - enableModality() { - if(!this.mask) { - this.mask = document.createElement('div'); - this.mask.style.zIndex = String(parseInt(this.containerViewChild.nativeElement.style.zIndex) - 1); - let maskStyleClass = 'ui-widget-overlay ui-dialog-mask'; - if(this.blockScroll) { - maskStyleClass += ' ui-dialog-mask-scrollblocker'; - } - this.domHandler.addMultipleClasses(this.mask, maskStyleClass); - - if(this.closable && this.dismissableMask) { - this.maskClickListener = this.renderer.listen(this.mask, 'click', (event: any) => { - this.close(event); - }); - } - document.body.appendChild(this.mask); - if(this.blockScroll) { - this.domHandler.addClass(document.body, 'ui-overflow-hidden'); - } - } - } - - disableModality() { - if(this.mask) { - document.body.removeChild(this.mask); - if(this.blockScroll) { - let bodyChildren = document.body.children; - let hasBlockerMasks: boolean; - for(let i = 0; i < bodyChildren.length; i++) { - let bodyChild = bodyChildren[i]; - if(this.domHandler.hasClass(bodyChild, 'ui-dialog-mask-scrollblocker')) { - hasBlockerMasks = true; - break; - } - } - - if(!hasBlockerMasks) { - this.domHandler.removeClass(document.body, 'ui-overflow-hidden'); - } - } - this.mask = null; - } - } - - unbindMaskClickListener() { - if(this.maskClickListener) { - this.maskClickListener(); - this.maskClickListener = null; - } - } - - moveOnTop() { - if(this.autoZIndex) { - this.containerViewChild.nativeElement.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex)); - } - } - - onCloseMouseDown(event: Event) { - this.closeIconMouseDown = true; - } - - initDrag(event: MouseEvent) { - if(this.closeIconMouseDown) { - this.closeIconMouseDown = false; - return; - } - - if(this.draggable) { - this.dragging = true; - this.lastPageX = event.pageX; - this.lastPageY = event.pageY; - this.domHandler.addClass(document.body, 'ui-unselectable-text'); - } - } - - onDrag(event: MouseEvent) { - if(this.dragging) { - let deltaX = event.pageX - this.lastPageX; - let deltaY = event.pageY - this.lastPageY; - let leftPos = parseInt(this.containerViewChild.nativeElement.style.left) + deltaX; - let topPos = parseInt(this.containerViewChild.nativeElement.style.top) + deltaY; - - if(leftPos >= this.minX) { - this.containerViewChild.nativeElement.style.left = leftPos + 'px'; - } - - if(topPos >= this.minY) { - this.containerViewChild.nativeElement.style.top = topPos + 'px'; - } - - this.lastPageX = event.pageX; - this.lastPageY = event.pageY; - } - } - - endDrag(event: MouseEvent) { - if(this.draggable) { - this.dragging = false; - this.domHandler.removeClass(document.body, 'ui-unselectable-text'); - } - } - - initResize(event: MouseEvent) { - if(this.resizable) { - this.preWidth = null; - this.resizing = true; - this.lastPageX = event.pageX; - this.lastPageY = event.pageY; - this.domHandler.addClass(document.body, 'ui-unselectable-text'); - } - } - - onResize(event: MouseEvent) { - if(this.resizing) { - let deltaX = event.pageX - this.lastPageX; - let deltaY = event.pageY - this.lastPageY; - let containerWidth = this.domHandler.getOuterWidth(this.containerViewChild.nativeElement); - let containerHeight = this.domHandler.getOuterHeight(this.containerViewChild.nativeElement); - let contentHeight = this.domHandler.getOuterHeight(this.contentViewChild.nativeElement); - let newWidth = containerWidth + deltaX; - let newHeight = containerHeight + deltaY; - - if(newWidth > this.minWidth) { - this.containerViewChild.nativeElement.style.width = newWidth + 'px'; - } - - if(newHeight > this.minHeight) { - this.containerViewChild.nativeElement.style.height = newHeight + 'px'; - this.contentViewChild.nativeElement.style.height = contentHeight + deltaY + 'px'; - } - - this.lastPageX = event.pageX; - this.lastPageY = event.pageY; - } - } - - ok(evt) { - this.onOk.emit(evt); - } - - onResizeEnd(event: MouseEvent) { - if(this.resizing) { - this.resizing = false; - this.domHandler.removeClass(document.body, 'ui-unselectable-text'); - } - } - - bindGlobalListeners() { - if(this.draggable) { - this.bindDocumentDragListener(); - this.bindDocumentDragEndListener(); - } - - if(this.resizable) { - this.bindDocumentResizeListeners(); - } - - if(this.responsive) { - this.bindDocumentResponsiveListener(); - } - - if(this.closeOnEscape && this.closable) { - this.bindDocumentEscapeListener(); - } - } - - unbindGlobalListeners() { - this.unbindDocumentDragListener(); - this.unbindDocumentDragEndListener(); - this.unbindDocumentResizeListeners(); - this.unbindDocumentResponsiveListener(); - this.unbindDocumentEscapeListener(); - } - - bindDocumentDragListener() { - this.zone.runOutsideAngular(() => { - this.documentDragListener = this.onDrag.bind(this); - window.document.addEventListener('mousemove', this.documentDragListener); - }); - } - - unbindDocumentDragListener() { - if(this.documentDragListener) { - window.document.removeEventListener('mousemove', this.documentDragListener); - this.documentDragListener = null; - } - } - - bindDocumentDragEndListener() { - this.zone.runOutsideAngular(() => { - this.documentDragEndListener = this.endDrag.bind(this); - window.document.addEventListener('mouseup', this.documentDragEndListener); - }); - } - - unbindDocumentDragEndListener() { - if(this.documentDragEndListener) { - window.document.removeEventListener('mouseup', this.documentDragEndListener); - this.documentDragEndListener = null; - } - } - - bindDocumentResizeListeners() { - this.zone.runOutsideAngular(() => { - this.documentResizeListener = this.onResize.bind(this); - this.documentResizeEndListener = this.onResizeEnd.bind(this); - window.document.addEventListener('mousemove', this.documentResizeListener); - window.document.addEventListener('mouseup', this.documentResizeEndListener); - }); - } - - unbindDocumentResizeListeners() { - if(this.documentResizeListener && this.documentResizeEndListener) { - window.document.removeEventListener('mouseup', this.documentResizeListener); - window.document.removeEventListener('mouseup', this.documentResizeEndListener); - this.documentResizeListener = null; - this.documentResizeEndListener = null; - } - } - - bindDocumentResponsiveListener() { - this.zone.runOutsideAngular(() => { - this.documentResponsiveListener = this.onWindowResize.bind(this); - window.addEventListener('resize', this.documentResponsiveListener); - }); - } - - unbindDocumentResponsiveListener() { - if(this.documentResponsiveListener) { - window.removeEventListener('resize', this.documentResponsiveListener); - this.documentResponsiveListener = null; - } - } - - onWindowResize(event) { - let viewport = this.domHandler.getViewport(); - let width = this.domHandler.getOuterWidth(this.containerViewChild.nativeElement); - if(viewport.width <= this.breakpoint) { - if(!this.preWidth) { - this.preWidth = width; - } - this.containerViewChild.nativeElement.style.left = '0px'; - this.containerViewChild.nativeElement.style.width = '100%'; - } - else { - this.containerViewChild.nativeElement.style.width = this.preWidth + 'px'; - this.positionOverlay(); - } - } - - bindDocumentEscapeListener() { - this.documentEscapeListener = this.renderer.listen('document', 'keydown', (event) => { - if(event.which == 27) { - if(parseInt(this.containerViewChild.nativeElement.style.zIndex) == DomHandler.zindex) { - this.close(event); - } - } - }); - } - - unbindDocumentEscapeListener() { - if(this.documentEscapeListener) { - this.documentEscapeListener(); - this.documentEscapeListener = null; - } - } - - ngOnDestroy() { - this.initialized = false; - - this.disableModality(); - - this.unbindGlobalListeners(); - - if(this.appendTo) { - this.el.nativeElement.appendChild(this.containerViewChild.nativeElement); - } - - this.unbindMaskClickListener(); - } - -} - -@NgModule({ - imports: [CommonModule, ButtonModule], - exports: [Dialog,SharedModule], - declarations: [Dialog] -}) -export class DialogModule { } diff --git a/dashboard/src/app/components/dom/domhandler.ts b/dashboard/src/app/components/dom/domhandler.ts deleted file mode 100644 index 82a232098..000000000 --- a/dashboard/src/app/components/dom/domhandler.ts +++ /dev/null @@ -1,468 +0,0 @@ -import { Injectable } from '@angular/core'; - -@Injectable() -export class DomHandler { - - public static zindex: number = 1000; - - private calculatedScrollbarWidth: number = null; - - private browser: any; - - public addClass(element: any, className: string): void { - if (element.classList) - element.classList.add(className); - else - element.className += ' ' + className; - } - - public addMultipleClasses(element: any, className: string): void { - if (element.classList) { - let styles: string[] = className.split(' '); - for (let i = 0; i < styles.length; i++) { - element.classList.add(styles[i]); - } - - } - else { - let styles: string[] = className.split(' '); - for (let i = 0; i < styles.length; i++) { - element.className += ' ' + styles[i]; - } - } - } - - public removeClass(element: any, className: string): void { - if (element.classList) - element.classList.remove(className); - else - element.className = element.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); - } - - public hasClass(element: any, className: string): boolean { - if (element.classList) - return element.classList.contains(className); - else - return new RegExp('(^| )' + className + '( |$)', 'gi').test(element.className); - } - - public siblings(element: any): any { - return Array.prototype.filter.call(element.parentNode.children, function (child) { - return child !== element; - }); - } - - public find(element: any, selector: string): any[] { - return element.querySelectorAll(selector); - } - - public findSingle(element: any, selector: string): any { - return element.querySelector(selector); - } - - public index(element: any): number { - let children = element.parentNode.childNodes; - let num = 0; - for (var i = 0; i < children.length; i++) { - if (children[i] == element) return num; - if (children[i].nodeType == 1) num++; - } - return -1; - } - - public indexWithinGroup(element: any, attributeName: string): number { - let children = element.parentNode.childNodes; - let num = 0; - for (var i = 0; i < children.length; i++) { - if (children[i] == element) return num; - if (children[i].attributes && children[i].attributes[attributeName] && children[i].nodeType == 1) num++; - } - return -1; - } - - public relativePosition(element: any, target: any): void { - let elementDimensions = element.offsetParent ? { width: element.offsetWidth, height: element.offsetHeight } : this.getHiddenElementDimensions(element); - let targetHeight = target.offsetHeight; - let targetWidth = target.offsetWidth; - let targetOffset = target.getBoundingClientRect(); - let windowScrollTop = this.getWindowScrollTop(); - let viewport = this.getViewport(); - let top, left; - - if ((targetOffset.top + targetHeight + elementDimensions.height) > viewport.height) { - top = -1 * (elementDimensions.height); - if(targetOffset.top + top < 0) { - top = 0; - } - } - else { - top = targetHeight; - } - - - if ((targetOffset.left + elementDimensions.width) > viewport.width) - left = targetWidth - elementDimensions.width; - else - left = 0; - - element.style.top = top + 'px'; - element.style.left = left + 'px'; - } - - public absolutePosition(element: any, target: any): void { - let elementDimensions = element.offsetParent ? { width: element.offsetWidth, height: element.offsetHeight } : this.getHiddenElementDimensions(element); - let elementOuterHeight = elementDimensions.height; - let elementOuterWidth = elementDimensions.width; - let targetOuterHeight = target.offsetHeight; - let targetOuterWidth = target.offsetWidth; - let targetOffset = target.getBoundingClientRect(); - let windowScrollTop = this.getWindowScrollTop(); - let windowScrollLeft = this.getWindowScrollLeft(); - let viewport = this.getViewport(); - let top, left; - - if (targetOffset.top + targetOuterHeight + elementOuterHeight > viewport.height) { - top = targetOffset.top + windowScrollTop - elementOuterHeight; - if(top < 0) { - top = 0 + windowScrollTop; - } - } - else { - top = targetOuterHeight + targetOffset.top + windowScrollTop; - } - - if (targetOffset.left + targetOuterWidth + elementOuterWidth > viewport.width) - left = targetOffset.left + windowScrollLeft + targetOuterWidth - elementOuterWidth; - else - left = targetOffset.left + windowScrollLeft; - - element.style.top = top + 'px'; - element.style.left = left + 'px'; - } - - public getHiddenElementOuterHeight(element: any): number { - element.style.visibility = 'hidden'; - element.style.display = 'block'; - let elementHeight = element.offsetHeight; - element.style.display = 'none'; - element.style.visibility = 'visible'; - - return elementHeight; - } - - public getHiddenElementOuterWidth(element: any): number { - element.style.visibility = 'hidden'; - element.style.display = 'block'; - let elementWidth = element.offsetWidth; - element.style.display = 'none'; - element.style.visibility = 'visible'; - - return elementWidth; - } - - public getHiddenElementDimensions(element: any): any { - let dimensions: any = {}; - element.style.visibility = 'hidden'; - element.style.display = 'block'; - dimensions.width = element.offsetWidth; - dimensions.height = element.offsetHeight; - element.style.display = 'none'; - element.style.visibility = 'visible'; - - return dimensions; - } - - public scrollInView(container, item) { - let borderTopValue: string = getComputedStyle(container).getPropertyValue('borderTopWidth'); - let borderTop: number = borderTopValue ? parseFloat(borderTopValue) : 0; - let paddingTopValue: string = getComputedStyle(container).getPropertyValue('paddingTop'); - let paddingTop: number = paddingTopValue ? parseFloat(paddingTopValue) : 0; - let containerRect = container.getBoundingClientRect(); - let itemRect = item.getBoundingClientRect(); - let offset = (itemRect.top + document.body.scrollTop) - (containerRect.top + document.body.scrollTop) - borderTop - paddingTop; - let scroll = container.scrollTop; - let elementHeight = container.clientHeight; - let itemHeight = this.getOuterHeight(item); - - if (offset < 0) { - container.scrollTop = scroll + offset; - } - else if ((offset + itemHeight) > elementHeight) { - container.scrollTop = scroll + offset - elementHeight + itemHeight; - } - } - - public fadeIn(element, duration: number): void { - element.style.opacity = 0; - - let last = +new Date(); - let opacity = 0; - let tick = function () { - opacity = +element.style.opacity.replace(",", ".") + (new Date().getTime() - last) / duration; - element.style.opacity = opacity; - last = +new Date(); - - if (+opacity < 1) { - (window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 16); - } - }; - - tick(); - } - - public fadeOut(element, ms) { - var opacity = 1, - interval = 50, - duration = ms, - gap = interval / duration; - - let fading = setInterval(() => { - opacity = opacity - gap; - - if (opacity <= 0) { - opacity = 0; - clearInterval(fading); - } - - element.style.opacity = opacity; - }, interval); - } - - public getWindowScrollTop(): number { - let doc = document.documentElement; - return (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0); - } - - public getWindowScrollLeft(): number { - let doc = document.documentElement; - return (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0); - } - - public matches(element, selector: string): boolean { - var p = Element.prototype; - var f = p['matches'] || p.webkitMatchesSelector || p['mozMatchesSelector'] || p.msMatchesSelector || function (s) { - return [].indexOf.call(document.querySelectorAll(s), this) !== -1; - }; - return f.call(element, selector); - } - - public getOuterWidth(el, margin?) { - let width = el.offsetWidth; - - if (margin) { - let style = getComputedStyle(el); - width += parseFloat(style.marginLeft) + parseFloat(style.marginRight); - } - - return width; - } - - public getHorizontalPadding(el) { - let style = getComputedStyle(el); - return parseFloat(style.paddingLeft) + parseFloat(style.paddingRight); - } - - public getHorizontalMargin(el) { - let style = getComputedStyle(el); - return parseFloat(style.marginLeft) + parseFloat(style.marginRight); - } - - public innerWidth(el) { - let width = el.offsetWidth; - let style = getComputedStyle(el); - - width += parseFloat(style.paddingLeft) + parseFloat(style.paddingRight); - return width; - } - - public width(el) { - let width = el.offsetWidth; - let style = getComputedStyle(el); - - width -= parseFloat(style.paddingLeft) + parseFloat(style.paddingRight); - return width; - } - - public getInnerHeight(el) { - let height = el.offsetHeight; - let style = getComputedStyle(el); - - height += parseFloat(style.paddingTop) + parseFloat(style.paddingBottom); - return height; - } - - public getOuterHeight(el, margin?) { - let height = el.offsetHeight; - - if (margin) { - let style = getComputedStyle(el); - height += parseFloat(style.marginTop) + parseFloat(style.marginBottom); - } - - return height; - } - - public getHeight(el): number { - let height = el.offsetHeight; - let style = getComputedStyle(el); - - height -= parseFloat(style.paddingTop) + parseFloat(style.paddingBottom) + parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth); - - return height; - } - - public getWidth(el): number { - let width = el.offsetWidth; - let style = getComputedStyle(el); - - width -= parseFloat(style.paddingLeft) + parseFloat(style.paddingRight) + parseFloat(style.borderLeftWidth) + parseFloat(style.borderRightWidth); - - return width; - } - - public getViewport(): any { - let win = window, - d = document, - e = d.documentElement, - g = d.getElementsByTagName('body')[0], - w = win.innerWidth || e.clientWidth || g.clientWidth, - h = win.innerHeight || e.clientHeight || g.clientHeight; - - return { width: w, height: h }; - } - - public getOffset(el) { - let rect = el.getBoundingClientRect(); - - return { - top: rect.top + document.body.scrollTop, - left: rect.left + document.body.scrollLeft - }; - } - - getUserAgent(): string { - return navigator.userAgent; - } - - isIE() { - var ua = window.navigator.userAgent; - - var msie = ua.indexOf('MSIE '); - if (msie > 0) { - // IE 10 or older => return version number - return true; - } - - var trident = ua.indexOf('Trident/'); - if (trident > 0) { - // IE 11 => return version number - var rv = ua.indexOf('rv:'); - return true; - } - - var edge = ua.indexOf('Edge/'); - if (edge > 0) { - // Edge (IE 12+) => return version number - return true; - } - - // other browser - return false; - } - - appendChild(element: any, target: any) { - if(this.isElement(target)) - target.appendChild(element); - else if(target.el && target.el.nativeElement) - target.el.nativeElement.appendChild(element); - else - throw 'Cannot append ' + target + ' to ' + element; - } - - removeChild(element: any, target: any) { - if(this.isElement(target)) - target.removeChild(element); - else if(target.el && target.el.nativeElement) - target.el.nativeElement.removeChild(element); - else - throw 'Cannot remove ' + element + ' from ' + target; - } - - isElement(obj: any) { - return (typeof HTMLElement === "object" ? obj instanceof HTMLElement : - obj && typeof obj === "object" && obj !== null && obj.nodeType === 1 && typeof obj.nodeName === "string" - ); - } - - calculateScrollbarWidth(): number { - if(this.calculatedScrollbarWidth !== null) - return this.calculatedScrollbarWidth; - - let scrollDiv = document.createElement("div"); - scrollDiv.className = "ui-scrollbar-measure"; - document.body.appendChild(scrollDiv); - - let scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; - document.body.removeChild(scrollDiv); - - this.calculatedScrollbarWidth = scrollbarWidth; - - return scrollbarWidth; - } - - invokeElementMethod(element: any, methodName: string, args?: any[]): void { - (element as any)[methodName].apply(element, args); - } - - clearSelection(): void { - if(window.getSelection) { - if(window.getSelection().empty) { - window.getSelection().empty(); - } else if(window.getSelection().removeAllRanges && window.getSelection().rangeCount > 0 && window.getSelection().getRangeAt(0).getClientRects().length > 0) { - window.getSelection().removeAllRanges(); - } - } - else if(document['selection'] && document['selection'].empty) { - try { - document['selection'].empty(); - } catch(error) { - //ignore IE bug - } - } - } - - getBrowser() { - if(!this.browser) { - let matched = this.resolveUserAgent(); - this.browser = {}; - - if (matched.browser) { - this.browser[matched.browser] = true; - this.browser['version'] = matched.version; - } - - if (this.browser['chrome']) { - this.browser['webkit'] = true; - } else if (this.browser['webkit']) { - this.browser['safari'] = true; - } - } - - return this.browser; - } - - resolveUserAgent() { - let ua = navigator.userAgent.toLowerCase(); - let match = /(chrome)[ \/]([\w.]+)/.exec(ua) || - /(webkit)[ \/]([\w.]+)/.exec(ua) || - /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || - /(msie) ([\w.]+)/.exec(ua) || - ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || - []; - - return { - browser: match[1] || "", - version: match[2] || "0" - }; - } -} diff --git a/dashboard/src/app/components/dragdrop/dragdrop.spec.ts b/dashboard/src/app/components/dragdrop/dragdrop.spec.ts deleted file mode 100644 index f8e8918a6..000000000 --- a/dashboard/src/app/components/dragdrop/dragdrop.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Draggable } from './dragdrop'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Draggable', () => { - - let draggable: Draggable; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Draggable - ] - }); - - fixture = TestBed.createComponent(Draggable); - draggable = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/dragdrop/dragdrop.ts b/dashboard/src/app/components/dragdrop/dragdrop.ts deleted file mode 100644 index 96dc821f0..000000000 --- a/dashboard/src/app/components/dragdrop/dragdrop.ts +++ /dev/null @@ -1,226 +0,0 @@ -import {NgModule,Directive,OnDestroy,AfterViewInit,ElementRef,HostListener,Input,Output,EventEmitter,NgZone} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; - -@Directive({ - selector: '[pDraggable]', - host: { - '[draggable]': 'true' - }, - providers: [DomHandler] -}) -export class Draggable implements AfterViewInit, OnDestroy { - - @Input('pDraggable') scope: string; - - @Input() dragEffect: string; - - @Input() dragHandle: string; - - @Output() onDragStart: EventEmitter = new EventEmitter(); - - @Output() onDragEnd: EventEmitter = new EventEmitter(); - - @Output() onDrag: EventEmitter = new EventEmitter(); - - handle: any; - - dragListener: any; - - mouseOverListener: any; - - mouseLeaveListener: any; - - constructor(public el: ElementRef, public domHandler: DomHandler, public zone: NgZone) {} - - ngAfterViewInit() { - this.bindMouseListeners(); - } - - bindDragListener() { - if (!this.dragListener) { - this.zone.runOutsideAngular(() => { - this.dragListener = this.drag.bind(this); - this.el.nativeElement.addEventListener('drag', this.dragListener); - }); - } - } - - unbindDragListener() { - if (this.dragListener) { - this.zone.runOutsideAngular(() => { - this.el.nativeElement.removeEventListener('drag', this.dragListener); - this.dragListener = null; - }); - } - } - - bindMouseListeners() { - if (!this.mouseOverListener && this.mouseLeaveListener) { - this.zone.runOutsideAngular(() => { - this.mouseOverListener = this.mouseover.bind(this); - this.mouseLeaveListener = this.mouseleave.bind(this); - this.el.nativeElement.addEventListener('mouseover', this.mouseOverListener); - this.el.nativeElement.addEventListener('mouseleave', this.mouseLeaveListener); - }); - } - } - - unbindMouseListeners() { - if (this.mouseOverListener && this.mouseLeaveListener) { - this.zone.runOutsideAngular(() => { - this.el.nativeElement.removeEventListener('mouseover', this.mouseOverListener); - this.el.nativeElement.removeEventListener('mouseleave', this.mouseLeaveListener); - this.mouseOverListener = null; - this.mouseLeaveListener = null; - }); - } - } - - drag(event) { - this.onDrag.emit(event); - } - - @HostListener('dragstart', ['$event']) - dragStart(event) { - if(this.allowDrag()) { - if(this.dragEffect) { - event.dataTransfer.effectAllowed = this.dragEffect; - } - event.dataTransfer.setData('text', this.scope); - - this.onDragStart.emit(event); - - this.bindDragListener(); - } - else { - event.preventDefault(); - } - } - - @HostListener('dragend', ['$event']) - dragEnd(event) { - this.onDragEnd.emit(event); - this.unbindDragListener(); - } - - mouseover(event) { - this.handle = event.target; - } - - mouseleave(event) { - this.handle = null; - } - - allowDrag() : boolean { - if(this.dragHandle && this.handle) - return this.domHandler.matches(this.handle, this.dragHandle); - else - return true; - } - - ngOnDestroy() { - this.unbindDragListener(); - this.unbindMouseListeners(); - } - -} - -@Directive({ - selector: '[pDroppable]', - providers: [DomHandler] -}) -export class Droppable implements AfterViewInit, OnDestroy { - - @Input('pDroppable') scope: string|string[]; - - @Input() dropEffect: string; - - @Output() onDragEnter: EventEmitter = new EventEmitter(); - - @Output() onDragLeave: EventEmitter = new EventEmitter(); - - @Output() onDrop: EventEmitter = new EventEmitter(); - - constructor(public el: ElementRef, public domHandler: DomHandler, public zone: NgZone) {} - - dragOverListener: any; - - ngAfterViewInit() { - this.bindDragOverListener(); - } - - bindDragOverListener() { - if (!this.dragOverListener) { - this.zone.runOutsideAngular(() => { - this.dragOverListener = this.dragOver.bind(this); - this.el.nativeElement.addEventListener('dragover', this.dragOverListener); - }); - } - } - - unbindDragOverListener() { - if (this.dragOverListener) { - this.zone.runOutsideAngular(() => { - this.el.nativeElement.removeEventListener('dragover', this.dragOverListener); - this.dragOverListener = null; - }); - } - } - - dragOver(event) { - event.preventDefault(); - } - - @HostListener('drop', ['$event']) - drop(event) { - if(this.allowDrop(event)) { - event.preventDefault(); - this.onDrop.emit(event); - } - } - - @HostListener('dragenter', ['$event']) - dragEnter(event) { - event.preventDefault(); - - if(this.dropEffect) { - event.dataTransfer.dropEffect = this.dropEffect; - } - - this.onDragEnter.emit(event); - } - - @HostListener('dragleave', ['$event']) - dragLeave(event) { - event.preventDefault(); - - this.onDragLeave.emit(event); - } - - allowDrop(event): boolean { - let dragScope = event.dataTransfer.getData('text'); - if(typeof (this.scope) == "string" && dragScope == this.scope) { - return true; - } - else if(this.scope instanceof Array) { - for(let j = 0; j < this.scope.length; j++) { - if(dragScope == this.scope[j]) { - return true; - } - } - } - return false; - } - - ngOnDestroy() { - this.unbindDragOverListener(); - } -} - -@NgModule({ - imports: [CommonModule], - exports: [Draggable,Droppable], - declarations: [Draggable,Droppable] -}) -export class DragDropModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/dropdown/dropdown.scss b/dashboard/src/app/components/dropdown/dropdown.scss deleted file mode 100644 index 3a64356cf..000000000 --- a/dashboard/src/app/components/dropdown/dropdown.scss +++ /dev/null @@ -1,131 +0,0 @@ -.ui-dropdown { - display: inline-block; - position: relative; - cursor: pointer; - vertical-align: middle; - @extend .ui-corner-all-small; -} - -.ui-dropdown .ui-dropdown-clear-icon { - position: absolute; - right: 2em; - top: 50%; - font-size: .75em; - height: 1em; - margin-top: -.5em; - right: 2.5em; -} - -.ui-dropdown .ui-dropdown-trigger { - border-right: none; - border-top: none; - border-bottom: none; - cursor: pointer; - width: .25rem; - height: 100%; - position: absolute; - right: 0; - top: 0; - padding: 0; - @extend .ui-corner-right-small; -} - -.ui-dropdown .ui-dropdown-trigger .fa { - margin-top: .07rem; - margin-left: .02rem; //原为.03rem,改为.02rem更居中 -} - -.ui-dropdown .ui-dropdown-label { - display: block; - border: none; - white-space: nowrap; - overflow: hidden; - font-weight: normal; - width: 100%; - padding-right: 2.5em; -} - -.ui-dropdown .ui-inputtext { - min-height: .30rem; - min-width: .80rem; - line-height: .20rem; -} - -.ui-dropdown-item-empty, -.ui-dropdown-label-empty { - text-indent: -9999px; - overflow: hidden; -} - -.ui-dropdown.ui-state-disabled .ui-dropdown-trigger, -.ui-dropdown.ui-state-disabled .ui-dropdown-label { - cursor: default; -} - -.ui-dropdown label.ui-dropdown-label { - cursor: pointer; -} - -.ui-dropdown input.ui-dropdown-label { - cursor: default; -} - -.ui-dropdown .ui-dropdown-panel { - min-width: 100%; -} - -.ui-dropdown-panel { - position: absolute; - height: auto; - display: none; -} - -.ui-dropdown-panel .ui-dropdown-items-wrapper { - overflow: auto; -} - -.ui-dropdown-panel .ui-dropdown-item { - font-weight: normal; - border: 0 none; - cursor: pointer; - margin: 1px 0; - padding: .125em .25em; - text-align: left; -} - -.ui-dropdown-panel .ui-dropdown-item-group { - font-weight: bold; - cursor: default; -} - -.ui-dropdown-panel .ui-dropdown-list { - padding: 0.4em; - border: 0 none; -} - -.ui-dropdown-panel .ui-dropdown-filter { - width: 100%; - box-sizing: border-box; - padding-right: 1.5em; -} - -.ui-dropdown-panel .ui-dropdown-filter-container { - position: relative; - margin: 0; - padding: 0.4em; - display: inline-block; - width: 100%; -} - -.ui-dropdown-panel .ui-dropdown-filter-container .fa { - position: absolute; - top: .8em; - right: 1em; -} - - -/** Dropdown **/ - -.ui-fluid .ui-dropdown { - width: 100%; -} \ No newline at end of file diff --git a/dashboard/src/app/components/dropdown/dropdown.spec.ts b/dashboard/src/app/components/dropdown/dropdown.spec.ts deleted file mode 100644 index 83edc4102..000000000 --- a/dashboard/src/app/components/dropdown/dropdown.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Dropdown } from './dropdown'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Dropdown', () => { - - let dropdown: Dropdown; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Dropdown - ] - }); - - fixture = TestBed.createComponent(Dropdown); - dropdown = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/dropdown/dropdown.ts b/dashboard/src/app/components/dropdown/dropdown.ts deleted file mode 100644 index 34113c61d..000000000 --- a/dashboard/src/app/components/dropdown/dropdown.ts +++ /dev/null @@ -1,761 +0,0 @@ -import {NgModule,Component,ElementRef,OnInit,AfterViewInit,AfterContentInit,AfterViewChecked,OnDestroy,Input,Output,Renderer2,EventEmitter,ContentChildren, - QueryList,ViewChild,TemplateRef,forwardRef,ChangeDetectorRef,NgZone} from '@angular/core'; -import {trigger,state,style,transition,animate} from '@angular/animations'; -import {CommonModule} from '@angular/common'; -import {SelectItem} from '../common/selectitem'; -import {SharedModule,PrimeTemplate} from '../common/shared'; -import {DomHandler} from '../dom/domhandler'; -import {ObjectUtils} from '../utils/objectutils'; -import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; - -export const DROPDOWN_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => Dropdown), - multi: true -}; - -@Component({ - selector: 'p-dropdown', - template: ` -
-
- -
-
- -
- - - - -
- -
-
-
- - -
-
-
    - - -
  • - {{optgroup.label||'empty'}} - -
  • - -
    -
    - - - - -
  • - {{option.label||'empty'}} - -
  • -
    -
  • {{emptyFilterMessage}}
  • -
-
-
-
- `, - animations: [ - trigger('panelState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]) - ], - host: { - '[class.ui-inputwrapper-filled]': 'filled', - '[class.ui-inputwrapper-focus]': 'focus' - }, - providers: [DomHandler,ObjectUtils,DROPDOWN_VALUE_ACCESSOR] -}) -export class Dropdown implements OnInit,AfterViewInit,AfterContentInit,AfterViewChecked,OnDestroy,ControlValueAccessor { - - @Input() scrollHeight: string = '200px'; - - @Input() filter: boolean; - - @Input() name: string; - - @Input() style: any; - - @Input() panelStyle: any; - - @Input() styleClass: string; - - @Input() panelStyleClass: string; - - @Input() disabled: boolean; - - @Input() readonly: boolean; - - @Input() autoWidth: boolean = true; - - @Input() required: boolean; - - @Input() editable: boolean; - - @Input() appendTo: any; - - @Input() tabindex: number; - - @Input() placeholder: string; - - @Input() filterPlaceholder: string; - - @Input() inputId: string; - - @Input() dataKey: string; - - @Input() filterBy: string = 'label'; - - @Input() lazy: boolean = true; - - @Input() autofocus: boolean; - - @Input() resetFilterOnHide: boolean = false; - - @Input() dropdownIcon: string = 'fa fa-fw fa-caret-down'; - - @Input() optionLabel: string; - - @Input() autoDisplayFirst: boolean = true; - - @Input() group: boolean; - - @Input() showClear: boolean; - - @Input() emptyFilterMessage: string = 'No results found'; - - @Output() onChange: EventEmitter = new EventEmitter(); - - @Output() onFocus: EventEmitter = new EventEmitter(); - - @Output() onBlur: EventEmitter = new EventEmitter(); - - @ViewChild('container') containerViewChild: ElementRef; - - @ViewChild('panel') panelViewChild: ElementRef; - - @ViewChild('itemswrapper') itemsWrapperViewChild: ElementRef; - - @ViewChild('filter') filterViewChild: ElementRef; - - @ViewChild('in') focusViewChild: ElementRef; - - @ViewChild('editableInput') editableInputViewChild: ElementRef; - - @ContentChildren(PrimeTemplate) templates: QueryList; - - public itemTemplate: TemplateRef; - - public groupTemplate: TemplateRef; - - public selectedItemTemplate: TemplateRef; - - selectedOption: any; - - _options: any[]; - - value: any; - - onModelChange: Function = () => {}; - - onModelTouched: Function = () => {}; - - optionsToDisplay: any[]; - - hover: boolean; - - focus: boolean; - - filled: boolean; - - public panelVisible: boolean = false; - - public shown: boolean; - - public documentClickListener: any; - - public optionsChanged: boolean; - - public panel: HTMLDivElement; - - public container: HTMLDivElement; - - public itemsWrapper: HTMLDivElement; - - public initialized: boolean; - - public selfClick: boolean; - - public itemClick: boolean; - - public clearClick: boolean; - - public hoveredItem: any; - - public selectedOptionUpdated: boolean; - - public filterValue: string; - - constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2, private cd: ChangeDetectorRef, - public objectUtils: ObjectUtils, public zone: NgZone) {} - - ngAfterContentInit() { - this.templates.forEach((item) => { - switch(item.getType()) { - case 'item': - this.itemTemplate = item.template; - break; - - case 'selectedItem': - this.selectedItemTemplate = item.template; - break; - - case 'group': - this.groupTemplate = item.template; - break; - - default: - this.itemTemplate = item.template; - break; - } - }); - } - - ngOnInit() { - this.optionsToDisplay = this.options; - this.updateSelectedOption(null); - } - - @Input() get options(): any[] { - return this._options; - } - - set options(val: any[]) { - let opts = this.optionLabel ? this.objectUtils.generateSelectItems(val, this.optionLabel) : val; - this._options = opts; - this.optionsToDisplay = this._options; - this.updateSelectedOption(this.value); - this.optionsChanged = true; - - if(this.filterValue && this.filterValue.length) { - this.activateFilter(); - } - } - - ngAfterViewInit() { - this.container = this.containerViewChild.nativeElement; - this.panel = this.panelViewChild.nativeElement; - this.itemsWrapper = this.itemsWrapperViewChild.nativeElement; - - if(this.editable) { - this.updateEditableLabel(); - } - - this.updateDimensions(); - this.initialized = true; - - if(this.appendTo) { - if(this.appendTo === 'body') - document.body.appendChild(this.panel); - else - this.domHandler.appendChild(this.panel, this.appendTo); - } - } - - get label(): string { - return (this.selectedOption ? this.selectedOption.label : null); - } - - updateEditableLabel(): void { - if(this.editableInputViewChild && this.editableInputViewChild.nativeElement) { - this.editableInputViewChild.nativeElement.value = (this.selectedOption ? this.selectedOption.label : this.value||''); - } - } - - onItemClick(event, option) { - this.itemClick = true; - this.selectItem(event, option); - this.focusViewChild.nativeElement.focus(); - this.filled = true; - this.hide(); - } - - selectItem(event, option) { - if(this.selectedOption != option) { - this.selectedOption = option; - this.value = option.value; - - this.onModelChange(this.value); - this.updateEditableLabel(); - this.onChange.emit({ - originalEvent: event, - value: this.value - }); - } - } - - ngAfterViewChecked() { - if(this.shown) { - this.onShow(); - this.shown = false; - } - - if(this.optionsChanged && this.panelVisible) { - this.optionsChanged = false; - - this.zone.runOutsideAngular(() => { - setTimeout(() => { - this.updateDimensions(); - this.alignPanel(); - }, 1); - }); - } - - if(this.selectedOptionUpdated && this.itemsWrapper) { - let selectedItem = this.domHandler.findSingle(this.panel, 'li.ui-state-highlight'); - if(selectedItem) { - this.domHandler.scrollInView(this.itemsWrapper, this.domHandler.findSingle(this.panel, 'li.ui-state-highlight')); - } - this.selectedOptionUpdated = false; - } - } - - writeValue(value: any): void { - if(this.filter) { - this.resetFilter(); - } - - this.value = value; - this.updateSelectedOption(value); - this.updateEditableLabel(); - this.updateFilledState(); - this.cd.markForCheck(); - } - - resetFilter(): void { - if(this.filterViewChild && this.filterViewChild.nativeElement) { - this.filterViewChild.nativeElement.value = ''; - } - - this.optionsToDisplay = this.options; - } - - updateSelectedOption(val: any): void { - this.selectedOption = this.findOption(val, this.optionsToDisplay); - if(this.autoDisplayFirst && !this.placeholder && !this.selectedOption && this.optionsToDisplay && this.optionsToDisplay.length && !this.editable) { - this.selectedOption = this.optionsToDisplay[0]; - } - this.selectedOptionUpdated = true; - } - - registerOnChange(fn: Function): void { - this.onModelChange = fn; - } - - registerOnTouched(fn: Function): void { - this.onModelTouched = fn; - } - - setDisabledState(val: boolean): void { - this.disabled = val; - } - - updateDimensions() { - if(this.autoWidth) { - let select = this.domHandler.findSingle(this.el.nativeElement, 'select'); - if(!this.style||(!this.style['width']&&!this.style['min-width'])) { - this.el.nativeElement.children[0].style.width = select.offsetWidth + 30 + 'px'; - } - } - } - - onMouseclick(event) { - if(this.disabled||this.readonly) { - return; - } - - this.selfClick = true; - this.clearClick = this.domHandler.hasClass(event.target, 'ui-dropdown-clear-icon'); - - if(!this.itemClick && !this.clearClick) { - this.focusViewChild.nativeElement.focus(); - - if(this.panelVisible) - this.hide(); - else { - this.show(); - - if (this.filterViewChild != undefined) { - setTimeout(() => { - this.filterViewChild.nativeElement.focus(); - }, 200); - } - } - } - } - - onEditableInputClick(event) { - this.itemClick = true; - this.bindDocumentClickListener(); - } - - onEditableInputFocus(event) { - this.focus = true; - this.hide(); - } - - onEditableInputChange(event) { - this.value = event.target.value; - this.updateSelectedOption(this.value); - this.onModelChange(this.value); - this.onChange.emit({ - originalEvent: event, - value: this.value - }); - } - - onShow() { - this.bindDocumentClickListener(); - - if(this.options && this.options.length) { - this.alignPanel(); - - let selectedListItem = this.domHandler.findSingle(this.itemsWrapper, '.ui-dropdown-item.ui-state-highlight'); - if(selectedListItem) { - this.domHandler.scrollInView(this.itemsWrapper, selectedListItem); - } - } - } - - show() { - if(this.appendTo) { - this.panel.style.minWidth = this.domHandler.getWidth(this.container) + 'px'; - } - - this.panel.style.zIndex = String(++DomHandler.zindex); - this.panelVisible = true; - this.shown = true; - } - - hide() { - this.panelVisible = false; - - if(this.filter && this.resetFilterOnHide) { - this.resetFilter(); - } - } - - alignPanel() { - if(this.appendTo) - this.domHandler.absolutePosition(this.panel, this.container); - else - this.domHandler.relativePosition(this.panel, this.container); - } - - onInputFocus(event) { - this.focus = true; - this.onFocus.emit(event); - } - - onInputBlur(event) { - this.focus = false; - this.onModelTouched(); - this.onBlur.emit(event); - } - - onKeydown(event) { - if(this.readonly || !this.optionsToDisplay || this.optionsToDisplay.length === null) { - return; - } - - switch(event.which) { - //down - case 40: - if(!this.panelVisible && event.altKey) { - this.show(); - } - else { - if(this.group) { - let selectedItemIndex = this.selectedOption ? this.findOptionGroupIndex(this.selectedOption.value, this.optionsToDisplay) : -1; - - if(selectedItemIndex !== -1) { - let nextItemIndex = selectedItemIndex.itemIndex + 1; - if(nextItemIndex < (this.optionsToDisplay[selectedItemIndex.groupIndex].items.length)) { - this.selectItem(event, this.optionsToDisplay[selectedItemIndex.groupIndex].items[nextItemIndex]); - this.selectedOptionUpdated = true; - } - else if(this.optionsToDisplay[selectedItemIndex.groupIndex + 1]) { - this.selectItem(event, this.optionsToDisplay[selectedItemIndex.groupIndex + 1].items[0]); - this.selectedOptionUpdated = true; - } - } - else { - this.selectItem(event, this.optionsToDisplay[0].items[0]); - } - } - else { - let selectedItemIndex = this.selectedOption ? this.findOptionIndex(this.selectedOption.value, this.optionsToDisplay) : -1; - let nextItemIndex = selectedItemIndex + 1; - if(nextItemIndex != (this.optionsToDisplay.length)) { - this.selectItem(event, this.optionsToDisplay[nextItemIndex]); - this.selectedOptionUpdated = true; - } - else { - this.selectItem(event, this.optionsToDisplay[0]); - } - } - } - - event.preventDefault(); - - break; - - //up - case 38: - if(this.group) { - let selectedItemIndex = this.selectedOption ? this.findOptionGroupIndex(this.selectedOption.value, this.optionsToDisplay) : -1; - if(selectedItemIndex !== -1) { - let prevItemIndex = selectedItemIndex.itemIndex - 1; - if(prevItemIndex >= 0) { - this.selectItem(event, this.optionsToDisplay[selectedItemIndex.groupIndex].items[prevItemIndex]); - this.selectedOptionUpdated = true; - } - else if(prevItemIndex < 0) { - let prevGroup = this.optionsToDisplay[selectedItemIndex.groupIndex - 1]; - if(prevGroup) { - this.selectItem(event, prevGroup.items[prevGroup.items.length - 1]); - this.selectedOptionUpdated = true; - } - } - } - } - else { - let selectedItemIndex = this.selectedOption ? this.findOptionIndex(this.selectedOption.value, this.optionsToDisplay) : -1; - if(selectedItemIndex > 0) { - let prevItemIndex = selectedItemIndex - 1; - this.selectItem(event, this.optionsToDisplay[prevItemIndex]); - this.selectedOptionUpdated = true; - } - } - - event.preventDefault(); - break; - - //space - case 32: - case 32: - if(!this.panelVisible){ - this.show(); - event.preventDefault(); - } - break; - - //enter - case 13: - if (!this.filter || (this.optionsToDisplay && this.optionsToDisplay.length > 0)) { - this.hide(); - } - - event.preventDefault(); - break; - - //escape and tab - case 27: - case 9: - this.hide(); - break; - } - } - - findOptionIndex(val: any, opts: any[]): number { - let index: number = -1; - if(opts) { - for(let i = 0; i < opts.length; i++) { - if((val == null && opts[i].value == null) || this.objectUtils.equals(val, opts[i].value, this.dataKey)) { - index = i; - break; - } - } - } - - return index; - } - - findOptionGroupIndex(val: any, opts: any[]): any { - let groupIndex, itemIndex; - - if(opts) { - for(let i = 0; i < opts.length; i++) { - groupIndex = i; - itemIndex = this.findOptionIndex(val, opts[i].items); - - if(itemIndex !== -1) { - break; - } - } - } - - if(itemIndex !== -1) { - return {groupIndex: groupIndex, itemIndex: itemIndex}; - } - else { - return -1; - } - } - - findOption(val: any, opts: any[], inGroup?: boolean): SelectItem { - if(this.group && !inGroup) { - let opt: SelectItem; - if(opts && opts.length) { - for(let optgroup of opts) { - opt = this.findOption(val, optgroup.items, true); - if(opt) { - break; - } - } - } - return opt; - } - else { - let index: number = this.findOptionIndex(val, opts); - return (index != -1) ? opts[index] : null; - } - } - - onFilter(event): void { - let inputValue = event.target.value.toLowerCase(); - if(inputValue && inputValue.length) { - this.filterValue = inputValue; - this.activateFilter(); - } - else { - this.filterValue = null; - this.optionsToDisplay = this.options; - } - - this.optionsChanged = true; - } - - activateFilter() { - let searchFields: string[] = this.filterBy.split(','); - if(this.options && this.options.length) { - if(this.group) { - let filteredGroups = []; - for(let optgroup of this.options) { - let filteredSubOptions = this.objectUtils.filter(optgroup.items, searchFields, this.filterValue); - if(filteredSubOptions && filteredSubOptions.length) { - filteredGroups.push({ - label: optgroup.label, - value: optgroup.value, - items: filteredSubOptions - }); - } - } - - this.optionsToDisplay = filteredGroups; - } - else { - this.optionsToDisplay = this.objectUtils.filter(this.options, searchFields, this.filterValue); - } - - this.optionsChanged = true; - } - } - - applyFocus(): void { - if(this.editable) - this.domHandler.findSingle(this.el.nativeElement, '.ui-dropdown-label.ui-inputtext').focus(); - else - this.domHandler.findSingle(this.el.nativeElement, 'input[readonly]').focus(); - } - - bindDocumentClickListener() { - if(!this.documentClickListener) { - this.documentClickListener = this.renderer.listen('document', 'click', () => { - if(!this.selfClick&&!this.itemClick) { - this.panelVisible = false; - this.unbindDocumentClickListener(); - } - - this.selfClick = false; - this.itemClick = false; - this.cd.markForCheck(); - }); - } - } - - unbindDocumentClickListener() { - if(this.documentClickListener) { - this.documentClickListener(); - this.documentClickListener = null; - } - } - - updateFilledState() { - this.filled = (this.value != null); - } - - clear(event: Event) { - this.clearClick = true; - this.value = null; - this.onModelChange(this.value); - this.onChange.emit({ - originalEvent: event, - value: this.value - }); - this.updateSelectedOption(this.value); - this.updateEditableLabel(); - this.updateFilledState(); - } - - ngOnDestroy() { - this.initialized = false; - - this.unbindDocumentClickListener(); - - if(this.appendTo) { - this.el.nativeElement.appendChild(this.panel); - } - } -} - -@NgModule({ - imports: [CommonModule,SharedModule], - exports: [Dropdown,SharedModule], - declarations: [Dropdown] -}) -export class DropdownModule { } diff --git a/dashboard/src/app/components/dropmenu/dropmenu.scss b/dashboard/src/app/components/dropmenu/dropmenu.scss deleted file mode 100644 index 839dfa41b..000000000 --- a/dashboard/src/app/components/dropmenu/dropmenu.scss +++ /dev/null @@ -1,145 +0,0 @@ -.ui-dropmenu { - position: relative; - display: inline-block; - zoom: 1; -} - -.ui-dropmenu > .ui-widget.ui-button { - padding-right: 0.20rem; - padding-left: 0; - width: auto; - min-width: 0; - vertical-align: top; - background: none; - border: none; - color: map-get($color-primary, 'normal'); - &:hover { - background: none; - border: none; - color: map-get($color-primary, 'hover'); - box-shadow: none; - } - &:active { - background: none; - border: none; - color: map-get($color-primary, 'active'); - } - &:disabled{ - background: none; - border: none; - color: $color-disabled; - } - & > .ui-button-icon-right{ - right: 0; - } - &.ui-button-icon-only{ - padding-right: 0; - } -} - -.ui-dropmenu.ui-state-disabled button { - cursor: default; -} - -/* ui-dropmenu-list */ -.ui-dropmenu-list { - position: absolute; - display: none; - border: none; - box-shadow: 0px 3px 10px 0px rgba(0, 0, 0, 0.18); - @extend .ui-corner-all-small; -} - -.ui-dropmenu-list .ui-menu-separator { - border: none; - border-top: 10px solid #f5f5f5; - & + li.ui-menuitem{ - border-top: solid 1px #f2f2f2; - } -} - -.ui-dropmenu-list ul { - list-style: none; - margin: 0; - padding: 0; -} - -.ui-dropmenu-list .ui-submenu-list { - display: none; - position: absolute; - border: none; - box-shadow: 0px 3px 10px 0px rgba(0, 0, 0, 0.18); - @extend .ui-corner-all-small; -} - -.ui-dropmenu-list .ui-menuitem-link { - padding: 0 .20rem 0 .15rem; - display: block; - position: relative; - line-height: .40rem; - &:hover{ - color: map-get($map: $color-primary, $key: hover); - background: #f9f9f9; - } -} - -.ui-dropmenu-list .ui-menuitem { - position: relative; - white-space: nowrap; - min-width: 1.50rem; - border-bottom: solid 1px #f2f2f2; - &:first-of-type { - .ui-menuitem-link{ - @extend .ui-corner-top-small; - } - } - &:last-of-type { - border: none; - .ui-menuitem-link{ - @extend .ui-corner-bottom-small; - } - } -} - -.ui-dropmenu-list .ui-menuitem-link .ui-submenu-icon { - position: absolute; - margin-top: -.5em; - right: 0; - top: 50%; -} - -.ui-dropmenu-list .ui-menuitem-active > .ui-submenu > .ui-submenu-list { - display: block !important; -} - - -.ui-fluid .ui-dropmenu { - width: 100%; -} - -.ui-fluid .ui-dropmenu .ui-button { - width: 100%; -} - -.ui-dropmenu-list.ui-dropmenu-large { - @extend .ui-corner-all-medium; - .ui-submenu-list{ - @extend .ui-corner-all-medium; - } - .ui-menuitem{ - min-width: 1.80rem; - &:first-of-type { - .ui-menuitem-link{ - padding-top: 0.05rem; - @extend .ui-corner-top-medium; - } - } - &:last-of-type { - .ui-menuitem-link{ - padding-top: 0; - padding-bottom: 0.05rem; - @extend .ui-corner-bottom-medium; - } - } - } -} \ No newline at end of file diff --git a/dashboard/src/app/components/dropmenu/dropmenu.ts b/dashboard/src/app/components/dropmenu/dropmenu.ts deleted file mode 100644 index ef46af1b9..000000000 --- a/dashboard/src/app/components/dropmenu/dropmenu.ts +++ /dev/null @@ -1,266 +0,0 @@ -import {NgModule,Component,ElementRef,AfterViewInit,OnDestroy,Input,Output,Renderer2,Inject,forwardRef,ViewChild,AfterViewChecked,ContentChildren,EventEmitter,QueryList,ChangeDetectorRef} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; -import {MenuItem} from '../common/menuitem'; -import {Location} from '@angular/common'; -import {trigger,state,style,transition,animate} from '@angular/animations'; -import {ButtonModule} from '../button/button'; -import {Router} from '@angular/router'; -import {RouterModule} from '@angular/router'; - -@Component({ - selector: 'p-dropMenuSub', - template: ` - - `, - providers: [DomHandler] -}) -export class ContextMenuSub { - - @Input() item: MenuItem; - - @Input() root: boolean; - - constructor(public domHandler: DomHandler, @Inject(forwardRef(() => DropMenu)) public contextMenu: DropMenu) {} - - activeItem: any; - - containerLeft: any; - - hideTimeout: any; - - onItemMouseEnter(event, item, menuitem) { - if(menuitem.disabled) { - return; - } - - if(this.hideTimeout) { - clearTimeout(this.hideTimeout); - this.hideTimeout = null; - } - - this.activeItem = item; - let nextElement = item.children[0].nextElementSibling; - if(nextElement) { - let sublist = nextElement.children[0]; - sublist.style.zIndex = ++DomHandler.zindex; - this.position(sublist, item); - } - } - - onItemMouseLeave(event, link) { - this.hideTimeout = setTimeout(() => { - this.activeItem = null; - }, 1000); - } - - itemClick(event, item: MenuItem) { - if(item.disabled) { - event.preventDefault(); - return; - } - - if(!item.url) { - event.preventDefault(); - } - - if(item.command) { - item.command({ - originalEvent: event, - item: item - }); - } - } - - listClick(event) { - this.activeItem = null; - } - - position(sublist, item) { - this.containerLeft = this.domHandler.getOffset(item.parentElement) - let viewport = this.domHandler.getViewport(); - let sublistWidth = sublist.offsetParent ? sublist.offsetWidth: this.domHandler.getHiddenElementOuterWidth(sublist); - let itemOuterWidth = this.domHandler.getOuterWidth(item.children[0]); - - sublist.style.top = '0px'; - - if((parseInt(this.containerLeft.left) + itemOuterWidth + sublistWidth) > (viewport.width - this.calculateScrollbarWidth())) { - sublist.style.left = -sublistWidth + 'px'; - } - else { - sublist.style.left = itemOuterWidth + 'px'; - } - } - - calculateScrollbarWidth(): number { - let scrollDiv = document.createElement("div"); - scrollDiv.className = "ui-scrollbar-measure"; - document.body.appendChild(scrollDiv); - - let scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; - document.body.removeChild(scrollDiv); - - return scrollbarWidth; - } -} - -@Component({ - selector: 'p-dropmenu', - template: ` -
- -
- -
-
- `, - providers: [DomHandler] -}) -export class DropMenu implements AfterViewInit,OnDestroy { - - @Input() model: MenuItem[]; - - @Input() label: string; - - @Input() icon: string = "fa-caret-down"; - - @Input() disabled: boolean; - - @Input() global: boolean; - - @Input() target: any; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() appendTo: any = "body"; - - @Input() autoZIndex: boolean = true; - - @Input() baseZIndex: number = 0; - - @Output() onDropdownClick: EventEmitter = new EventEmitter(); - - @ViewChild('container') containerViewChild: ElementRef; - - @ViewChild('overlay') overlayViewChild: ElementRef; - - documentClickListener: any; - - public dropdownClick: boolean; - - public shown: boolean; - - constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2) {} - - ngAfterViewInit() { - if(this.appendTo) { - if(this.appendTo === 'body') - document.body.appendChild( this.overlayViewChild.nativeElement); - else - this.domHandler.appendChild(this.overlayViewChild.nativeElement, this.appendTo); - } - } - - onDropdownButtonClick(event: Event) { - if(!this.shown) { - this.dropdownClick = true; - }else{ - this.dropdownClick = false; - } - this.onDropdownClick.emit(event); - this.show(event); - } - - show(event?) { - this.alignPanel(); - this.moveOnTop(); - this.overlayViewChild.nativeElement.style.display = 'block'; - this.domHandler.fadeIn(this.overlayViewChild.nativeElement, 250); - this.bindDocumentClickListener(); - - if(event) { - event.preventDefault(); - } - } - - hide() { - this.overlayViewChild.nativeElement.style.display = 'none'; - this.unbindDocumentClickListener(); - } - - alignPanel() { - if(this.appendTo) - this.domHandler.absolutePosition(this.overlayViewChild.nativeElement, this.containerViewChild.nativeElement); - else - this.domHandler.relativePosition(this.overlayViewChild.nativeElement, this.containerViewChild.nativeElement); - } - - moveOnTop() { - if(this.autoZIndex) { - this.overlayViewChild.nativeElement.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex)); - } - } - - bindDocumentClickListener() { - if(!this.documentClickListener) { - this.documentClickListener = this.renderer.listen('document', 'click', (event) => { - if(this.dropdownClick) { - this.dropdownClick = false; - this.shown = true; - } - else { - this.hide(); - this.shown = false; - this.unbindDocumentClickListener(); - } - }); - } - } - - unbindDocumentClickListener() { - if(this.documentClickListener) { - this.documentClickListener(); - this.documentClickListener = null; - } - } - - ngOnDestroy() { - this.unbindDocumentClickListener(); - - if(this.appendTo) { - this.el.nativeElement.appendChild(this.overlayViewChild.nativeElement); - } - } - -} - -@NgModule({ - imports: [CommonModule, ButtonModule, RouterModule], - exports: [DropMenu, ButtonModule, RouterModule], - declarations: [DropMenu,ContextMenuSub] -}) -export class DropMenuModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/editor/editor.spec.ts b/dashboard/src/app/components/editor/editor.spec.ts deleted file mode 100644 index 90dc4c2a9..000000000 --- a/dashboard/src/app/components/editor/editor.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Editor } from './editor'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Editor', () => { - - let editor: Editor; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Editor - ] - }); - - fixture = TestBed.createComponent(Editor); - editor = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/editor/editor.ts b/dashboard/src/app/components/editor/editor.ts deleted file mode 100644 index c53b8ba18..000000000 --- a/dashboard/src/app/components/editor/editor.ts +++ /dev/null @@ -1,193 +0,0 @@ -import {NgModule,Component,ElementRef,AfterViewInit,Input,Output,EventEmitter,ContentChild,OnChanges,forwardRef} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {SharedModule,Header} from '../common/shared' -import {DomHandler} from '../dom/domhandler'; -import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; - -declare var Quill: any; - -export const EDITOR_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => Editor), - multi: true -}; - -@Component({ - selector: 'p-editor', - template: ` -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- `, - providers: [DomHandler,EDITOR_VALUE_ACCESSOR] -}) -export class Editor implements AfterViewInit,ControlValueAccessor { - - @Output() onTextChange: EventEmitter = new EventEmitter(); - - @Output() onSelectionChange: EventEmitter = new EventEmitter(); - - @ContentChild(Header) toolbar; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() placeholder: string; - - @Input() formats: string[]; - - @Output() onInit: EventEmitter = new EventEmitter(); - - value: string; - - _readonly: boolean; - - onModelChange: Function = () => {}; - - onModelTouched: Function = () => {}; - - quill: any; - - constructor(public el: ElementRef, public domHandler: DomHandler) {} - - ngAfterViewInit() { - let editorElement = this.domHandler.findSingle(this.el.nativeElement ,'div.ui-editor-content'); - let toolbarElement = this.domHandler.findSingle(this.el.nativeElement ,'div.ui-editor-toolbar'); - - this.quill = new Quill(editorElement, { - modules: { - toolbar: toolbarElement - }, - placeholder: this.placeholder, - readOnly: this.readonly, - theme: 'snow', - formats: this.formats - }); - - if(this.value) { - this.quill.pasteHTML(this.value); - } - - this.quill.on('text-change', (delta, oldContents, source) => { - if (source === 'user') { - let html = editorElement.children[0].innerHTML; - let text = this.quill.getText(); - if (html == '


') { - html = null; - } - - this.onTextChange.emit({ - htmlValue: html, - textValue: text, - delta: delta, - source: source - }); - - this.onModelChange(html); - this.onModelTouched(); - } - }); - - this.quill.on('selection-change', (range, oldRange, source) => { - this.onSelectionChange.emit({ - range: range, - oldRange: oldRange, - source: source - }); - }); - - this.onInit.emit({ - editor: this.quill - }); - } - - writeValue(value: any) : void { - this.value = value; - - if(this.quill) { - if(value) - this.quill.pasteHTML(value); - else - this.quill.setText(''); - } - } - - registerOnChange(fn: Function): void { - this.onModelChange = fn; - } - - registerOnTouched(fn: Function): void { - this.onModelTouched = fn; - } - - getQuill() { - return this.quill; - } - - @Input() get readonly(): boolean { - return this._readonly; - } - - set readonly(val:boolean) { - this._readonly = val; - - if(this.quill) { - if(this._readonly) - this.quill.disable(); - else - this.quill.enable(); - } - } -} - -@NgModule({ - imports: [CommonModule], - exports: [Editor,SharedModule], - declarations: [Editor] -}) -export class EditorModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/fieldset/fieldset.css b/dashboard/src/app/components/fieldset/fieldset.css deleted file mode 100644 index 823e1f178..000000000 --- a/dashboard/src/app/components/fieldset/fieldset.css +++ /dev/null @@ -1,29 +0,0 @@ -.ui-fieldset, -.ui-fieldset .ui-fieldset-legend { - padding: 0.5em 1em; -} - -.ui-fieldset-toggleable .ui-fieldset-legend { - padding: 0; -} - -.ui-fieldset-toggleable .ui-fieldset-legend a { - padding: 0.5em 1em; - cursor:pointer; - white-space: nowrap; - display: block; -} - -.ui-fieldset .ui-fieldset-toggler { - margin-right: .1em; - display: inline-block; - vertical-align: middle; -} - -.ui-fieldset .ui-fieldset-legend-text { - vertical-align: middle; -} - -.ui-fieldset .ui-fieldset-content-wrapper-overflown { - overflow: hidden; -} \ No newline at end of file diff --git a/dashboard/src/app/components/fieldset/fieldset.spec.ts b/dashboard/src/app/components/fieldset/fieldset.spec.ts deleted file mode 100644 index 47b014d34..000000000 --- a/dashboard/src/app/components/fieldset/fieldset.spec.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { TestBed, ComponentFixture, fakeAsync, tick } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Fieldset } from './fieldset'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Fieldset', () => { - - let fieldset: Fieldset; - let fixture: ComponentFixture
; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Fieldset - ] - }); - - fixture = TestBed.createComponent(Fieldset); - fieldset = fixture.componentInstance; - }); - - it('should display the legend', () => { - fieldset.legend = 'PrimeNG Fieldset Legend'; - fixture.detectChanges(); - const headerEl = fixture.debugElement.query(By.css('.ui-fieldset-legend-text')); - expect(headerEl.nativeElement.textContent).toContain('PrimeNG Fieldset Legend') - }); - - it('should not render toggle icon when not toggleable', () => { - fixture.detectChanges(); - const toggleIcon = fixture.debugElement.query(By.css('.ui-fieldset-toggler')); - expect(toggleIcon).toBeNull(); - }); - - it('should render toggle icon when toggleable', () => { - fieldset.toggleable = true; - fixture.detectChanges(); - const toggleIcon = fixture.debugElement.query(By.css('.ui-fieldset-toggler')); - expect(toggleIcon).not.toBeNull(); - }); - - it('should toggle the fieldset when toggler is clicked', fakeAsync(() => { - fieldset.toggleable = true; - fixture.detectChanges(); - const togglerEl = fixture.nativeElement.querySelector('.ui-fieldset-legend').children[0]; - - togglerEl.click(); - expect(fieldset.collapsed).toEqual(true); - - tick(500); - - togglerEl.click(); - expect(fieldset.collapsed).toEqual(false); - })); - -}); diff --git a/dashboard/src/app/components/fieldset/fieldset.ts b/dashboard/src/app/components/fieldset/fieldset.ts deleted file mode 100644 index 631e2842d..000000000 --- a/dashboard/src/app/components/fieldset/fieldset.ts +++ /dev/null @@ -1,113 +0,0 @@ -import {NgModule,Component,Input,Output,EventEmitter,ElementRef} from '@angular/core'; -import {trigger,state,style,transition,animate} from '@angular/animations'; -import {CommonModule} from '@angular/common'; -import {SharedModule} from '../common/shared'; -import {BlockableUI} from '../common/blockableui'; - -let idx: number = 0; - -@Component({ - selector: 'p-fieldset', - template: ` -
- - - - - - - - - {{legend}} - - - -
-
- -
-
-
- `, - animations: [ - trigger('fieldsetContent', [ - state('hidden', style({ - height: '0px' - })), - state('visible', style({ - height: '*' - })), - transition('visible => hidden', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')), - transition('hidden => visible', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')) - ]) - ] -}) -export class Fieldset implements BlockableUI { - - @Input() legend: string; - - @Input() toggleable: boolean; - - @Input() collapsed: boolean = false; - - @Output() collapsedChange: EventEmitter = new EventEmitter(); - - @Output() onBeforeToggle: EventEmitter = new EventEmitter(); - - @Output() onAfterToggle: EventEmitter = new EventEmitter(); - - @Input() style: any; - - @Input() styleClass: string - - public animating: boolean; - - constructor(private el: ElementRef) {} - - id: string = `ui-fieldset-${idx++}`; - - toggle(event) { - if(this.animating) { - return false; - } - - this.animating = true; - this.onBeforeToggle.emit({originalEvent: event, collapsed: this.collapsed}); - - if(this.collapsed) - this.expand(event); - else - this.collapse(event); - - this.onAfterToggle.emit({originalEvent: event, collapsed: this.collapsed}); - event.preventDefault(); - } - - expand(event) { - this.collapsed = false; - this.collapsedChange.emit(this.collapsed); - } - - collapse(event) { - this.collapsed = true; - this.collapsedChange.emit(this.collapsed); - } - - getBlockableElement(): HTMLElement { - return this.el.nativeElement.children[0]; - } - - onToggleDone(event: Event) { - this.animating = false; - } - -} - -@NgModule({ - imports: [CommonModule], - exports: [Fieldset,SharedModule], - declarations: [Fieldset] -}) -export class FieldsetModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/fileupload/fileupload.css b/dashboard/src/app/components/fileupload/fileupload.css deleted file mode 100644 index 11b4ac301..000000000 --- a/dashboard/src/app/components/fileupload/fileupload.css +++ /dev/null @@ -1,96 +0,0 @@ -/* - * FileUpload - */ -.ui-fileupload-buttonbar .ui-fileupload-choose.ui-state-disabled input { - cursor: default; -} - -.ui-fileupload-buttonbar { - padding: .5em; - border-bottom: 0 none; -} - -.ui-fileupload-buttonbar .ui-button { - vertical-align: middle; - margin-right: .25em; -} - -.ui-fileupload-content { - padding: 1em; - position: relative; - transition: border-color .3s; -} - -.ui-fileupload-content.ui-fileupload-highlight { - border-color: #156090; -} - -.ui-fileupload-files img { - border: none; -} - -.ui-fileupload-files { - display: table; -} - -.ui-fileupload-row { - display: table-row; -} - -.ui-fileupload-row > div { - display: table-cell; - padding: .5em 1em; - vertical-align: middle; -} - -.ui-fileupload-content .ui-progressbar { - width: 100%; - position: absolute; - top: 1px; - left: 0; - height: .25em; - border: 0 none; -} - -.ui-fileupload-content .ui-progressbar-value { - -moz-border-radius: 0; - -webkit-border-radius: 0; - border-radius: 0; - border: 0 none; -} - -/* Simple */ -.ui-fileupload-choose { - position: relative; - overflow: hidden; -} - -.ui-fileupload-choose input[type=file] { - position: absolute; - top: 0; - right: 0; - margin: 0; - opacity: 0; - min-height: 100%; - font-size: 100px; - text-align: right; - filter: alpha(opacity=0); - direction: ltr; - cursor: pointer; -} - -.ui-fileupload-choose.ui-fileupload-choose-selected input[type=file] { - display: none; -} - -/* ui-fluid */ -.ui-fluid .ui-fileupload .ui-button { - width: auto; -} - -.ui-fluid .ui-fileupload-content .ui-button-icon-only { - width: 2em; -} - - - diff --git a/dashboard/src/app/components/fileupload/fileupload.spec.ts b/dashboard/src/app/components/fileupload/fileupload.spec.ts deleted file mode 100644 index 0a74fa1bf..000000000 --- a/dashboard/src/app/components/fileupload/fileupload.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { FileUpload } from './fileupload'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('FileUpload', () => { - - let fileupload: FileUpload; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - FileUpload - ] - }); - - fixture = TestBed.createComponent(FileUpload); - fileupload = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/fileupload/fileupload.ts b/dashboard/src/app/components/fileupload/fileupload.ts deleted file mode 100644 index c0f32503e..000000000 --- a/dashboard/src/app/components/fileupload/fileupload.ts +++ /dev/null @@ -1,459 +0,0 @@ -import {NgModule,Component,OnInit,OnDestroy,Input,Output,EventEmitter,TemplateRef,AfterViewInit,AfterContentInit, - ContentChildren,QueryList,ViewChild,ElementRef,NgZone} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {DomSanitizer} from '@angular/platform-browser'; -import {ButtonModule} from '../button/button'; -import {MessagesModule} from '../messages/messages'; -import {ProgressBarModule} from '../progressbar/progressbar'; -import {DomHandler} from '../dom/domhandler'; -import {Message} from '../common/message'; -import {PrimeTemplate,SharedModule} from '../common/shared'; -import {BlockableUI} from '../common/blockableui'; - -@Component({ - selector: 'p-fileUpload', - template: ` -
-
- - - - - - - - -
-
- - - - -
-
-
-
-
{{file.name}}
-
{{formatSize(file.size)}}
-
-
-
-
- -
-
- -
-
- - - {{auto ? chooseLabel : hasFiles() ? files[0].name : chooseLabel}} - - - `, - providers: [DomHandler] -}) -export class FileUpload implements OnInit,AfterViewInit,AfterContentInit,OnDestroy,BlockableUI { - - @Input() name: string; - - @Input() url: string; - - @Input() method: string = 'POST'; - - @Input() multiple: boolean; - - @Input() accept: string; - - @Input() disabled: boolean; - - @Input() auto: boolean; - - @Input() withCredentials: boolean; - - @Input() maxFileSize: number; - - @Input() invalidFileSizeMessageSummary: string = '{0}: Invalid file size, '; - - @Input() invalidFileSizeMessageDetail: string = 'maximum upload size is {0}.'; - - @Input() invalidFileTypeMessageSummary: string = '{0}: Invalid file type, '; - - @Input() invalidFileTypeMessageDetail: string = 'allowed file types: {0}.'; - - @Input() style: string; - - @Input() styleClass: string; - - @Input() previewWidth: number = 50; - - @Input() chooseLabel: string = 'Choose'; - - @Input() uploadLabel: string = 'Upload'; - - @Input() cancelLabel: string = 'Cancel'; - - @Input() showUploadButton: boolean = true; - - @Input() showCancelButton: boolean = true; - - @Input() mode: string = 'advanced'; - - @Input() customUpload: boolean; - - @Output() onBeforeUpload: EventEmitter = new EventEmitter(); - - @Output() onBeforeSend: EventEmitter = new EventEmitter(); - - @Output() onUpload: EventEmitter = new EventEmitter(); - - @Output() onError: EventEmitter = new EventEmitter(); - - @Output() onClear: EventEmitter = new EventEmitter(); - - @Output() onRemove: EventEmitter = new EventEmitter(); - - @Output() onSelect: EventEmitter = new EventEmitter(); - - @Output() onProgress: EventEmitter = new EventEmitter(); - - @Output() uploadHandler: EventEmitter = new EventEmitter(); - - @ContentChildren(PrimeTemplate) templates: QueryList; - - @ViewChild('advancedfileinput') advancedFileInput: ElementRef; - - @ViewChild('basicfileinput') basicFileInput: ElementRef; - - @ViewChild('content') content: ElementRef; - - @Input() files: File[]; - - public progress: number = 0; - - public dragHighlight: boolean; - - public msgs: Message[]; - - public fileTemplate: TemplateRef; - - public contentTemplate: TemplateRef; - - public toolbarTemplate: TemplateRef; - - focus: boolean; - - duplicateIEEvent: boolean; // flag to recognize duplicate onchange event for file input - - constructor(private el: ElementRef, public domHandler: DomHandler, public sanitizer: DomSanitizer, public zone: NgZone){} - - ngOnInit() { - this.files = []; - } - - ngAfterContentInit() { - this.templates.forEach((item) => { - switch(item.getType()) { - case 'file': - this.fileTemplate = item.template; - break; - - case 'content': - this.contentTemplate = item.template; - break; - - case 'toolbar': - this.toolbarTemplate = item.template; - break; - - default: - this.fileTemplate = item.template; - break; - } - }); - } - - ngAfterViewInit() { - if(this.mode === 'advanced') { - this.zone.runOutsideAngular(() => { - this.content.nativeElement.addEventListener('dragover', this.onDragOver.bind(this)); - }); - } - } - - onFileSelect(event) { - if(event.type !== 'drop' && this.isIE11() && this.duplicateIEEvent) { - this.duplicateIEEvent = false; - return; - } - - this.msgs = []; - if(!this.multiple) { - this.files = []; - } - - let files = event.dataTransfer ? event.dataTransfer.files : event.target.files; - for(let i = 0; i < files.length; i++) { - let file = files[i]; - - if(!this.isFileSelected(file)){ - if(this.validate(file)) { - if(this.isImage(file)) { - file.objectURL = this.sanitizer.bypassSecurityTrustUrl((window.URL.createObjectURL(files[i]))); - } - - this.files.push(files[i]); - } - } - } - - this.onSelect.emit({originalEvent: event, files: files}); - - if(this.hasFiles() && this.auto) { - this.upload(); - } - - if (event.type !== 'drop' && this.isIE11()) { - this.clearIEInput(); - } else { - this.clearInputElement(); - } - } - - isFileSelected(file: File): boolean{ - for(let sFile of this.files){ - if((sFile.name + sFile.type + sFile.size) === (file.name + file.type+file.size)) { - return true; - } - } - - return false; - } - - isIE11() { - return !!window['MSInputMethodContext'] && !!document['documentMode']; - } - - validate(file: File): boolean { - if(this.accept && !this.isFileTypeValid(file)) { - this.msgs.push({ - severity: 'error', - summary: this.invalidFileTypeMessageSummary.replace('{0}', file.name), - detail: this.invalidFileTypeMessageDetail.replace('{0}', this.accept) - }); - return false; - } - - if(this.maxFileSize && file.size > this.maxFileSize) { - this.msgs.push({ - severity: 'error', - summary: this.invalidFileSizeMessageSummary.replace('{0}', file.name), - detail: this.invalidFileSizeMessageDetail.replace('{0}', this.formatSize(this.maxFileSize)) - }); - return false; - } - - return true; - } - - private isFileTypeValid(file: File): boolean { - let acceptableTypes = this.accept.split(','); - for(let type of acceptableTypes) { - let acceptable = this.isWildcard(type) ? this.getTypeClass(file.type) === this.getTypeClass(type) - : file.type == type || this.getFileExtension(file) === type; - - if(acceptable) { - return true; - } - } - - return false; - } - - getTypeClass(fileType: string): string { - return fileType.substring(0, fileType.indexOf('/')); - } - - isWildcard(fileType: string): boolean { - return fileType.indexOf('*') !== -1; - } - - getFileExtension(file: File): string { - return '.' + file.name.split('.').pop(); - } - - isImage(file: File): boolean { - return /^image\//.test(file.type); - } - - onImageLoad(img: any) { - window.URL.revokeObjectURL(img.src); - } - - upload() { - if(this.customUpload) { - this.uploadHandler.emit({ - files: this.files - }); - } - else { - this.msgs = []; - let xhr = new XMLHttpRequest(), - formData = new FormData(); - - this.onBeforeUpload.emit({ - 'xhr': xhr, - 'formData': formData - }); - - for(let i = 0; i < this.files.length; i++) { - formData.append(this.name, this.files[i], this.files[i].name); - } - - xhr.upload.addEventListener('progress', (e: ProgressEvent) => { - if(e.lengthComputable) { - this.progress = Math.round((e.loaded * 100) / e.total); - } - - this.onProgress.emit({originalEvent: e, progress: this.progress}); - }, false); - - xhr.onreadystatechange = () => { - if(xhr.readyState == 4) { - this.progress = 0; - - if(xhr.status >= 200 && xhr.status < 300) - this.onUpload.emit({xhr: xhr, files: this.files}); - else - this.onError.emit({xhr: xhr, files: this.files}); - - this.clear(); - } - }; - - xhr.open(this.method, this.url, true); - - this.onBeforeSend.emit({ - 'xhr': xhr, - 'formData': formData - }); - - xhr.withCredentials = this.withCredentials; - - xhr.send(formData); - } - } - - clear() { - this.files = []; - this.onClear.emit(); - this.clearInputElement(); - } - - remove(event: Event, index: number) { - this.clearInputElement(); - this.onRemove.emit({originalEvent: event, file: this.files[index]}); - this.files.splice(index, 1); - } - - clearInputElement() { - if (this.advancedFileInput && this.advancedFileInput.nativeElement) { - this.advancedFileInput.nativeElement.value = ''; - } - } - - clearIEInput() { - if (this.advancedFileInput && this.advancedFileInput.nativeElement) { - this.duplicateIEEvent = true; //IE11 fix to prevent onFileChange trigger again - this.advancedFileInput.nativeElement.value = ''; - } - } - - hasFiles(): boolean { - return this.files && this.files.length > 0; - } - - onDragEnter(e) { - if(!this.disabled) { - e.stopPropagation(); - e.preventDefault(); - } - } - - onDragOver(e) { - if(!this.disabled) { - this.domHandler.addClass(this.content.nativeElement, 'ui-fileupload-highlight'); - this.dragHighlight = true; - e.stopPropagation(); - e.preventDefault(); - } - } - - onDragLeave(event) { - if(!this.disabled) { - this.domHandler.removeClass(this.content.nativeElement, 'ui-fileupload-highlight'); - } - } - - onDrop(event) { - if(!this.disabled) { - this.domHandler.removeClass(this.content.nativeElement, 'ui-fileupload-highlight'); - event.stopPropagation(); - event.preventDefault(); - - let files = event.dataTransfer ? event.dataTransfer.files : event.target.files; - let allowDrop = this.multiple||(files && files.length === 1); - - if(allowDrop) { - this.onFileSelect(event); - } - } - } - - onFocus() { - this.focus = true; - } - - onBlur() { - this.focus = false; - } - - formatSize(bytes) { - if(bytes == 0) { - return '0 B'; - } - let k = 1000, - dm = 3, - sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], - i = Math.floor(Math.log(bytes) / Math.log(k)); - - return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; - } - - onSimpleUploaderClick(event: Event) { - if(this.hasFiles()) { - this.upload(); - } - } - - getBlockableElement(): HTMLElement { - return this.el.nativeElement.children[0]; - } - - ngOnDestroy() { - if(this.content && this.content.nativeElement) { - this.content.nativeElement.removeEventListener('dragover', this.onDragOver); - } - } -} - -@NgModule({ - imports: [CommonModule,SharedModule,ButtonModule,ProgressBarModule,MessagesModule], - exports: [FileUpload,SharedModule,ButtonModule,ProgressBarModule,MessagesModule], - declarations: [FileUpload] -}) -export class FileUploadModule { } diff --git a/dashboard/src/app/components/form/form.scss b/dashboard/src/app/components/form/form.scss deleted file mode 100644 index 54f8bd931..000000000 --- a/dashboard/src/app/components/form/form.scss +++ /dev/null @@ -1,103 +0,0 @@ -.form{ - .form-item{ - margin-bottom: 0.1rem; - flex-wrap: nowrap; - .form-label{ - padding:0; - line-height: 0.32rem; - flex-shrink: 0; - &::before{ - content: "*"; - display: inline; - color: transparent; - padding-right: 0; - margin-left: -0.09rem; - } - &.required::before{ - color: $stateErrorTextColor; - } - label{ - color: map-get($map: $color-text, $key: secondary); - &::after{ - content: ":"; - display: inline; - padding-left: 0.05rem; - } - } - } - .form-content{ - .text-only{ - line-height: .32rem; - } - } - } - .hide .form-item .form-label{ - display: none; - } - .button-group{ - margin-top: 0.3rem; - } - p{ - margin-bottom: 0.2rem; - } - .form-nest{ - .form-item{ - margin-bottom: 0.1rem; - } - } - - .ui-g-1, .ui-g-2, .ui-g-3, .ui-g-4, .ui-g-5, .ui-g-6, .ui-g-7, .ui-g-8, .ui-g-9, .ui-g-10, .ui-g-11, .ui-g-12 { - padding: 0; - } -} - -.form-group-container{ - .form-item{ - margin-bottom: 0!important; - } -} - -.form > .title-secondary:first-of-type{ - margin-top: 0; -} - -.form > * > .title-secondary:first-of-type{ - margin-top: 0; -} - -[name^="form-template"]{ - display: none; -} - -.ui-message-container{ - padding: 0; - margin: 0; - animation: fadeInDown 150ms cubic-bezier(0.4, 0, 0.2, 1),fadeIn 150ms cubic-bezier(0.4, 0 0.2, 1); - animation-fill-mode: forwards; - - .ui-message{ - border: none; - margin: .05rem 0; - padding: 0; - color: $stateErrorTextColor; - } - - .ui-messages-error{ - background: inherit; - color: $stateErrorTextColor; - border: none; - list-style-type: none; - margin: 0; - padding: 10px 0 0 0 ; - } - - .fa{ - vertical-align: middle; - margin-right: 2px; - margin-top: -2px; - } - - .ui-message-error-text{ - vertical-align: middle; - } -} \ No newline at end of file diff --git a/dashboard/src/app/components/form/form.ts b/dashboard/src/app/components/form/form.ts deleted file mode 100644 index cf700a6c6..000000000 --- a/dashboard/src/app/components/form/form.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { NgModule, Component, Directive, Input, Output, ElementRef, Injector, OnInit, AfterViewInit, AfterContentChecked } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule, ReactiveFormsModule, FormGroup, AbstractControl } from '@angular/forms'; -import { Keys } from '../common/keys.pipe'; - -@Directive({ - selector: 'form' -}) - -export class Form{ - @Input() grid: {label: string, content: string }; - - @Input() errorMessage: {[key: string]: {[key: string]: any}}; - - @Input() formGroup: FormGroup; - - @Input() columns: any; - - constructor(el: ElementRef) { - el.nativeElement.classList.add('form'); - } -} - -@Component({ - selector: 'form-item', - template: ` -
-
- -
-
- -
-
- - - {{ (errorMessage && errorMessage[errKey]) || formCtrl.errors[errKey] }} - -
-
-
-
- ` -}) - -export class FormItem implements OnInit, AfterViewInit, AfterContentChecked { - - @Input() required: boolean; - - @Input() label: string; - - @Input() hide: string; - - errorMessage: {[Key:string]:{[key:string]:any}}; - - itemStyleClass: string; - - labelStyleClass: string; - - contentStyleClass: string; - - formInstance: Form; - - formCtrl: AbstractControl; - - formctrls: { name:string, formCtrl: AbstractControl, errorMessage: {[Key:string]:{[key:string]:any}}}[] = []; - - constructor( private el: ElementRef, private injector: Injector){} - - ngOnInit(): void{ - //栅格样式 - this.formInstance = this.injector.get(Form); - - if( !this.formInstance ){ - throw "require Form"; - } - - if( this.formInstance.grid ){ - this.labelStyleClass = this.formInstance.grid.label; - this.contentStyleClass = this.formInstance.grid.content; - } - - if( this.formInstance.columns ){ - let className = "ui-g-" + 12 / this.formInstance.columns; - this.itemStyleClass = className; - } - } - - ngAfterViewInit(): void{ - let ctrlElems =this.el.nativeElement.querySelectorAll(".form-content [formControlName]"); - if( this.formInstance.formGroup && ctrlElems.length > 0){ - ctrlElems.forEach(elem => { - let name = elem.getAttribute("formControlName"); - let formCtrl = this.formInstance.formGroup.get(name); - - if( formCtrl ){ - this.formctrls.push({ - name: name, - formCtrl: formCtrl, - errorMessage: this.formInstance.errorMessage && this.formInstance.errorMessage[name] - }); - } - }) - } - } - - ngAfterContentChecked(){ - this.updateFormCtrl(); - } - - //显示第一个错误 - updateFormCtrl(): void { - let firstErrorCtrl = this.formctrls.filter( item => { - let formCtrl = item.formCtrl; - return formCtrl.invalid && (formCtrl.dirty || formCtrl.touched); - })[0]; - - if( firstErrorCtrl ){ - this.formCtrl = firstErrorCtrl.formCtrl; - this.errorMessage = firstErrorCtrl.errorMessage; - } - else{ - this.formCtrl = null; - this.errorMessage = null; - } - } - -} - -@NgModule({ - imports: [CommonModule, FormsModule ], - exports: [Form, FormItem, Keys ], - declarations: [Form, FormItem, Keys ] -}) -export class FormModule{} - diff --git a/dashboard/src/app/components/galleria/galleria.css b/dashboard/src/app/components/galleria/galleria.css deleted file mode 100644 index 8226a610b..000000000 --- a/dashboard/src/app/components/galleria/galleria.css +++ /dev/null @@ -1,81 +0,0 @@ -.ui-galleria { - overflow: hidden; - visibility: hidden; - position: relative; -} - -.ui-galleria-panel-wrapper { - position: relative; - padding: 0; - margin: 0; -} - -.ui-galleria-panel { - filter: inherit; - position: absolute; - top: 0; - left: 0; - list-style-type: none; -} - -.ui-galleria-filmstrip-wrapper { - overflow: hidden; - margin: .25em auto; - position: relative; -} - -.ui-galleria-filmstrip { - list-style: none outside none; - margin: 0; - padding: 0; - width: 2340px; - z-index: 900; - position: absolute; - top: 0; - left: 0; -} - -.ui-galleria-frame { - float:left; - margin-right: 5px; - opacity: 0.3; - cursor: pointer; -} - -.ui-galleria-frame-active { - opacity: 1; -} - -.ui-galleria-frame-content { - overflow: hidden; -} - -.ui-galleria-nav-next, .ui-galleria-nav-prev { - cursor: pointer; - position: absolute; -} - -.ui-galleria-nav-prev { - left: 5px; -} - -.ui-galleria-nav-next { - right: 5px; -} - -.ui-galleria-caption { - position: absolute; - left:1px; - background-color: rgba(0,0,0,0.5); - display: none; - color: #ededed; - padding: 0.2em 1em; -} - -.ui-galleria-caption h4 { - color: #ededed; -} - -.ui-galleria-panel-content { - padding: 1em 1.4em; -} \ No newline at end of file diff --git a/dashboard/src/app/components/galleria/galleria.spec.ts b/dashboard/src/app/components/galleria/galleria.spec.ts deleted file mode 100644 index 0124eae2d..000000000 --- a/dashboard/src/app/components/galleria/galleria.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Galleria } from './galleria'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Galleria', () => { - - let galleria: Galleria; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Galleria - ] - }); - - fixture = TestBed.createComponent(Galleria); - galleria = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/galleria/galleria.ts b/dashboard/src/app/components/galleria/galleria.ts deleted file mode 100644 index cc4c6c952..000000000 --- a/dashboard/src/app/components/galleria/galleria.ts +++ /dev/null @@ -1,246 +0,0 @@ -import {NgModule,Component,ElementRef,AfterViewChecked,AfterViewInit,OnDestroy,Input,Output,EventEmitter} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; - -@Component({ - selector: 'p-galleria', - template: ` -
-
    -
  • - -
  • -
-
-
    -
  • -
    - -
    -
  • -
-
-
-
-
-

{{images[activeIndex]?.title}}

{{images[activeIndex]?.alt}}

-
-
- `, - providers: [DomHandler] -}) -export class Galleria implements AfterViewChecked,AfterViewInit,OnDestroy { - - @Input() style: any; - - @Input() styleClass: string; - - @Input() panelWidth: number = 600; - - @Input() panelHeight: number = 400; - - @Input() frameWidth: number = 60; - - @Input() frameHeight: number = 40; - - @Input() activeIndex: number = 0; - - @Input() showFilmstrip: boolean = true; - - @Input() autoPlay: boolean = true; - - @Input() transitionInterval: number = 4000; - - @Input() showCaption: boolean = true; - - @Output() onImageClicked = new EventEmitter(); - - @Output() onImageChange = new EventEmitter(); - - _images: any[]; - - slideshowActive: boolean; - - public container: any; - - public panelWrapper: any; - - public panels: any; - - public caption: any; - - public stripWrapper: any; - - public strip: any; - - public frames: any; - - public interval: any; - - public stripLeft: number = 0; - - public imagesChanged: boolean; - - public initialized: boolean; - - constructor(public el: ElementRef, public domHandler: DomHandler) {} - - ngAfterViewChecked() { - if(this.imagesChanged) { - this.stopSlideshow(); - this.render(); - this.imagesChanged = false; - } - } - - @Input() get images(): any[] { - return this._images; - } - - set images(value:any[]) { - this._images = value; - this.activeIndex = 0; - this.imagesChanged = true; - } - - ngAfterViewInit() { - this.container = this.el.nativeElement.children[0]; - this.panelWrapper = this.domHandler.findSingle(this.el.nativeElement, 'ul.ui-galleria-panel-wrapper'); - this.initialized = true; - - if(this.showFilmstrip) { - this.stripWrapper = this.domHandler.findSingle(this.container,'div.ui-galleria-filmstrip-wrapper'); - this.strip = this.domHandler.findSingle(this.stripWrapper,'ul.ui-galleria-filmstrip'); - } - - if(this.images && this.images.length) { - this.render(); - } - } - - render() { - this.panels = this.domHandler.find(this.panelWrapper, 'li.ui-galleria-panel'); - - if(this.showFilmstrip) { - this.frames = this.domHandler.find(this.strip,'li.ui-galleria-frame'); - this.stripWrapper.style.width = this.domHandler.width(this.panelWrapper) - 50 + 'px'; - this.stripWrapper.style.height = this.frameHeight + 'px'; - } - - if(this.showCaption) { - this.caption = this.domHandler.findSingle(this.container,'div.ui-galleria-caption'); - this.caption.style.bottom = this.showFilmstrip ? this.domHandler.getOuterHeight(this.stripWrapper,true) + 'px' : 0 + 'px'; - this.caption.style.width = this.domHandler.width(this.panelWrapper) + 'px'; - } - - if(this.autoPlay) { - this.startSlideshow(); - } - - this.container.style.visibility = 'visible'; - } - - startSlideshow() { - this.interval = setInterval(() => { - this.next(); - }, this.transitionInterval); - - this.slideshowActive = true; - } - - stopSlideshow() { - if(this.interval) { - clearInterval(this.interval); - } - - this.slideshowActive = false; - } - - clickNavRight() { - if(this.slideshowActive) { - this.stopSlideshow(); - } - this.next(); - } - - clickNavLeft() { - if(this.slideshowActive) { - this.stopSlideshow(); - } - this.prev(); - } - - frameClick(frame) { - if(this.slideshowActive) { - this.stopSlideshow(); - } - - this.select(this.domHandler.index(frame), false); - } - - prev() { - if(this.activeIndex !== 0) { - this.select(this.activeIndex - 1, true); - } - } - - next() { - if(this.activeIndex !== (this.panels.length-1)) { - this.select(this.activeIndex + 1, true); - } - else { - this.select(0, false); - this.stripLeft = 0; - } - } - - select(index, reposition) { - if(index !== this.activeIndex) { - let oldPanel = this.panels[this.activeIndex], - newPanel = this.panels[index]; - - this.domHandler.fadeIn(newPanel, 500); - - if(this.showFilmstrip) { - let oldFrame = this.frames[this.activeIndex], - newFrame = this.frames[index]; - - if(reposition === undefined || reposition === true) { - let frameLeft = newFrame.offsetLeft, - stepFactor = this.frameWidth + parseInt(getComputedStyle(newFrame)['margin-right'], 10), - stripLeft = this.strip.offsetLeft, - frameViewportLeft = frameLeft + stripLeft, - frameViewportRight = frameViewportLeft + this.frameWidth; - - if(frameViewportRight > this.domHandler.width(this.stripWrapper)) - this.stripLeft -= stepFactor; - else if(frameViewportLeft < 0) - this.stripLeft += stepFactor; - } - } - - this.activeIndex = index; - - this.onImageChange.emit({index: index}); - } - } - - clickImage(event, image, i) { - this.onImageClicked.emit({originalEvent: event, image: image, index: i}) - } - - ngOnDestroy() { - this.stopSlideshow(); - } - -} - -@NgModule({ - imports: [CommonModule], - exports: [Galleria], - declarations: [Galleria] -}) -export class GalleriaModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/gmap/gmap.spec.ts b/dashboard/src/app/components/gmap/gmap.spec.ts deleted file mode 100644 index e2ca75344..000000000 --- a/dashboard/src/app/components/gmap/gmap.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { GMap } from './gmap'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('GMap', () => { - - let gmap: GMap; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - GMap - ] - }); - - fixture = TestBed.createComponent(GMap); - gmap = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/gmap/gmap.ts b/dashboard/src/app/components/gmap/gmap.ts deleted file mode 100644 index cd6a72ecd..000000000 --- a/dashboard/src/app/components/gmap/gmap.ts +++ /dev/null @@ -1,165 +0,0 @@ -import {NgModule,Component,ElementRef,OnInit,AfterViewChecked,DoCheck,OnDestroy,Input,Output,EventEmitter,IterableDiffers,ChangeDetectorRef,NgZone} from '@angular/core'; -import {CommonModule} from '@angular/common'; - -declare var google: any; - -@Component({ - selector: 'p-gmap', - template: `
` -}) -export class GMap implements AfterViewChecked,DoCheck { - - @Input() style: any; - - @Input() styleClass: string; - - @Input() options: any; - - @Input() overlays: any[]; - - @Output() onMapClick: EventEmitter = new EventEmitter(); - - @Output() onOverlayClick: EventEmitter = new EventEmitter(); - - @Output() onOverlayDragStart: EventEmitter = new EventEmitter(); - - @Output() onOverlayDrag: EventEmitter = new EventEmitter(); - - @Output() onOverlayDragEnd: EventEmitter = new EventEmitter(); - - @Output() onMapReady: EventEmitter = new EventEmitter(); - - @Output() onMapDragEnd: EventEmitter = new EventEmitter(); - - @Output() onZoomChanged: EventEmitter = new EventEmitter(); - - differ: any; - - map: any; - - constructor(public el: ElementRef,differs: IterableDiffers, public cd: ChangeDetectorRef, public zone:NgZone) { - this.differ = differs.find([]).create(null); - } - - ngAfterViewChecked() { - if(!this.map && this.el.nativeElement.offsetParent) { - this.initialize(); - } - } - - initialize() { - this.map = new google.maps.Map(this.el.nativeElement.children[0], this.options); - this.onMapReady.emit({ - map: this.map - }); - - if(this.overlays) { - for(let overlay of this.overlays) { - overlay.setMap(this.map); - this.bindOverlayEvents(overlay); - } - } - - this.map.addListener('click', (event) => { - this.zone.run(() => { - this.onMapClick.emit(event); - }); - }); - - this.map.addListener('dragend', (event) => { - this.zone.run(() => { - this.onMapDragEnd.emit(event); - }); - }); - - this.map.addListener('zoom_changed', (event) => { - this.zone.run(() => { - this.onZoomChanged.emit(event); - }); - }); - } - - bindOverlayEvents(overlay: any) { - overlay.addListener('click', (event) => { - this.zone.run(() => { - this.onOverlayClick.emit({ - originalEvent: event, - 'overlay': overlay, - map: this.map - }); - }); - }); - - if(overlay.getDraggable()) { - this.bindDragEvents(overlay); - } - } - - ngDoCheck() { - let changes = this.differ.diff(this.overlays); - - if(changes && this.map) { - changes.forEachRemovedItem((record) => {record.item.setMap(null)}); - changes.forEachAddedItem((record) => { - record.item.setMap(this.map); - record.item.addListener('click', (event) => { - this.zone.run(() => { - this.onOverlayClick.emit({ - originalEvent: event, - overlay: record.item, - map: this.map - }); - }); - }); - - if(record.item.getDraggable()) { - this.bindDragEvents(record.item); - } - }); - } - } - - bindDragEvents(overlay) { - overlay.addListener('dragstart', (event) => { - this.zone.run(() => { - this.onOverlayDragStart.emit({ - originalEvent: event, - overlay: overlay, - map: this.map - }); - }); - }); - - overlay.addListener('drag', (event) => { - this.zone.run(() => { - this.onOverlayDrag.emit({ - originalEvent: event, - overlay: overlay, - map: this.map - }); - }); - }); - - overlay.addListener('dragend', (event) => { - this.zone.run(() => { - this.onOverlayDragEnd.emit({ - originalEvent: event, - overlay: overlay, - map: this.map - }); - }); - - }); - } - - getMap() { - return this.map; - } -} - -@NgModule({ - imports: [CommonModule], - exports: [GMap], - declarations: [GMap] -}) -export class GMapModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/grid/grid.css b/dashboard/src/app/components/grid/grid.css deleted file mode 100644 index 3771df8cc..000000000 --- a/dashboard/src/app/components/grid/grid.css +++ /dev/null @@ -1,774 +0,0 @@ -/* Deprecated Grid CSS */ -.ui-grid { - clear: both; - padding: 0; - margin: 0; -} - -.ui-grid::before, -.ui-grid::after { - content:""; - display:table; -} - -.ui-grid::after { - clear:both; -} - -.ui-grid .ui-grid-row { - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; - display: flex; - clear:both; -} - -.ui-grid-row::after { - clear: both; - content: ""; - display: table; -} - -.ui-grid-col-1, -.ui-grid-col-2, -.ui-grid-col-3, -.ui-grid-col-4, -.ui-grid-col-5, -.ui-grid-col-6, -.ui-grid-col-7, -.ui-grid-col-8, -.ui-grid-col-9, -.ui-grid-col-10, -.ui-grid-col-11, -.ui-grid-col-12 { - float: left; - box-sizing: border-box; -} - -.ui-grid-col-1 { - width: 8.33333%; -} - -.ui-grid-col-2 { - width: 16.66666%; -} - -.ui-grid-col-3 { - width: 25%; -} - -.ui-grid-col-4 { - width: 33.33333%; -} - -.ui-grid-col-5 { - width: 41.66666%; -} - -.ui-grid-col-6 { - width: 50%; -} - -.ui-grid-col-7 { - width: 58.33333%; -} - -.ui-grid-col-8 { - width: 66.66666%; -} - -.ui-grid-col-9 { - width: 75%; -} - -.ui-grid-col-10 { - width: 83.33333%; -} - -.ui-grid-col-11 { - width: 91.66666%; -} - -.ui-grid-col-12 { - width: 100%; -} - -@media (min-width: 480px) { - .ui-grid-fixed { - width: 480px; - } -} - -@media (min-width: 768px) { - .ui-grid-fixed { - width: 768px; - } -} - -@media (min-width: 960px) { - .ui-grid-fixed { - width: 960px; - } -} - -@media (min-width: 1024px) { - .ui-grid-fixed { - width: 1024px; - } -} - -/* Responsive */ -@media (max-width: 640px) { - .ui-grid-responsive .ui-grid-row { - display: block; - } - - .ui-grid-responsive .ui-grid-col-1, - .ui-grid-responsive .ui-grid-col-2, - .ui-grid-responsive .ui-grid-col-3, - .ui-grid-responsive .ui-grid-col-4, - .ui-grid-responsive .ui-grid-col-5, - .ui-grid-responsive .ui-grid-col-6, - .ui-grid-responsive .ui-grid-col-7, - .ui-grid-responsive .ui-grid-col-8, - .ui-grid-responsive .ui-grid-col-9, - .ui-grid-responsive .ui-grid-col-10, - .ui-grid-responsive .ui-grid-col-11, - .ui-grid-responsive .ui-grid-col-12 { - width: 100%; - float: none; - } -} - -.ui-grid.ui-grid-pad > .ui-grid-row > div { - padding: .25em .5em; -} - -/* Responsive */ -@media (max-width: 640px) { - .ui-grid-responsive .ui-grid-row { - display: block; - } - - .ui-grid-responsive .ui-grid-col-1, - .ui-grid-responsive .ui-grid-col-2, - .ui-grid-responsive .ui-grid-col-3, - .ui-grid-responsive .ui-grid-col-4, - .ui-grid-responsive .ui-grid-col-5, - .ui-grid-responsive .ui-grid-col-6, - .ui-grid-responsive .ui-grid-col-7, - .ui-grid-responsive .ui-grid-col-8, - .ui-grid-responsive .ui-grid-col-9, - .ui-grid-responsive .ui-grid-col-10, - .ui-grid-responsive .ui-grid-col-11, - .ui-grid-responsive .ui-grid-col-12 { - width: 100%; - float: none; - } -} - -/* New Grid CSS */ -.ui-g { - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; - display: flex; - flex-wrap: wrap; -} - -.ui-g::after { - clear: both; - content: ""; - display: table; -} - -.ui-g-1, -.ui-g-2, -.ui-g-3, -.ui-g-4, -.ui-g-5, -.ui-g-6, -.ui-g-7, -.ui-g-8, -.ui-g-9, -.ui-g-10, -.ui-g-11, -.ui-g-12 { - float: left; - box-sizing: border-box; - padding: 0.5em; -} - -.ui-g-1 { - width: 8.3333%; -} - -.ui-g-2 { - width: 16.6667%; -} - -.ui-g-3 { - width: 25%; -} - -.ui-g-4 { - width: 33.3333%; -} - -.ui-g-5 { - width: 41.6667%; -} - -.ui-g-6 { - width: 50%; -} - -.ui-g-7 { - width: 58.3333%; -} - -.ui-g-8 { - width: 66.6667%; -} - -.ui-g-9 { - width: 75%; -} - -.ui-g-10 { - width: 83.3333%; -} - -.ui-g-11 { - width: 91.6667%; -} - -.ui-g-12 { - width: 100%; -} - -.ui-g-offset-12 { - margin-left: 100%; -} - -.ui-g-offset-11 { - margin-left: 91.66666667%; -} - -.ui-g-offset-10 { - margin-left: 83.33333333%; -} - -.ui-g-offset-9 { - margin-left: 75%; -} - -.ui-g-offset-8 { - margin-left: 66.66666667%; -} - -.ui-g-offset-7 { - margin-left: 58.33333333%; -} - -.ui-g-offset-6 { - margin-left: 50%; -} - -.ui-g-offset-5 { - margin-left: 41.66666667%; -} - -.ui-g-offset-4 { - margin-left: 33.33333333%; -} - -.ui-g-offset-3 { - margin-left: 25%; -} - -.ui-g-offset-2 { - margin-left: 16.66666667%; -} - -.ui-g-offset-1 { - margin-left: 8.33333333%; -} - -.ui-g-offset-0 { - margin-left: 0%; -} - -@media screen and (max-width: 40em) { - .ui-sm-1, - .ui-sm-2, - .ui-sm-3, - .ui-sm-4, - .ui-sm-5, - .ui-sm-6, - .ui-sm-7, - .ui-sm-8, - .ui-sm-9, - .ui-sm-10, - .ui-sm-11, - .ui-sm-12 { - padding: 0.5em; - } - - .ui-sm-1 { - width: 8.3333%; - } - - .ui-sm-2 { - width: 16.6667%; - } - - .ui-sm-3 { - width: 25%; - } - - .ui-sm-4 { - width: 33.3333%; - } - - .ui-sm-5 { - width: 41.6667%; - } - - .ui-sm-6 { - width: 50%; - } - - .ui-sm-7 { - width: 58.3333%; - } - - .ui-sm-8 { - width: 66.6667%; - } - - .ui-sm-9 { - width: 75%; - } - - .ui-sm-10 { - width: 83.3333%; - } - - .ui-sm-11 { - width: 91.6667%; - } - - .ui-sm-12 { - width: 100%; - } - - .ui-sm-offset-12 { - margin-left: 100%; - } - - .ui-sm-offset-11 { - margin-left: 91.66666667%; - } - - .ui-sm-offset-10 { - margin-left: 83.33333333%; - } - - .ui-sm-offset-9 { - margin-left: 75%; - } - - .ui-sm-offset-8 { - margin-left: 66.66666667%; - } - - .ui-sm-offset-7 { - margin-left: 58.33333333%; - } - - .ui-sm-offset-6 { - margin-left: 50%; - } - - .ui-sm-offset-5 { - margin-left: 41.66666667%; - } - - .ui-sm-offset-4 { - margin-left: 33.33333333%; - } - - .ui-sm-offset-3 { - margin-left: 25%; - } - - .ui-sm-offset-2 { - margin-left: 16.66666667%; - } - - .ui-sm-offset-1 { - margin-left: 8.33333333%; - } - - .ui-sm-offset-0 { - margin-left: 0%; - } -} - -@media screen and (min-width: 40.063em) { - .ui-md-1, - .ui-md-2, - .ui-md-3, - .ui-md-4, - .ui-md-5, - .ui-md-6, - .ui-md-7, - .ui-md-8, - .ui-md-9, - .ui-md-10, - .ui-md-11, - .ui-md-12 { - padding: 0.5em; - } - - .ui-md-1 { - width: 8.3333%; - } - - .ui-md-2 { - width: 16.6667%; - } - - .ui-md-3 { - width: 25%; - } - - .ui-md-4 { - width: 33.3333%; - } - - .ui-md-5 { - width: 41.6667%; - } - - .ui-md-6 { - width: 50%; - } - - .ui-md-7 { - width: 58.3333%; - } - - .ui-md-8 { - width: 66.6667%; - } - - .ui-md-9 { - width: 75%; - } - - .ui-md-10 { - width: 83.3333%; - } - - .ui-md-11 { - width: 91.6667%; - } - - .ui-md-12 { - width: 100%; - } - - .ui-md-offset-12 { - margin-left: 100%; - } - - .ui-md-offset-11 { - margin-left: 91.66666667%; - } - - .ui-md-offset-10 { - margin-left: 83.33333333%; - } - - .ui-md-offset-9 { - margin-left: 75%; - } - - .ui-md-offset-8 { - margin-left: 66.66666667%; - } - - .ui-md-offset-7 { - margin-left: 58.33333333%; - } - - .ui-md-offset-6 { - margin-left: 50%; - } - - .ui-md-offset-5 { - margin-left: 41.66666667%; - } - - .ui-md-offset-4 { - margin-left: 33.33333333%; - } - - .ui-md-offset-3 { - margin-left: 25%; - } - - .ui-md-offset-2 { - margin-left: 16.66666667%; - } - - .ui-md-offset-1 { - margin-left: 8.33333333%; - } - - .ui-md-offset-0 { - margin-left: 0%; - } -} - -@media screen and (min-width: 64.063em) { - .ui-lg-1, - .ui-lg-2, - .ui-lg-3, - .ui-lg-4, - .ui-lg-5, - .ui-lg-6, - .ui-lg-7, - .ui-lg-8, - .ui-lg-9, - .ui-lg-10, - .ui-lg-11, - .ui-lg-12 { - padding: 0.5em; - } - - .ui-lg-1 { - width: 8.3333%; - } - - .ui-lg-2 { - width: 16.6667%; - } - - .ui-lg-3 { - width: 25%; - } - - .ui-lg-4 { - width: 33.3333%; - } - - .ui-lg-5 { - width: 41.6667%; - } - - .ui-lg-6 { - width: 50%; - } - - .ui-lg-7 { - width: 58.3333%; - } - - .ui-lg-8 { - width: 66.6667%; - } - - .ui-lg-9 { - width: 75%; - } - - .ui-lg-10 { - width: 83.3333%; - } - - .ui-lg-11 { - width: 91.6667%; - } - - .ui-lg-12 { - width: 100%; - } - - .ui-lg-offset-12 { - margin-left: 100%; - } - - .ui-lg-offset-11 { - margin-left: 91.66666667%; - } - - .ui-lg-offset-10 { - margin-left: 83.33333333%; - } - - .ui-lg-offset-9 { - margin-left: 75%; - } - - .ui-lg-offset-8 { - margin-left: 66.66666667%; - } - - .ui-lg-offset-7 { - margin-left: 58.33333333%; - } - - .ui-lg-offset-6 { - margin-left: 50%; - } - - .ui-lg-offset-5 { - margin-left: 41.66666667%; - } - - .ui-lg-offset-4 { - margin-left: 33.33333333%; - } - - .ui-lg-offset-3 { - margin-left: 25%; - } - - .ui-lg-offset-2 { - margin-left: 16.66666667%; - } - - .ui-lg-offset-1 { - margin-left: 8.33333333%; - } - - .ui-lg-offset-0 { - margin-left: 0%; - } -} - -@media screen and (min-width: 90.063em) { - .ui-xl-1, - .ui-xl-2, - .ui-xl-3, - .ui-xl-4, - .ui-xl-5, - .ui-xl-6, - .ui-xl-7, - .ui-xl-8, - .ui-xl-9, - .ui-xl-10, - .ui-xl-11, - .ui-xl-12 { - padding: 0.5em; - } - - .ui-xl-1 { - width: 8.3333%; - } - - .ui-xl-2 { - width: 16.6667%; - } - - .ui-xl-3 { - width: 25%; - } - - .ui-xl-4 { - width: 33.3333%; - } - - .ui-xl-5 { - width: 41.6667%; - } - - .ui-xl-6 { - width: 50%; - } - - .ui-xl-7 { - width: 58.3333%; - } - - .ui-xl-8 { - width: 66.6667%; - } - - .ui-xl-9 { - width: 75%; - } - - .ui-xl-10 { - width: 83.3333%; - } - - .ui-xl-11 { - width: 91.6667%; - } - - .ui-xl-12 { - width: 100%; - } - - .ui-xl-offset-12 { - margin-left: 100%; - } - - .ui-xl-offset-11 { - margin-left: 91.66666667%; - } - - .ui-xl-offset-10 { - margin-left: 83.33333333%; - } - - .ui-xl-offset-9 { - margin-left: 75%; - } - - .ui-xl-offset-8 { - margin-left: 66.66666667%; - } - - .ui-xl-offset-7 { - margin-left: 58.33333333%; - } - - .ui-xl-offset-6 { - margin-left: 50%; - } - - .ui-xl-offset-5 { - margin-left: 41.66666667%; - } - - .ui-xl-offset-4 { - margin-left: 33.33333333%; - } - - .ui-xl-offset-3 { - margin-left: 25%; - } - - .ui-xl-offset-2 { - margin-left: 16.66666667%; - } - - .ui-xl-offset-1 { - margin-left: 8.33333333%; - } - - .ui-xl-offset-0 { - margin-left: 0%; - } -} - -.ui-g-nopad { - padding: 0; -} diff --git a/dashboard/src/app/components/growl/growl.css b/dashboard/src/app/components/growl/growl.css deleted file mode 100644 index 228b722bd..000000000 --- a/dashboard/src/app/components/growl/growl.css +++ /dev/null @@ -1,54 +0,0 @@ -.ui-growl { - position:fixed; - top: 20px; - right: 20px; - width: 20em; -} - -.ui-growl-item-container { - position:relative; - margin:0 0 10px 0; - opacity:0.95; - filter:alpha(opacity=95); -} - -.ui-growl-item { - position: relative; - display: block; - padding: .5em 1em; -} - -.ui-growl-item p { - padding: 0; - margin: 0; -} - -.ui-growl-icon-close { - position: absolute; - top: 4px; - right: 4px; - cursor: pointer; -} - -.ui-growl-title { - font-weight: bold; - padding: 0 0 .5em 0; - display: block; -} - -.ui-growl-image { - position: absolute; - display: inline-block; - left: .5em; - top: .25em; - padding: 0; -} - -.ui-growl-message { - padding: 0 0 .25em 0; - margin-left: 2.5em; -} - -.ui-growl-message p { - font-weight: normal; -} \ No newline at end of file diff --git a/dashboard/src/app/components/growl/growl.spec.ts b/dashboard/src/app/components/growl/growl.spec.ts deleted file mode 100644 index 801a68b76..000000000 --- a/dashboard/src/app/components/growl/growl.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Growl } from './growl'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Growl', () => { - - let growl: Growl; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Growl - ] - }); - - fixture = TestBed.createComponent(Growl); - growl = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/growl/growl.ts b/dashboard/src/app/components/growl/growl.ts deleted file mode 100644 index 7b835656f..000000000 --- a/dashboard/src/app/components/growl/growl.ts +++ /dev/null @@ -1,218 +0,0 @@ -import {NgModule,Component,ElementRef,AfterViewInit,DoCheck,OnDestroy,Input,Output,ViewChild,EventEmitter,IterableDiffers,Optional} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {Message} from '../common/message'; -import {DomHandler} from '../dom/domhandler'; -import {MessageService} from '../common/messageservice'; -import {Subscription} from 'rxjs/Subscription'; - -@Component({ - selector: 'p-growl', - template: ` -
-
-
-
- -
- {{msg.summary}} -

-
-
-
-
-
- `, - providers: [DomHandler] -}) -export class Growl implements AfterViewInit,DoCheck,OnDestroy { - - @Input() life: number = 3000; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() immutable: boolean = true; - - @Input() autoZIndex: boolean = true; - - @Input() baseZIndex: number = 0; - - @Input() key: string; - - @Output() onClick: EventEmitter = new EventEmitter(); - - @Output() onHover: EventEmitter = new EventEmitter(); - - @Output() onClose: EventEmitter = new EventEmitter(); - - @Output() valueChange: EventEmitter = new EventEmitter(); - - @ViewChild('container') containerViewChild: ElementRef; - - _sticky: boolean; - - _value: Message[]; - - timeout: any; - - preventRerender: boolean; - - differ: any; - - subscription: Subscription; - - closeIconClick: boolean; - - constructor(public el: ElementRef, public domHandler: DomHandler, public differs: IterableDiffers, @Optional() public messageService: MessageService) { - this.differ = differs.find([]).create(null); - - if(messageService) { - this.subscription = messageService.messageObserver.subscribe(messages => { - if(messages) { - if(messages instanceof Array) { - let filteredMessages = messages.filter(m => this.key === m.key); - this.value = this.value ? [...this.value, ...filteredMessages] : [...filteredMessages]; - } - else if (this.key === messages.key) { - this.value = this.value ? [...this.value, ...[messages]] : [messages]; - } - } - else { - this.value = null; - } - }); - } - } - - ngAfterViewInit() { - if(!this.sticky) { - this.initTimeout(); - } - } - - @Input() get value(): Message[] { - return this._value; - } - - set value(val:Message[]) { - this._value = val; - if(this.containerViewChild && this.containerViewChild.nativeElement && this.immutable) { - this.handleValueChange(); - } - } - - @Input() get sticky(): boolean { - return this._sticky; - } - - set sticky(value: boolean) { - if(value && this.timeout) { - clearTimeout(this.timeout); - } - this._sticky = value; - } - - ngDoCheck() { - if(!this.immutable && this.containerViewChild && this.containerViewChild.nativeElement) { - let changes = this.differ.diff(this.value); - if(changes) { - this.handleValueChange(); - } - } - } - - handleValueChange() { - if(this.preventRerender) { - this.preventRerender = false; - return; - } - - if(this.autoZIndex) { - this.containerViewChild.nativeElement.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex)); - } - this.domHandler.fadeIn(this.containerViewChild.nativeElement, 250); - - if(!this.sticky) { - this.initTimeout(); - } - } - - initTimeout() { - if(this.timeout) { - clearTimeout(this.timeout); - } - this.timeout = setTimeout(() => { - this.removeAll(); - }, this.life); - } - - remove(index: number, msgel: any) { - this.closeIconClick = true; - this.domHandler.fadeOut(msgel, 250); - - setTimeout(() => { - this.preventRerender = true; - this.onClose.emit({message:this.value[index]}); - - if(this.immutable) { - this._value = this.value.filter((val,i) => i!=index); - this.valueChange.emit(this._value); - } - else { - this._value.splice(index, 1); - } - }, 250); - } - - removeAll() { - if(this.value && this.value.length) { - this.domHandler.fadeOut(this.containerViewChild.nativeElement, 250); - - setTimeout(() => { - this.value.forEach((msg,index) => this.onClose.emit({message:this.value[index]})); - if(this.immutable) { - this.value = []; - this.valueChange.emit(this.value); - } - else { - this.value.splice(0, this.value.length); - } - }, 250); - } - } - - onMessageClick(i: number) { - if(this.closeIconClick) - this.closeIconClick = false; - else - this.onClick.emit({message: this.value[i]}); - } - - onMessageHover(i: number) { - this.onHover.emit({message: this.value[i]}); - } - - ngOnDestroy() { - if(!this.sticky) { - clearTimeout(this.timeout); - } - - if(this.subscription) { - this.subscription.unsubscribe(); - } - } - -} - -@NgModule({ - imports: [CommonModule], - exports: [Growl], - declarations: [Growl] -}) -export class GrowlModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/inplace/inplace.css b/dashboard/src/app/components/inplace/inplace.css deleted file mode 100644 index 05ed40149..000000000 --- a/dashboard/src/app/components/inplace/inplace.css +++ /dev/null @@ -1,11 +0,0 @@ -.ui-inplace .ui-inplace-display { - display: inline; - cursor: pointer; - border: 0 none; - padding: .25em; - font-weight: normal; -} - -.ui-inplace .ui-inplace-content { - display: inline; -} \ No newline at end of file diff --git a/dashboard/src/app/components/inplace/inplace.spec.ts b/dashboard/src/app/components/inplace/inplace.spec.ts deleted file mode 100644 index c39a2d9fa..000000000 --- a/dashboard/src/app/components/inplace/inplace.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Inplace } from './inplace'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Inplace', () => { - - let inplace: Inplace; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Inplace - ] - }); - - fixture = TestBed.createComponent(Inplace); - inplace = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/inplace/inplace.ts b/dashboard/src/app/components/inplace/inplace.ts deleted file mode 100644 index 8270f3e18..000000000 --- a/dashboard/src/app/components/inplace/inplace.ts +++ /dev/null @@ -1,71 +0,0 @@ -import {NgModule,Component,Input,Output,EventEmitter} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {ButtonModule} from '../button/button'; - -@Component({ - selector: 'p-inplaceDisplay', - template: '' -}) -export class InplaceDisplay {} - -@Component({ - selector: 'p-inplaceContent', - template: '' -}) -export class InplaceContent {} - -@Component({ - selector: 'p-inplace', - template: ` -
-
- -
-
- - -
-
- ` -}) -export class Inplace { - - @Input() active: boolean; - - @Input() closable: boolean; - - @Input() disabled: boolean; - - @Input() style: any; - - @Input() styleClass: string; - - @Output() onActivate: EventEmitter = new EventEmitter(); - - @Output() onDeactivate: EventEmitter = new EventEmitter(); - - hover: boolean; - - activate(event) { - if(!this.disabled) { - this.active = true; - this.onActivate.emit(event); - } - } - - deactivate(event) { - if(!this.disabled) { - this.active = false; - this.hover = false; - this.onDeactivate.emit(event); - } - } -} - -@NgModule({ - imports: [CommonModule,ButtonModule], - exports: [Inplace,InplaceDisplay,InplaceContent,ButtonModule], - declarations: [Inplace,InplaceDisplay,InplaceContent] -}) -export class InplaceModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/inputmask/inputmask.spec.ts b/dashboard/src/app/components/inputmask/inputmask.spec.ts deleted file mode 100644 index c7c9c8901..000000000 --- a/dashboard/src/app/components/inputmask/inputmask.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { InputMask } from './inputmask'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('InputMask', () => { - - let inputmask: InputMask; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - InputMask - ] - }); - - fixture = TestBed.createComponent(InputMask); - inputmask = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/inputmask/inputmask.ts b/dashboard/src/app/components/inputmask/inputmask.ts deleted file mode 100644 index e3e474087..000000000 --- a/dashboard/src/app/components/inputmask/inputmask.ts +++ /dev/null @@ -1,620 +0,0 @@ -/* - Port of jQuery MaskedInput by DigitalBush as a Native Angular2 Component in Typescript without jQuery - https://github.com/digitalBush/jquery.maskedinput/ - - Copyright (c) 2007-2014 Josh Bush (digitalbush.com) - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, - copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following - conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. -*/ -import {NgModule,Component,ElementRef,OnInit,OnDestroy,HostBinding,HostListener,Input,forwardRef,Output,EventEmitter,ViewChild} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; -import {InputTextModule} from '../inputtext/inputtext'; -import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; - -export const INPUTMASK_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => InputMask), - multi: true -}; - -@Component({ - selector: 'p-inputMask', - template: ``, - host: { - '[class.ui-inputwrapper-filled]': 'filled', - '[class.ui-inputwrapper-focus]': 'focus' - }, - providers: [INPUTMASK_VALUE_ACCESSOR,DomHandler] -}) -export class InputMask implements OnInit,OnDestroy,ControlValueAccessor { - - @Input() type: string = 'text'; - - @Input() slotChar: string = '_'; - - @Input() autoClear: boolean = true; - - @Input() style: string; - - @Input() inputId: string; - - @Input() styleClass: string; - - @Input() placeholder: string; - - @Input() size: number; - - @Input() maxlength: number; - - @Input() tabindex: string; - - @Input() disabled: boolean; - - @Input() readonly: boolean; - - @Input() unmask: boolean; - - @Input() name: string; - - @Input() required: boolean; - - @Input() characterPattern: string = '[A-Za-z]'; - - @ViewChild('input') inputViewChild: ElementRef; - - @Output() onComplete: EventEmitter = new EventEmitter(); - - @Output() onFocus: EventEmitter = new EventEmitter(); - - @Output() onBlur: EventEmitter = new EventEmitter(); - - value: any; - - _mask: string; - - onModelChange: Function = () => {}; - - onModelTouched: Function = () => {}; - - input: HTMLInputElement; - - filled: boolean; - - defs: any; - - tests: any[]; - - partialPosition: any; - - firstNonMaskPos: number; - - lastRequiredNonMaskPos: any; - - len: number; - - oldVal: string; - - buffer: any; - - defaultBuffer: string; - - focusText: string; - - caretTimeoutId: any; - - androidChrome: boolean; - - focus: boolean; - - constructor(public el: ElementRef, public domHandler: DomHandler) {} - - ngOnInit() { - let ua = this.domHandler.getUserAgent(); - this.androidChrome = /chrome/i.test(ua) && /android/i.test(ua); - - this.initMask(); - } - - @Input() get mask(): string { - return this._mask; - } - - set mask(val:string) { - this._mask = val; - - this.initMask(); - this.writeValue(''); - this.onModelChange(this.value); - } - - initMask() { - this.tests = []; - this.partialPosition = this.mask.length; - this.len = this.mask.length; - this.firstNonMaskPos = null; - this.defs = { - '9': '[0-9]', - 'a': this.characterPattern, - '*': `${this.characterPattern}|[0-9]` - }; - - let maskTokens = this.mask.split(''); - for(let i = 0; i < maskTokens.length; i++) { - let c = maskTokens[i]; - if (c == '?') { - this.len--; - this.partialPosition = i; - } - else if (this.defs[c]) { - this.tests.push(new RegExp(this.defs[c])); - if(this.firstNonMaskPos === null) { - this.firstNonMaskPos = this.tests.length - 1; - } - if(i < this.partialPosition){ - this.lastRequiredNonMaskPos = this.tests.length - 1; - } - } - else { - this.tests.push(null); - } - } - - this.buffer = []; - for(let i = 0; i < maskTokens.length; i++) { - let c = maskTokens[i]; - if(c != '?') { - if(this.defs[c]) - this.buffer.push(this.getPlaceholder(i)); - else - this.buffer.push(c); - } - } - this.defaultBuffer = this.buffer.join(''); - } - - writeValue(value: any) : void { - this.value = value; - - if(this.inputViewChild.nativeElement) { - if(this.value == undefined || this.value == null) - this.inputViewChild.nativeElement.value = ''; - else - this.inputViewChild.nativeElement.value = this.value; - - this.checkVal(); - this.focusText = this.inputViewChild.nativeElement.value; - this.updateFilledState(); - } - } - - registerOnChange(fn: Function): void { - this.onModelChange = fn; - } - - registerOnTouched(fn: Function): void { - this.onModelTouched = fn; - } - - setDisabledState(val: boolean): void { - this.disabled = val; - } - - caret(first?: number, last?: number) { - let range, begin, end; - - if(!this.inputViewChild.nativeElement.offsetParent||this.inputViewChild.nativeElement !== document.activeElement) { - return; - } - - if(typeof first == 'number') { - begin = first; - end = (typeof last === 'number') ? last : begin; - if(this.inputViewChild.nativeElement.setSelectionRange) { - this.inputViewChild.nativeElement.setSelectionRange(begin, end); - } - else if(this.inputViewChild.nativeElement['createTextRange']) { - range = this.inputViewChild.nativeElement['createTextRange'](); - range.collapse(true); - range.moveEnd('character', end); - range.moveStart('character', begin); - range.select(); - } - } - else { - if (this.inputViewChild.nativeElement.setSelectionRange) { - begin = this.inputViewChild.nativeElement.selectionStart; - end = this.inputViewChild.nativeElement.selectionEnd; - } - else if (document['selection'] && document['selection'].createRange) { - range = document['selection'].createRange(); - begin = 0 - range.duplicate().moveStart('character', -100000); - end = begin + range.text.length; - } - - return {begin: begin, end: end}; - } - } - - isCompleted(): boolean { - let completed: boolean; - for (let i = this.firstNonMaskPos; i <= this.lastRequiredNonMaskPos; i++) { - if (this.tests[i] && this.buffer[i] === this.getPlaceholder(i)) { - return false; - } - } - - return true; - } - - getPlaceholder(i: number) { - if(i < this.slotChar.length) { - return this.slotChar.charAt(i); - } - return this.slotChar.charAt(0); - } - - seekNext(pos) { - while (++pos < this.len && !this.tests[pos]); - return pos; - } - - seekPrev(pos) { - while (--pos >= 0 && !this.tests[pos]); - return pos; - } - - shiftL(begin:number,end:number) { - let i, j; - - if (begin<0) { - return; - } - - for (i = begin, j = this.seekNext(end); i < this.len; i++) { - if (this.tests[i]) { - if (j < this.len && this.tests[i].test(this.buffer[j])) { - this.buffer[i] = this.buffer[j]; - this.buffer[j] = this.getPlaceholder(j); - } else { - break; - } - - j = this.seekNext(j); - } - } - this.writeBuffer(); - this.caret(Math.max(this.firstNonMaskPos, begin)); - } - - shiftR(pos) { - let i, c, j, t; - - for (i = pos, c = this.getPlaceholder(pos); i < this.len; i++) { - if (this.tests[i]) { - j = this.seekNext(i); - t = this.buffer[i]; - this.buffer[i] = c; - if (j < this.len && this.tests[j].test(t)) { - c = t; - } else { - break; - } - } - } - } - - handleAndroidInput(e) { - var curVal = this.inputViewChild.nativeElement.value; - var pos = this.caret(); - if (this.oldVal && this.oldVal.length && this.oldVal.length > curVal.length ) { - // a deletion or backspace happened - this.checkVal(true); - while (pos.begin > 0 && !this.tests[pos.begin-1]) - pos.begin--; - if (pos.begin === 0) - { - while (pos.begin < this.firstNonMaskPos && !this.tests[pos.begin]) - pos.begin++; - } - this.caret(pos.begin,pos.begin); - } else { - this.checkVal(true); - const newPos = this.seekNext(pos.begin); - - setTimeout(() => this.caret(newPos, newPos)); - } - - setTimeout(() => { - this.updateModel(e); - if (this.isCompleted()) { - this.onComplete.emit(); - } - }, 0); - } - - onInputBlur(e) { - this.focus = false; - this.onModelTouched(); - this.checkVal(); - this.updateModel(e); - this.updateFilledState(); - this.onBlur.emit(e); - - if (this.inputViewChild.nativeElement.value != this.focusText) { - let event = document.createEvent('HTMLEvents'); - event.initEvent('change', true, false); - this.inputViewChild.nativeElement.dispatchEvent(event); - } - } - - onKeyDown(e) { - if (this.readonly) { - return; - } - - let k = e.which||e.keyCode, - pos, - begin, - end; - let iPhone = /iphone/i.test(this.domHandler.getUserAgent()); - this.oldVal = this.inputViewChild.nativeElement.value; - - //backspace, delete, and escape get special treatment - if (k === 8 || k === 46 || (iPhone && k === 127)) { - pos = this.caret(); - begin = pos.begin; - end = pos.end; - - - if (end - begin === 0) { - begin=k!==46?this.seekPrev(begin):(end=this.seekNext(begin-1)); - end=k===46?this.seekNext(end):end; - } - - this.clearBuffer(begin, end); - this.shiftL(begin, end - 1); - this.updateModel(e); - - e.preventDefault(); - } else if( k === 13 ) { // enter - this.onInputBlur(e); - this.updateModel(e); - } else if (k === 27) { // escape - this.inputViewChild.nativeElement.value = this.focusText; - this.caret(0, this.checkVal()); - this.updateModel(e); - e.preventDefault(); - } - } - - onKeyPress(e) { - if (this.readonly){ - return; - } - - var k = e.which || e.keyCode, - pos = this.caret(), - p, - c, - next, - completed; - - if (e.ctrlKey || e.altKey || e.metaKey || k < 32) {//Ignore - return; - } else if ( k && k !== 13 ) { - if (pos.end - pos.begin !== 0){ - this.clearBuffer(pos.begin, pos.end); - this.shiftL(pos.begin, pos.end-1); - } - - p = this.seekNext(pos.begin - 1); - if (p < this.len) { - c = String.fromCharCode(k); - if (this.tests[p].test(c)) { - this.shiftR(p); - - this.buffer[p] = c; - this.writeBuffer(); - next = this.seekNext(p); - - if(/android/i.test(this.domHandler.getUserAgent())){ - //Path for CSP Violation on FireFox OS 1.1 - let proxy = () => { - this.caret(next); - }; - - setTimeout(proxy,0); - }else{ - this.caret(next); - } - if(pos.begin <= this.lastRequiredNonMaskPos){ - completed = this.isCompleted(); - } - } - } - e.preventDefault(); - } - - this.updateModel(e); - - this.updateFilledState(); - - if(completed) { - this.onComplete.emit(); - } - } - - clearBuffer(start, end) { - let i; - for (i = start; i < end && i < this.len; i++) { - if (this.tests[i]) { - this.buffer[i] = this.getPlaceholder(i); - } - } - } - - writeBuffer() { - this.inputViewChild.nativeElement.value = this.buffer.join(''); - } - - checkVal(allow?: boolean) { - //try to place characters where they belong - let test = this.inputViewChild.nativeElement.value, - lastMatch = -1, - i, - c, - pos; - - for (i = 0, pos = 0; i < this.len; i++) { - if (this.tests[i]) { - this.buffer[i] = this.getPlaceholder(i); - while (pos++ < test.length) { - c = test.charAt(pos - 1); - if (this.tests[i].test(c)) { - this.buffer[i] = c; - lastMatch = i; - break; - } - } - if (pos > test.length) { - this.clearBuffer(i + 1, this.len); - break; - } - } else { - if (this.buffer[i] === test.charAt(pos)) { - pos++; - } - if( i < this.partialPosition){ - lastMatch = i; - } - } - } - if (allow) { - this.writeBuffer(); - } else if (lastMatch + 1 < this.partialPosition) { - if (this.autoClear || this.buffer.join('') === this.defaultBuffer) { - // Invalid value. Remove it and replace it with the - // mask, which is the default behavior. - if(this.inputViewChild.nativeElement.value) this.inputViewChild.nativeElement.value = ''; - this.clearBuffer(0, this.len); - } else { - // Invalid value, but we opt to show the value to the - // user and allow them to correct their mistake. - this.writeBuffer(); - } - } else { - this.writeBuffer(); - this.inputViewChild.nativeElement.value = this.inputViewChild.nativeElement.value.substring(0, lastMatch + 1); - } - return (this.partialPosition ? i : this.firstNonMaskPos); - } - - onInputFocus(event) { - if (this.readonly){ - return; - } - - this.focus = true; - - clearTimeout(this.caretTimeoutId); - let pos; - - this.focusText = this.inputViewChild.nativeElement.value; - - pos = this.checkVal(); - - this.caretTimeoutId = setTimeout(() => { - if(this.inputViewChild.nativeElement !== document.activeElement){ - return; - } - this.writeBuffer(); - if (pos == this.mask.replace("?","").length) { - this.caret(0, pos); - } else { - this.caret(pos); - } - }, 10); - - this.onFocus.emit(event); - } - - onInput(event) { - if (this.androidChrome) - this.handleAndroidInput(event); - else - this.handleInputChange(event); - } - - handleInputChange(event) { - if (this.readonly){ - return; - } - - setTimeout(() => { - var pos = this.checkVal(true); - this.caret(pos); - this.updateModel(event); - if(this.isCompleted()) { - this.onComplete.emit(); - } - }, 0); - } - - getUnmaskedValue() { - let unmaskedBuffer = []; - for(let i = 0; i < this.buffer.length; i++) { - let c = this.buffer[i]; - if(this.tests[i] && c != this.getPlaceholder(i)) { - unmaskedBuffer.push(c); - } - } - - return unmaskedBuffer.join(''); - } - - updateModel(e) { - const updatedValue = this.unmask ? this.getUnmaskedValue() : e.target.value; - if(updatedValue) { - this.value = updatedValue; - this.onModelChange(this.value); - } - } - - updateFilledState() { - this.filled = this.inputViewChild.nativeElement && this.inputViewChild.nativeElement.value != ''; - } - - ngOnDestroy() { - - } -} - -@NgModule({ - imports: [CommonModule,InputTextModule], - exports: [InputMask], - declarations: [InputMask] -}) -export class InputMaskModule { } diff --git a/dashboard/src/app/components/inputswitch/inputswitch.css b/dashboard/src/app/components/inputswitch/inputswitch.css deleted file mode 100644 index da01d4378..000000000 --- a/dashboard/src/app/components/inputswitch/inputswitch.css +++ /dev/null @@ -1,58 +0,0 @@ -.ui-inputswitch { - display: inline-block; - padding: 0; - position: relative; - overflow: hidden; - cursor: pointer; - user-select: none; - -moz-user-select: none; - -khtml-user-select: none; - -webkit-user-select: none; - height: 1.5em; -} - -.ui-inputswitch .ui-inputswitch-on, -.ui-inputswitch .ui-inputswitch-off { - white-space: nowrap; - display: inline-block; - position: absolute; - top: 0; - width: auto; - overflow: hidden; - user-select: none; - -moz-user-select: none; - -khtml-user-select: none; - -webkit-user-select: none; - font-weight: bold; - height: 100%; - line-height: 1.5em; -} - -.ui-inputswitch .ui-inputswitch-on { - left: 0; - border: 0 none; -} - -.ui-inputswitch .ui-inputswitch-off { - right: 0; - text-align: right; -} - -.ui-inputswitch .ui-inputswitch-on span, -.ui-inputswitch .ui-inputswitch-off span { - display: inline-block; - text-align: center; - height: 100%; - line-height: inherit; -} - -.ui-inputswitch .ui-inputswitch-handle { - display: block; - width: 0; - position: absolute; - top: 0; - left: 0; - height: 100%; - border-top: 0 none; - border-bottom: 0 none; -} \ No newline at end of file diff --git a/dashboard/src/app/components/inputswitch/inputswitch.spec.ts b/dashboard/src/app/components/inputswitch/inputswitch.spec.ts deleted file mode 100644 index dfaddf2ce..000000000 --- a/dashboard/src/app/components/inputswitch/inputswitch.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { InputSwitch } from './inputswitch'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('InputSwitch', () => { - - let inputswitch: InputSwitch; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - InputSwitch - ] - }); - - fixture = TestBed.createComponent(InputSwitch); - inputswitch = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/inputswitch/inputswitch.ts b/dashboard/src/app/components/inputswitch/inputswitch.ts deleted file mode 100644 index f1431c5d9..000000000 --- a/dashboard/src/app/components/inputswitch/inputswitch.ts +++ /dev/null @@ -1,215 +0,0 @@ -import {NgModule,Component,ElementRef,AfterViewInit,AfterViewChecked,OnChanges,Input,forwardRef,EventEmitter,Output} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {NG_VALUE_ACCESSOR,ControlValueAccessor} from '@angular/forms'; -import {DomHandler} from '../dom/domhandler'; - -export const INPUTSWITCH_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => InputSwitch), - multi: true -}; - -@Component({ - selector: 'p-inputSwitch', - template: ` -
-
- {{offLabel}} -
-
- {{onLabel}} -
-
-
- -
-
- `, - providers: [INPUTSWITCH_VALUE_ACCESSOR,DomHandler] -}) -export class InputSwitch implements ControlValueAccessor,AfterViewInit,AfterViewChecked { - - @Input() onLabel: string = 'On'; - - @Input() offLabel: string = 'Off'; - - @Input() disabled: boolean; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() tabindex: number; - - @Input() inputId: string; - - @Input() ariaLabelTemplate: string = "InputSwitch {0}"; - - @Output() onChange: EventEmitter = new EventEmitter(); - - checked: boolean = false; - - focused: boolean = false; - - onModelChange: Function = () => {}; - - onModelTouched: Function = () => {}; - - public container: any; - - public handle: any; - - public onContainer: any; - - public offContainer: any; - - public onLabelChild: any; - - public offLabelChild: any; - - public offset: any; - - public ariaLabel: string; - - public ariaLabelledBy: string; - - initialized: boolean = false; - - constructor(public el: ElementRef, public domHandler: DomHandler) {} - - ngAfterViewInit() { - this.container = this.el.nativeElement.children[0]; - this.handle = this.domHandler.findSingle(this.el.nativeElement, 'div.ui-inputswitch-handle'); - this.onContainer = this.domHandler.findSingle(this.container,'div.ui-inputswitch-on'); - this.offContainer = this.domHandler.findSingle(this.container,'div.ui-inputswitch-off'); - this.onLabelChild = this.domHandler.findSingle(this.onContainer,'span.ui-inputswitch-onlabel'); - this.offLabelChild = this.domHandler.findSingle(this.offContainer,'span.ui-inputswitch-offlabel'); - } - - ngAfterViewChecked() { - if(this.container && this.container.offsetParent && !this.initialized) { - this.render(); - } - } - - render() { - let onContainerWidth = this.domHandler.width(this.onContainer), - offContainerWidth = this.domHandler.width(this.offContainer), - spanPadding = this.domHandler.innerWidth(this.offLabelChild) - this.domHandler.width(this.offLabelChild), - handleMargins = this.domHandler.getOuterWidth(this.handle) - this.domHandler.innerWidth(this.handle); - - var containerWidth = (onContainerWidth > offContainerWidth) ? onContainerWidth : offContainerWidth, - handleWidth = containerWidth; - - this.handle.style.width = handleWidth + 'px'; - handleWidth = this.domHandler.width(this.handle); - containerWidth = containerWidth + handleWidth + 6; - - var labelWidth = containerWidth - handleWidth - spanPadding - handleMargins; - - this.container.style.width = containerWidth + 'px'; - this.onLabelChild.style.width = labelWidth + 'px'; - this.offLabelChild.style.width = labelWidth + 'px'; - - //position - this.offContainer.style.width = (this.domHandler.width(this.container) - 5) + 'px'; - this.offset = this.domHandler.width(this.container) - this.domHandler.getOuterWidth(this.handle); - - //default value - if(this.checked) { - this.handle.style.left = this.offset + 'px'; - this.onContainer.style.width = this.offset + 'px'; - this.offLabelChild.style.marginRight = -this.offset + 'px'; - } - else { - this.onContainer.style.width = 0 + 'px'; - this.onLabelChild.style.marginLeft = -this.offset + 'px'; - } - - this.initialized = true; - } - - toggle(event,checkbox) { - if(!this.disabled) { - if(this.checked) { - this.checked = false; - this.uncheckUI(); - } - else { - this.checked = true; - this.checkUI(); - } - - this.onModelChange(this.checked); - this.onChange.emit({ - originalEvent: event, - checked: this.checked - }); - checkbox.focus(); - } - } - - checkUI() { - this.onContainer.style.width = this.offset + 'px'; - this.onLabelChild.style.marginLeft = 0 + 'px'; - this.offLabelChild.style.marginRight = -this.offset + 'px'; - this.handle.style.left = this.offset + 'px'; - this.updateAriaLabel(); - } - - uncheckUI() { - this.onContainer.style.width = 0 + 'px'; - this.onLabelChild.style.marginLeft = -this.offset + 'px'; - this.offLabelChild.style.marginRight = 0 + 'px'; - this.handle.style.left = 0 + 'px'; - this.updateAriaLabel(); - } - - onFocus(event) { - this.focused = true; - } - - onBlur(event) { - this.focused = false; - this.onModelTouched(); - } - - writeValue(checked: any) : void { - this.checked = checked; - - if(this.initialized) { - if(this.checked === true) - this.checkUI(); - else - this.uncheckUI(); - } - } - - registerOnChange(fn: Function): void { - this.onModelChange = fn; - } - - registerOnTouched(fn: Function): void { - this.onModelTouched = fn; - } - - setDisabledState(val: boolean): void { - this.disabled = val; - } - - updateAriaLabel() { - let pattern = /{(.*?)}/, - value = this.checked ? this.onLabel : this.offLabel; - - this.ariaLabel = this.ariaLabelTemplate.replace(this.ariaLabelTemplate.match(pattern)[0], value); - } -} - -@NgModule({ - imports: [CommonModule], - exports: [InputSwitch], - declarations: [InputSwitch] -}) -export class InputSwitchModule { } diff --git a/dashboard/src/app/components/inputtext/inputtext.scss b/dashboard/src/app/components/inputtext/inputtext.scss deleted file mode 100644 index 8d33f4df0..000000000 --- a/dashboard/src/app/components/inputtext/inputtext.scss +++ /dev/null @@ -1,112 +0,0 @@ -.ui-inputtext { - margin: 0; - outline: medium none; - font-weight: normal; - padding: .05rem; - min-height: 32px; - min-width: 220px; - @extend .ui-corner-all-small; -} - -.ui-widget-header .ui-inputtext, -.ui-widget-content .ui-inputtext { - font-weight: normal; -} - -.ui-fluid .ui-inputtext { - width: 100%; - min-width: 0; - box-sizing: border-box; - -webkit-box-sizing:border-box; - -moz-box-sizing: border-box; -} - -.ui-inputgroup { - display: -webkit-box; - display: -webkit-flex; - display: flex; -} - -.ui-inputgroup .ui-inputgroup-addon { - display: inline-block; - text-align: center; - min-width: 1.5em; - padding: .25em; - border-width: 1px; - border-style: solid; -} - -.ui-inputgroup .ui-inputgroup-addon + .ui-inputgroup-addon { - border-left: 0 none; -} - -.ui-inputgroup .ui-inputtext { - padding-left: .5em; -} - -.ui-inputgroup .ui-inputtext:not(:first-child) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; - border-left: 0 none; -} - -.ui-inputgroup .ui-inputtext:not(:last-child) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; - border-right: 0 none; -} - -.ui-inputgroup .ui-button { - margin-right: 0; - border-radius: 0; -} - -.ui-fluid .ui-inputgroup .ui-button { - width: auto; -} - -.ui-fluid .ui-inputgroup .ui-inputtext { - -webkit-box-flex: 1; - -webkit-flex: 1 1 auto; - -ms-flex: 1 1 auto; - flex: 1 1 auto; -} - -.ui-inputgroup .ui-chkbox, -.ui-inputgroup .ui-radiobutton { - margin-right: 0; - vertical-align: bottom; -} - -/* Floating Label */ -.ui-float-label { - display: block; - position:relative; -} - -.ui-float-label > label { - font-weight:normal; - position:absolute; - pointer-events:none; - left: .25em; - top: 50%; - margin-top: -.5em; - transition: 0.3s ease all; - -moz-transition: 0.3s ease all; - -webkit-transition: 0.3s ease all; - color: #898989; - line-height: 1; -} - -.ui-float-label > input:focus ~ label, -.ui-float-label > input.ui-state-filled ~ label, -.ui-float-label > .ui-inputwrapper-focus ~ label, -.ui-float-label > .ui-inputwrapper-filled ~ label { - top:-.75em; - font-size:12px; -} - -.ui-float-label > .input:-webkit-autofill ~ label { - top:-20px; - font-size:12px; -} \ No newline at end of file diff --git a/dashboard/src/app/components/inputtext/inputtext.spec.ts b/dashboard/src/app/components/inputtext/inputtext.spec.ts deleted file mode 100644 index 2e0d9836a..000000000 --- a/dashboard/src/app/components/inputtext/inputtext.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { InputText } from './inputtext'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('InputText', () => { - - let inputtext: InputText; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - InputText - ] - }); - - fixture = TestBed.createComponent(InputText); - inputtext = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/inputtext/inputtext.ts b/dashboard/src/app/components/inputtext/inputtext.ts deleted file mode 100644 index b1d670e7e..000000000 --- a/dashboard/src/app/components/inputtext/inputtext.ts +++ /dev/null @@ -1,42 +0,0 @@ -import {NgModule,Directive,ElementRef,HostListener,Input,DoCheck,Optional} from '@angular/core'; -import {NgModel} from '@angular/forms'; -import {CommonModule} from '@angular/common'; - -@Directive({ - selector: '[pInputText]', - host: { - '[class.ui-inputtext]': 'true', - '[class.ui-corner-all]': 'true', - '[class.ui-state-default]': 'true', - '[class.ui-widget]': 'true', - '[class.ui-state-filled]': 'filled' - } -}) -export class InputText implements DoCheck { - - filled: boolean; - - constructor(public el: ElementRef, @Optional() public ngModel: NgModel) {} - - ngDoCheck() { - this.updateFilledState(); - } - - //To trigger change detection to manage ui-state-filled for material labels when there is no value binding - @HostListener('input', ['$event']) - onInput(e) { - this.updateFilledState(); - } - - updateFilledState() { - this.filled = (this.el.nativeElement.value && this.el.nativeElement.value.length) || - (this.ngModel && this.ngModel.model); - } -} - -@NgModule({ - imports: [CommonModule], - exports: [InputText], - declarations: [InputText] -}) -export class InputTextModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/inputtextarea/inputtextarea.css b/dashboard/src/app/components/inputtextarea/inputtextarea.css deleted file mode 100644 index 3b1cb8ccc..000000000 --- a/dashboard/src/app/components/inputtextarea/inputtextarea.css +++ /dev/null @@ -1,15 +0,0 @@ -.ui-inputtextarea-resizable { - overflow: hidden; - resize:none; -} - -.ui-fluid .ui-inputtextarea { - width: 100%; -} - -.ui-float-label textarea:focus ~ label, -.ui-float-label textarea.ui-state-filled ~ label, -.ui-float-label textarea:-webkit-autofill ~ label { - top:-.75em; - font-size:12px; -} \ No newline at end of file diff --git a/dashboard/src/app/components/inputtextarea/inputtextarea.spec.ts b/dashboard/src/app/components/inputtextarea/inputtextarea.spec.ts deleted file mode 100644 index 8cfb5d61a..000000000 --- a/dashboard/src/app/components/inputtextarea/inputtextarea.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { InputTextarea } from './inputtextarea'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('InputTextarea', () => { - - let inputtextarea: InputTextarea; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - InputTextarea - ] - }); - - fixture = TestBed.createComponent(InputTextarea); - inputtextarea = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/inputtextarea/inputtextarea.ts b/dashboard/src/app/components/inputtextarea/inputtextarea.ts deleted file mode 100644 index 8fdb9be7e..000000000 --- a/dashboard/src/app/components/inputtextarea/inputtextarea.ts +++ /dev/null @@ -1,94 +0,0 @@ -import {NgModule,Directive,ElementRef,HostListener,Input,Output,OnInit,DoCheck,EventEmitter,Optional} from '@angular/core'; -import {NgModel} from '@angular/forms'; -import {CommonModule} from '@angular/common'; - -@Directive({ - selector: '[pInputTextarea]', - host: { - '[class.ui-inputtext]': 'true', - '[class.ui-corner-all]': 'true', - '[class.ui-state-default]': 'true', - '[class.ui-widget]': 'true', - '[class.ui-state-filled]': 'filled', - '[attr.rows]': 'rows', - '[attr.cols]': 'cols' - } -}) -export class InputTextarea implements OnInit,DoCheck { - - @Input() autoResize: boolean; - - @Input() rows: number; - - @Input() cols: number; - - @Output() onResize: EventEmitter = new EventEmitter(); - - rowsDefault: number; - - colsDefault: number; - - filled: boolean; - - constructor(public el: ElementRef, @Optional() public ngModel: NgModel) {} - - ngOnInit() { - this.rowsDefault = this.rows; - this.colsDefault = this.cols; - } - - ngDoCheck() { - this.updateFilledState(); - } - - //To trigger change detection to manage ui-state-filled for material labels when there is no value binding - @HostListener('input', ['$event']) - onInput(e) { - this.updateFilledState(); - } - - updateFilledState() { - this.filled = (this.el.nativeElement.value && this.el.nativeElement.value.length) || - (this.ngModel && this.ngModel.model); - } - - @HostListener('focus', ['$event']) - onFocus(e) { - if(this.autoResize) { - this.resize(e); - } - } - - @HostListener('blur', ['$event']) - onBlur(e) { - if(this.autoResize) { - this.resize(e); - } - } - - @HostListener('keyup', ['$event']) - onKeyup(e) { - if(this.autoResize) { - this.resize(e); - } - } - - resize(event?: Event) { - let linesCount = 0, - lines = this.el.nativeElement.value.split('\n'); - - for(let i = lines.length-1; i >= 0 ; --i) { - linesCount += Math.floor((lines[i].length / this.colsDefault) + 1); - } - - this.rows = (linesCount >= this.rowsDefault) ? (linesCount + 1) : this.rowsDefault; - this.onResize.emit(event||{}); - } -} - -@NgModule({ - imports: [CommonModule], - exports: [InputTextarea], - declarations: [InputTextarea] -}) -export class InputTextareaModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/keyfilter/keyfilter.spec.ts b/dashboard/src/app/components/keyfilter/keyfilter.spec.ts deleted file mode 100644 index 512f3b04e..000000000 --- a/dashboard/src/app/components/keyfilter/keyfilter.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { KeyFilter } from './keyfilter'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('KeyFilter', () => { - - let keyfilter: KeyFilter; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - KeyFilter - ] - }); - - fixture = TestBed.createComponent(KeyFilter); - keyfilter = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/keyfilter/keyfilter.ts b/dashboard/src/app/components/keyfilter/keyfilter.ts deleted file mode 100644 index c5e935513..000000000 --- a/dashboard/src/app/components/keyfilter/keyfilter.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { NgModule, Directive, ElementRef, HostBinding, HostListener, Input, forwardRef } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { DomHandler } from '../dom/domhandler'; -import { Validator, AbstractControl, NG_VALIDATORS } from '@angular/forms'; - -export const KEYFILTER_VALIDATOR: any = { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => KeyFilter), - multi: true -}; - -@Directive({ - selector: '[pKeyFilter]', - providers: [DomHandler, KEYFILTER_VALIDATOR] -}) -export class KeyFilter implements Validator { - - static DEFAULT_MASKS = { - pint: /[\d]/, - 'int': /[\d\-]/, - pnum: /[\d\.]/, - money: /[\d\.\s,]/, - num: /[\d\-\.]/, - hex: /[0-9a-f]/i, - email: /[a-z0-9_\.\-@]/i, - alpha: /[a-z_]/i, - alphanum: /[a-z0-9_]/i - }; - - static KEYS = { - TAB: 9, - RETURN: 13, - ESC: 27, - BACKSPACE: 8, - DELETE: 46 - }; - - static SAFARI_KEYS = { - 63234: 37, // left - 63235: 39, // right - 63232: 38, // up - 63233: 40, // down - 63276: 33, // page up - 63277: 34, // page down - 63272: 46, // delete - 63273: 36, // home - 63275: 35 // end - }; - - @Input() pValidateOnly: boolean; - - regex: RegExp; - - _pattern: any; - - constructor(public el: ElementRef, public domHandler: DomHandler) { } - - get pattern(): any { - return this._pattern; - } - - @Input('pKeyFilter') set pattern(_pattern: any) { - this._pattern = _pattern; - this.regex = KeyFilter.DEFAULT_MASKS[this._pattern] || this._pattern; - } - - isNavKeyPress(e: KeyboardEvent) { - let k = e.keyCode; - k = this.domHandler.getBrowser().safari ? (KeyFilter.SAFARI_KEYS[k] || k) : k; - - return (k >= 33 && k <= 40) || k == KeyFilter.KEYS.RETURN || k == KeyFilter.KEYS.TAB || k == KeyFilter.KEYS.ESC; - }; - - isSpecialKey(e: KeyboardEvent) { - let k = e.keyCode; - let c = e.charCode; - - return k == 9 || k == 13 || k == 27 || k == 16 || k == 17 ||(k >= 18 && k <= 20) || - (this.domHandler.getBrowser().opera && !e.shiftKey && (k == 8 || (k >= 33 && k <= 35) || (k >= 36 && k <= 39) || (k >= 44 && k <= 45))); - } - - - getKey(e: KeyboardEvent) { - let k = e.keyCode || e.charCode; - return this.domHandler.getBrowser().safari ? (KeyFilter.SAFARI_KEYS[k] || k) : k; - } - - getCharCode(e: KeyboardEvent) { - return e.charCode || e.keyCode || e.which; - }; - - @HostListener('keypress', ['$event']) - onKeyPress(e: KeyboardEvent) { - if(this.pValidateOnly) { - return; - } - - let browser = this.domHandler.getBrowser(); - - if (e.ctrlKey || e.altKey) { - return; - } - - let k = this.getKey(e); - if (browser.mozilla && (this.isNavKeyPress(e) || k == KeyFilter.KEYS.BACKSPACE || (k == KeyFilter.KEYS.DELETE && e.charCode == 0))) { - return; - } - - let c = this.getCharCode(e); - let cc = String.fromCharCode(c); - let ok = true; - - if (browser.mozilla && (this.isSpecialKey(e) || !cc)) { - return; - } - - ok = this.regex.test(cc); - - if (!ok) { - e.preventDefault(); - } - } - - validate(c: AbstractControl): { [key: string]: any } { - let value = this.el.nativeElement.value; - if (!this.regex.test(value)) { - return { - validatePattern: false - } - } - } - -} - -@NgModule({ - imports: [CommonModule], - exports: [KeyFilter], - declarations: [KeyFilter] -}) -export class KeyFilterModule { } diff --git a/dashboard/src/app/components/lightbox/images/loading.gif b/dashboard/src/app/components/lightbox/images/loading.gif deleted file mode 100644 index 19c67bbd0403f3f00d71bfb21a59cb6c55d482ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9427 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 { - - let lightbox: Lightbox; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Lightbox - ] - }); - - fixture = TestBed.createComponent(Lightbox); - lightbox = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/lightbox/lightbox.ts b/dashboard/src/app/components/lightbox/lightbox.ts deleted file mode 100644 index 3cf448a4b..000000000 --- a/dashboard/src/app/components/lightbox/lightbox.ts +++ /dev/null @@ -1,231 +0,0 @@ -import {NgModule,Component,ElementRef,Input,Output,Renderer2,AfterViewInit,OnDestroy} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; - -@Component({ - selector: 'p-lightbox', - template: ` -
- - - -
- - - -
-
- -
- - -
- -
-
- {{captionText}} -
-
-
- `, - providers: [DomHandler] -}) -export class Lightbox implements AfterViewInit,OnDestroy { - - @Input() images: any[]; - - @Input() type: string = 'image'; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() appendTo: any; - - @Input() easing: 'ease-out'; - - @Input() effectDuration: any = '500ms'; - - public visible: boolean; - - public loading: boolean; - - public currentImage: any; - - public captionText: string; - - public zindex: any; - - public panel: any; - - public index: number; - - public mask: any; - - public preventDocumentClickListener: boolean; - - public documentClickListener: any; - - constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2) {} - - onImageClick(event,image,i,content) { - this.index = i; - this.loading = true; - content.style.width = 32 + 'px'; - content.style.height = 32 + 'px'; - this.show(); - this.displayImage(image); - - this.preventDocumentClickListener = true; - event.preventDefault(); - } - - ngAfterViewInit() { - this.panel = this.domHandler.findSingle(this.el.nativeElement, '.ui-lightbox '); - - if(this.appendTo) { - if(this.appendTo === 'body') - document.body.appendChild(this.panel); - else - this.domHandler.appendChild(this.panel, this.appendTo); - } - - this.documentClickListener = this.renderer.listen('document', 'click', (event) => { - if(!this.preventDocumentClickListener&&this.visible) { - this.hide(event); - } - this.preventDocumentClickListener = false; - }); - } - - onLinkClick(event,content) { - this.show(); - this.preventDocumentClickListener = true; - event.preventDefault(); - } - - displayImage(image) { - setTimeout(() => { - this.currentImage = image; - this.captionText = image.title; - this.center(); - }, 1000); - } - - show() { - this.mask = document.createElement('div'); - this.mask.style.zIndex = ++DomHandler.zindex; - this.domHandler.addMultipleClasses(this.mask, 'ui-widget-overlay ui-dialog-mask'); - document.body.appendChild(this.mask); - - this.zindex = ++DomHandler.zindex; - this.center(); - this.visible = true; - } - - hide(event) { - this.captionText = null; - this.index = null; - this.currentImage = null; - this.visible = false; - this.panel.style.left = 'auto'; - this.panel.style.top = 'auto'; - - if(this.mask) { - document.body.removeChild(this.mask); - this.mask = null; - } - - event.preventDefault(); - } - - center() { - let elementWidth = this.domHandler.getOuterWidth(this.panel); - let elementHeight = this.domHandler.getOuterHeight(this.panel); - if(elementWidth == 0 && elementHeight == 0) { - this.panel.style.visibility = 'hidden'; - this.panel.style.display = 'block'; - elementWidth = this.domHandler.getOuterWidth(this.panel); - elementHeight = this.domHandler.getOuterHeight(this.panel); - this.panel.style.display = 'none'; - this.panel.style.visibility = 'visible'; - } - let viewport = this.domHandler.getViewport(); - let x = (viewport.width - elementWidth) / 2; - let y = (viewport.height - elementHeight) / 2; - - this.panel.style.left = x + 'px'; - this.panel.style.top = y + 'px'; - } - - onImageLoad(event,content) { - let image = event.target; - image.style.visibility = 'hidden'; - image.style.display = 'block'; - let imageWidth = this.domHandler.getOuterWidth(image); - let imageHeight = this.domHandler.getOuterHeight(image); - image.style.display = 'none'; - image.style.visibility = 'visible'; - - content.style.width = imageWidth + 'px'; - content.style.height = imageHeight + 'px'; - this.panel.style.left = parseInt(this.panel.style.left) + (this.domHandler.getOuterWidth(this.panel) - imageWidth) / 2 + 'px'; - this.panel.style.top = parseInt(this.panel.style.top) + (this.domHandler.getOuterHeight(this.panel) - imageHeight) / 2 + 'px'; - - setTimeout(() => { - this.domHandler.fadeIn(image, 500); - image.style.display = 'block'; - //this.captionText = this.currentImage.title; - this.loading = false; - }, parseInt(this.effectDuration)); - } - - prev(placeholder: any) { - this.captionText = null; - this.loading = true; - placeholder.style.display = 'none'; - if(this.index > 0) { - this.displayImage(this.images[--this.index]); - } - } - - next(placeholder: any) { - this.captionText = null; - this.loading = true; - placeholder.style.display = 'none'; - if(this.index <= (this.images.length - 1)) { - this.displayImage(this.images[++this.index]); - } - } - - get leftVisible():boolean { - return this.images && this.images.length && this.index != 0 && !this.loading; - } - - get rightVisible():boolean { - return this.images && this.images.length && this.index < (this.images.length - 1) && !this.loading; - } - - ngOnDestroy() { - if(this.documentClickListener) { - this.documentClickListener(); - } - - if(this.appendTo) { - this.el.nativeElement.appendChild(this.panel); - } - } - -} - -@NgModule({ - imports: [CommonModule], - exports: [Lightbox], - declarations: [Lightbox] -}) -export class LightboxModule { } diff --git a/dashboard/src/app/components/listbox/listbox.css b/dashboard/src/app/components/listbox/listbox.css deleted file mode 100644 index a73fd1364..000000000 --- a/dashboard/src/app/components/listbox/listbox.css +++ /dev/null @@ -1,72 +0,0 @@ -.ui-listbox { - padding: .25em; - width: 10em; -} - -.ui-listbox .ui-listbox-list-wrapper { - overflow:auto; -} - -.ui-listbox .ui-listbox-list { - list-style-type: none; - margin: 0; - padding: 0; -} - -.ui-listbox .ui-listbox-item { - padding: .25em; - border: 0 none; - cursor: pointer; - font-weight: normal; - margin-bottom: 1px; -} - -.ui-listbox .ui-listbox-item > span { - vertical-align: middle; -} - -.ui-listbox .ui-listbox-item:last-child { - margin-bottom: 0; -} - -.ui-listbox.ui-state-disabled .ui-listbox-item { - cursor: default; -} - -.ui-listbox-header { - margin-bottom: 0.3em; - padding: .125em .2em; - position: relative; -} - -.ui-listbox-header .ui-chkbox { - display: inline-block; - vertical-align: middle; - cursor: pointer; -} - -.ui-listbox-header .ui-listbox-filter-container { - display: inline-block; - vertical-align: middle; - position: relative; - width: 100%; -} - -.ui-listbox-header.ui-listbox-header-w-checkbox .ui-listbox-filter-container { - width: calc(100% - 2em); -} - -.ui-listbox-header .ui-listbox-filter-container .fa { - position: absolute; - top: .25em; - left: .25em; -} - -.ui-listbox-header .ui-inputtext { - padding: .125em .125em .125em 1.25em; - width: 100%; -} - -.ui-listbox-footer { - padding: .125em .2em; -} \ No newline at end of file diff --git a/dashboard/src/app/components/listbox/listbox.spec.ts b/dashboard/src/app/components/listbox/listbox.spec.ts deleted file mode 100644 index b9eb30138..000000000 --- a/dashboard/src/app/components/listbox/listbox.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Listbox } from './listbox'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Listbox', () => { - - let listbox: Listbox; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Listbox - ] - }); - - fixture = TestBed.createComponent(Listbox); - listbox = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/listbox/listbox.ts b/dashboard/src/app/components/listbox/listbox.ts deleted file mode 100644 index f7274a65a..000000000 --- a/dashboard/src/app/components/listbox/listbox.ts +++ /dev/null @@ -1,416 +0,0 @@ -import {NgModule,Component,ElementRef,Input,Output,EventEmitter,AfterContentInit,ContentChildren,ContentChild,QueryList,TemplateRef,IterableDiffers,forwardRef,ChangeDetectorRef} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {SelectItem} from '../common/selectitem'; -import {SharedModule,PrimeTemplate,Footer, Header} from '../common/shared'; -import {DomHandler} from '../dom/domhandler'; -import {ObjectUtils} from '../utils/objectutils'; -import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; - -export const LISTBOX_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => Listbox), - multi: true -}; - -@Component({ - selector: 'p-listbox', - template: ` -
-
- -
-
- -
-
-
-
- -
-
- -
-
-
- - -
-
-
-
    -
  • -
    -
    - -
    -
    - -
    -
    - {{option.label}} - -
  • -
-
- -
- `, - providers: [DomHandler,ObjectUtils,LISTBOX_VALUE_ACCESSOR] -}) -export class Listbox implements AfterContentInit,ControlValueAccessor { - - @Input() multiple: boolean; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() listStyle: any; - - @Input() readonly: boolean; - - @Input() disabled: boolean; - - @Input() checkbox: boolean = false; - - @Input() filter: boolean = false; - - @Input() filterMode: string = 'contains'; - - @Input() metaKeySelection: boolean = true; - - @Input() dataKey: string; - - @Input() showToggleAll: boolean = true; - - @Input() optionLabel: string; - - @Output() onChange: EventEmitter = new EventEmitter(); - - @Output() onDblClick: EventEmitter = new EventEmitter(); - - @ContentChild(Header) headerFacet; - - @ContentChild(Footer) footerFacet; - - @ContentChildren(PrimeTemplate) templates: QueryList; - - public itemTemplate: TemplateRef; - - public filterValue: string; - - public filtered: boolean; - - public value: any; - - public onModelChange: Function = () => { }; - - public onModelTouched: Function = () => { }; - - public checkboxClick: boolean; - - public optionTouched: boolean; - - public focus: boolean; - - public _options: any[]; - - constructor(public el: ElementRef, public domHandler: DomHandler, public objectUtils: ObjectUtils, public cd: ChangeDetectorRef) {} - - @Input() get options(): any[] { - return this._options; - } - - set options(val: any[]) { - let opts = this.optionLabel ? this.objectUtils.generateSelectItems(val, this.optionLabel) : val; - this._options = opts; - } - - ngAfterContentInit() { - this.templates.forEach((item) => { - switch(item.getType()) { - case 'item': - this.itemTemplate = item.template; - break; - - default: - this.itemTemplate = item.template; - break; - } - }); - } - - writeValue(value: any): void { - this.value = value; - this.cd.markForCheck(); - } - - registerOnChange(fn: Function): void { - this.onModelChange = fn; - } - - registerOnTouched(fn: Function): void { - this.onModelTouched = fn; - } - - setDisabledState(val: boolean): void { - this.disabled = val; - } - - onOptionClick(event, option) { - if(this.disabled) { - return; - } - - if(!this.checkboxClick) { - if(this.multiple) - this.onOptionClickMultiple(event, option); - else - this.onOptionClickSingle(event, option); - } - else { - this.checkboxClick = false; - } - - this.optionTouched = false; - } - - onOptionTouchEnd(event, option) { - if(this.disabled) { - return; - } - - this.optionTouched = true; - } - - onOptionClickSingle(event, option) { - let selected = this.isSelected(option); - let valueChanged = false; - let metaSelection = this.optionTouched ? false : this.metaKeySelection; - - if(metaSelection) { - let metaKey = (event.metaKey || event.ctrlKey); - - if(selected) { - if(metaKey) { - this.value = null; - valueChanged = true; - } - } - else { - this.value = option.value; - valueChanged = true; - } - } - else { - this.value = selected ? null : option.value; - valueChanged = true; - } - - if(valueChanged) { - this.onModelChange(this.value); - this.onChange.emit({ - originalEvent: event, - value: this.value - }); - } - } - - onOptionClickMultiple(event, option) { - let selected = this.isSelected(option); - let valueChanged = false; - let metaSelection = this.optionTouched ? false : this.metaKeySelection; - - if(metaSelection) { - let metaKey = (event.metaKey || event.ctrlKey); - - if(selected) { - if(metaKey) { - this.removeOption(option); - } - else { - this.value = [option.value]; - } - valueChanged = true; - } - else { - this.value = (metaKey) ? this.value || [] : []; - this.value = [...this.value, option.value]; - valueChanged = true; - } - } - else { - if(selected) { - this.removeOption(option); - } - else { - this.value = [...this.value||[],option.value]; - } - - valueChanged = true; - } - - if (valueChanged) { - this.onModelChange(this.value); - this.onChange.emit({ - originalEvent: event, - value: this.value - }); - } - } - - removeOption(option: any): void { - this.value = this.value.filter(val => !this.objectUtils.equals(val, option.value, this.dataKey)); - } - - isSelected(option: SelectItem) { - let selected = false; - - if(this.multiple) { - if(this.value) { - for(let val of this.value) { - if(this.objectUtils.equals(val, option.value, this.dataKey)) { - selected = true; - break; - } - } - } - } - else { - selected = this.objectUtils.equals(this.value, option.value, this.dataKey); - } - - return selected; - } - - get allChecked(): boolean { - if(this.filterValue) - return this.allFilteredSelected(); - else - return this.value && this.options && (this.value.length === this.options.length); - } - - allFilteredSelected(): boolean { - let allSelected: boolean; - if(this.value && this.options && this.options.length) { - allSelected = true; - for(let opt of this.options) { - if(this.isItemVisible(opt)) { - if(!this.isSelected(opt)) { - allSelected = false; - break; - } - } - } - } - - return allSelected; - } - - onFilter(event) { - let query = event.target.value.trim().toLowerCase(); - this.filterValue = query.length ? query : null; - } - - toggleAll(event, checkbox) { - if(this.disabled || !this.options || this.options.length === 0) { - return; - } - - if(checkbox.checked) { - this.value = []; - } - else { - if(this.options) { - this.value = []; - for(let i = 0; i < this.options.length; i++) { - let opt = this.options[i]; - if(this.isItemVisible(opt)) { - this.value.push(opt.value); - } - } - } - } - checkbox.checked = !checkbox.checked; - this.onModelChange(this.value); - this.onChange.emit({originalEvent: event, value: this.value}); - } - - isItemVisible(option: SelectItem): boolean { - if(this.filterValue) { - let visible; - - switch(this.filterMode) { - case 'startsWith': - visible = option.label.toLowerCase().indexOf(this.filterValue.toLowerCase()) === 0; - break; - - case 'contains': - visible = option.label.toLowerCase().indexOf(this.filterValue.toLowerCase()) > -1; - break; - - default: - visible = true; - } - - return visible; - } - else { - return true; - } - } - - onDoubleClick(event: Event, option: SelectItem): any { - if(this.disabled) { - return; - } - - this.onDblClick.emit({ - originalEvent: event, - value: this.value - }) - } - - onCheckboxClick(event: Event, option: SelectItem) { - if(this.disabled) { - return; - } - - this.checkboxClick = true; - let selected = this.isSelected(option); - - if(selected) { - this.removeOption(option); - } - else { - this.value = this.value ? this.value : []; - this.value = [...this.value,option.value]; - } - - this.onModelChange(this.value); - this.onChange.emit({ - originalEvent: event, - value: this.value - }); - } - - onInputFocus(event) { - this.focus = true; - } - - onInputBlur(event) { - this.focus = false; - } -} - -@NgModule({ - imports: [CommonModule, SharedModule], - exports: [Listbox, SharedModule], - declarations: [Listbox] -}) -export class ListboxModule { } - diff --git a/dashboard/src/app/components/megamenu/megamenu.css b/dashboard/src/app/components/megamenu/megamenu.css deleted file mode 100644 index 5b4c4da38..000000000 --- a/dashboard/src/app/components/megamenu/megamenu.css +++ /dev/null @@ -1,76 +0,0 @@ -.ui-megamenu { - padding: .25em; -} - -.ui-megamenu-root-list { - margin: 0; - padding: 0; - list-style: none; -} - -.ui-megamenu-root-list > .ui-menuitem { - position: relative; -} - -.ui-megamenu .ui-menuitem-link { - padding: .25em; - display: block; - text-decoration: none; -} - -.ui-megamenu-panel { - display: none; - position: absolute; - width: auto; -} - -.ui-megamenu-root-list > .ui-menuitem-active > .ui-megamenu-panel { - display: block; -} - -.ui-megamenu-panel .ui-menuitem { - margin: .125em 0; -} - -.ui-megamenu-submenu { - margin: 0; - padding: 0; - list-style: none; - width: 12.5em; -} - -.ui-megamenu-submenu-header { - padding: .25em; -} - -/* Horizontal */ -.ui-megamenu-horizontal .ui-megamenu-root-list > .ui-menuitem { - display: inline-block; -} - -/* Vertical */ -.ui-megamenu-vertical { - width: 12.5em; -} - -.ui-megamenu-vertical .ui-megamenu-root-list > .ui-menuitem { - display: block; -} - -.ui-megamenu-vertical .ui-megamenu-root-list > .ui-menuitem > .ui-menuitem-link { - position: relative; -} - -.ui-megamenu-vertical .ui-megamenu-root-list > .ui-menuitem > .ui-menuitem-link > .ui-submenu-icon { - position: absolute; - width: 1em; - height: 1em; - top: 50%; - right: 0; - margin-top: -.5em; -} - -.ui-megamenu .ui-g { - -ms-flex-wrap: nowrap; - flex-wrap: nowrap; -} \ No newline at end of file diff --git a/dashboard/src/app/components/megamenu/megamenu.spec.ts b/dashboard/src/app/components/megamenu/megamenu.spec.ts deleted file mode 100644 index f8fa4f9f0..000000000 --- a/dashboard/src/app/components/megamenu/megamenu.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { MegaMenu } from './megamenu'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('MegaMenu', () => { - - let megamenu: MegaMenu; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - MegaMenu - ] - }); - - fixture = TestBed.createComponent(MegaMenu); - megamenu = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/megamenu/megamenu.ts b/dashboard/src/app/components/megamenu/megamenu.ts deleted file mode 100644 index ef9a9fae8..000000000 --- a/dashboard/src/app/components/megamenu/megamenu.ts +++ /dev/null @@ -1,183 +0,0 @@ -import {NgModule,Component,ElementRef,AfterViewInit,Input,Output,Renderer2} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; -import {MenuItem} from '../common/menuitem'; -import {Location} from '@angular/common'; -import {RouterModule} from '@angular/router'; - -@Component({ - selector: 'p-megaMenu', - template: ` -
- -
- `, - providers: [DomHandler] -}) -export class MegaMenu { - - @Input() model: MenuItem[]; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() orientation: string = 'horizontal'; - - @Input() autoZIndex: boolean = true; - - @Input() baseZIndex: number = 0; - - activeItem: any; - - hideTimeout: any; - - constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2) {} - - onItemMouseEnter(event, item, menuitem: MenuItem) { - if(menuitem.disabled) { - return; - } - - if(this.hideTimeout) { - clearTimeout(this.hideTimeout); - this.hideTimeout = null; - } - - this.activeItem = item; - - if(menuitem.items) { - let submenu = item.children[0].nextElementSibling; - if (submenu) { - if (this.autoZIndex) { - submenu.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex)); - } - - if (this.orientation === 'horizontal') { - submenu.style.top = this.domHandler.getOuterHeight(item.children[0]) + 'px'; - submenu.style.left = '0px'; - } - else if (this.orientation === 'vertical') { - submenu.style.top = '0px'; - submenu.style.left = this.domHandler.getOuterWidth(item.children[0]) + 'px'; - } - } - } - } - - onItemMouseLeave(event, link) { - this.hideTimeout = setTimeout(() => { - this.activeItem = null; - }, 1000); - } - - itemClick(event, item: MenuItem) { - if(item.disabled) { - event.preventDefault(); - return; - } - - if(!item.url) { - event.preventDefault(); - } - - if(item.command) { - item.command({ - originalEvent: event, - item: item - }); - } - - this.activeItem = null; - } - - getColumnClass(menuitem: MenuItem) { - let length = menuitem.items ? menuitem.items.length: 0; - let columnClass; - switch(length) { - case 2: - columnClass= 'ui-g-6'; - break; - - case 3: - columnClass= 'ui-g-4'; - break; - - case 4: - columnClass= 'ui-g-3'; - break; - - case 6: - columnClass= 'ui-g-2'; - break; - - default: - columnClass= 'ui-g-12'; - break; - } - - return columnClass; - } -} - -@NgModule({ - imports: [CommonModule,RouterModule], - exports: [MegaMenu,RouterModule], - declarations: [MegaMenu] -}) -export class MegaMenuModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/menu/menu.css b/dashboard/src/app/components/menu/menu.css deleted file mode 100644 index 504d81429..000000000 --- a/dashboard/src/app/components/menu/menu.css +++ /dev/null @@ -1,34 +0,0 @@ -.ui-menu { - width: 12.5em; - padding: .25em; -} - -.ui-menu.ui-menu-dynamic { - position: absolute; - display: none; -} - -.ui-menu .ui-menu-separator { - border-width: 1px 0 0 0; -} - -.ui-menu ul { - list-style: none; - margin: 0; - padding: 0; -} - -.ui-menu .ui-submenu-header { - padding: .25em .5em; - margin: .125em 0; -} - -.ui-menu .ui-menuitem { - margin: .125em 0; -} - -.ui-menu .ui-menuitem-link { - padding: .25em; - display: block; - text-decoration: none; -} \ No newline at end of file diff --git a/dashboard/src/app/components/menu/menu.spec.ts b/dashboard/src/app/components/menu/menu.spec.ts deleted file mode 100644 index 1925e5c5e..000000000 --- a/dashboard/src/app/components/menu/menu.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Menu } from './menu'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Menu', () => { - - let menu: Menu; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Menu - ] - }); - - fixture = TestBed.createComponent(Menu); - menu = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/menu/menu.ts b/dashboard/src/app/components/menu/menu.ts deleted file mode 100644 index e4d78dd05..000000000 --- a/dashboard/src/app/components/menu/menu.ts +++ /dev/null @@ -1,188 +0,0 @@ -import {NgModule,Component,ElementRef,AfterViewInit,OnDestroy,Input,Output,Renderer2,HostListener,ViewChild,Inject,forwardRef} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; -import {MenuItem} from '../common/menuitem'; -import {RouterModule} from '@angular/router'; - -@Component({ - selector: '[pMenuItemContent]', - template: ` - - - {{item.label}} - - - - {{item.label}} - - ` -}) -export class MenuItemContent { - - @Input("pMenuItemContent") item: MenuItem; - - constructor(@Inject(forwardRef(() => Menu)) public menu: Menu) {} -} - -@Component({ - selector: 'p-menu', - template: ` -
-
    - -
  • -
  • {{submenu.label}}
  • - -
  • -
  • -
    -
    - -
  • -
  • -
    -
-
- `, - providers: [DomHandler], - host: {'(window:resize)': 'onResize($event)'} -}) -export class Menu implements AfterViewInit,OnDestroy { - - @Input() model: MenuItem[]; - - @Input() popup: boolean; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() appendTo: any; - - @Input() autoZIndex: boolean = true; - - @Input() baseZIndex: number = 0; - - @ViewChild('container') containerViewChild: ElementRef; - - container: HTMLDivElement; - - documentClickListener: any; - - preventDocumentDefault: any; - - onResizeTarget: any; - - constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2) {} - - ngAfterViewInit() { - this.container = this.containerViewChild.nativeElement; - - if(this.popup) { - if(this.appendTo) { - if(this.appendTo === 'body') - document.body.appendChild(this.container); - else - this.domHandler.appendChild(this.container, this.appendTo); - } - - this.documentClickListener = this.renderer.listen('document', 'click', () => { - if(!this.preventDocumentDefault) { - this.hide(); - } - this.preventDocumentDefault = false; - }); - } - } - - toggle(event) { - if(this.container.offsetParent) - this.hide(); - else - this.show(event); - - this.preventDocumentDefault = true; - } - - onResize(event) { - if(this.onResizeTarget && this.container.offsetParent) { - this.domHandler.absolutePosition(this.container, this.onResizeTarget); - } - } - - show(event) { - let target = event.currentTarget; - this.onResizeTarget = event.currentTarget; - this.moveOnTop(); - this.container.style.display = 'block'; - this.domHandler.absolutePosition(this.container, target); - this.domHandler.fadeIn(this.container, 250); - this.preventDocumentDefault = true; - } - - moveOnTop() { - if(this.autoZIndex) { - this.containerViewChild.nativeElement.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex)); - } - } - - hide() { - this.container.style.display = 'none'; - } - - itemClick(event, item: MenuItem) { - if(item.disabled) { - event.preventDefault(); - return; - } - - if(!item.url) { - event.preventDefault(); - } - - if(item.command) { - item.command({ - originalEvent: event, - item: item - }); - } - - if(this.popup) { - this.hide(); - } - } - - ngOnDestroy() { - if(this.popup) { - if(this.documentClickListener) { - this.documentClickListener(); - } - - if(this.appendTo) { - this.el.nativeElement.appendChild(this.container); - } - } - } - - hasSubMenu(): boolean { - if(this.model) { - for(var item of this.model) { - if(item.items) { - return true; - } - } - } - return false; - } -} - -@NgModule({ - imports: [CommonModule,RouterModule], - exports: [Menu,RouterModule], - declarations: [Menu,MenuItemContent] -}) -export class MenuModule { } diff --git a/dashboard/src/app/components/menubar/menubar.css b/dashboard/src/app/components/menubar/menubar.css deleted file mode 100644 index a7ae54758..000000000 --- a/dashboard/src/app/components/menubar/menubar.css +++ /dev/null @@ -1,70 +0,0 @@ -.ui-menubar { - padding: .25em; -} - -.ui-menubar .ui-menu-separator { - border-width: 1px 0 0 0; -} - -.ui-menubar:after { - content: ""; - clear: both; - display: table; -} - -.ui-menubar ul { - margin: 0; - padding: 0; - list-style: none; -} - -.ui-menubar .ui-menuitem-link { - display: block; - padding: .25em; - position: relative; - text-decoration: none; -} - -.ui-menubar .ui-menubar-root-list { - display: inline-block; -} - -.ui-menubar .ui-menubar-root-list > .ui-menuitem { - display: inline-block; - position: relative; -} - -.ui-menubar .ui-menubar-root-list > .ui-menuitem > .ui-menuitem-link { - padding: .5em; -} - -.ui-menubar .ui-menubar-root-list > li ul { - display: none; -} - -.ui-menubar .ui-submenu-list { - display: none; - position: absolute; - min-width: 12.5em; - padding: .25em; -} - -.ui-menubar .ui-submenu-list .ui-menuitem { - margin: .125em 0; -} - -.ui-menubar .ui-submenu-list .ui-menuitem-link .ui-submenu-icon { - position: absolute; - margin-top: -.5em; - right: 0; - top: 50%; -} - -.ui-menubar .ui-menuitem-active > .ui-submenu > .ui-submenu-list { - display: block; -} - -.ui-menubar .ui-menubar-custom { - float: right; - padding: .25em; -} \ No newline at end of file diff --git a/dashboard/src/app/components/menubar/menubar.spec.ts b/dashboard/src/app/components/menubar/menubar.spec.ts deleted file mode 100644 index ba8b45288..000000000 --- a/dashboard/src/app/components/menubar/menubar.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Menubar } from './menubar'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Menubar', () => { - - let menubar: Menubar; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Menubar - ] - }); - - fixture = TestBed.createComponent(Menubar); - menubar = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/menubar/menubar.ts b/dashboard/src/app/components/menubar/menubar.ts deleted file mode 100644 index 78403dcaf..000000000 --- a/dashboard/src/app/components/menubar/menubar.ts +++ /dev/null @@ -1,219 +0,0 @@ -import { NgModule, Component, ElementRef, Input, Renderer2, OnDestroy } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { DomHandler } from '../dom/domhandler'; -import { MenuItem } from '../common/menuitem'; -import { Location } from '@angular/common'; -import { RouterModule } from '@angular/router'; - -@Component({ - selector: 'p-menubarSub', - template: ` - - `, - providers: [DomHandler] -}) -export class MenubarSub implements OnDestroy { - - @Input() item: MenuItem; - - @Input() root: boolean; - - @Input() autoDisplay: boolean; - - @Input() autoZIndex: boolean = true; - - @Input() baseZIndex: number = 0; - - documentClickListener: any; - - menuClick: boolean; - - menuHoverActive: boolean = false; - - activeItem: any; - - hideTimeout: any; - - activeMenu: any; - - constructor(public domHandler: DomHandler, public renderer: Renderer2) { } - - onItemMenuClick(event: Event, item: HTMLLIElement, menuitem: MenuItem) { - if (!this.autoDisplay) { - - if (menuitem.disabled) { - return; - } - - this.activeItem = this.activeMenu ? (this.activeMenu.isEqualNode(item)? null: item) : item; - let nextElement = item.children[0].nextElementSibling; - if (nextElement) { - let sublist = nextElement.children[0]; - if (this.autoZIndex) { - sublist.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex)); - } - - if (this.root) { - sublist.style.top = this.domHandler.getOuterHeight(item.children[0]) + 'px'; - sublist.style.left = '0px' - } - else { - sublist.style.top = '0px'; - sublist.style.left = this.domHandler.getOuterWidth(item.children[0]) + 'px'; - } - } - - this.menuClick = true; - this.menuHoverActive = this.activeMenu ? (!this.activeMenu.isEqualNode(item)) : true; - this.activeMenu = this.activeMenu ? (this.activeMenu.isEqualNode(item)? null: item) : item; - this.bindEventListener(); - } - } - - bindEventListener() { - if (!this.documentClickListener) { - this.documentClickListener = this.renderer.listen('document', 'click',(event) => { - if (!this.menuClick) { - this.activeItem = null; - this.menuHoverActive = false; - } - this.menuClick = false; - }); - } - } - - onItemMouseEnter(event: Event, item: HTMLLIElement, menuitem: MenuItem) { - if (this.autoDisplay || (!this.autoDisplay && this.root && this.menuHoverActive)) { - if (menuitem.disabled) { - return; - } - - if(this.hideTimeout) { - clearTimeout(this.hideTimeout); - this.hideTimeout = null; - } - - this.activeItem = item; - let nextElement = item.children[0].nextElementSibling; - if (nextElement) { - let sublist = nextElement.children[0]; - sublist.style.zIndex = String(++DomHandler.zindex); - - if (this.root) { - sublist.style.top = this.domHandler.getOuterHeight(item.children[0]) + 'px'; - sublist.style.left = '0px' - } - else { - sublist.style.top = '0px'; - sublist.style.left = this.domHandler.getOuterWidth(item.children[0]) + 'px'; - } - } - - this.activeMenu = this.activeMenu ? (this.activeMenu.isEqualNode(item)? null: item) : item; - } - } - - onItemMouseLeave(event: Event) { - if (this.autoDisplay) { - this.hideTimeout = setTimeout(() => { - this.activeItem = null; - }, 1000); - } - } - - itemClick(event, item: MenuItem)  { - if (item.disabled) { - event.preventDefault(); - return; - } - - if (!item.url) { - event.preventDefault(); - } - - if (item.command) { - item.command({ - originalEvent: event, - item: item - }); - } - - this.activeItem = null; - } - - listClick(event) { - if (this.autoDisplay) { - this.activeItem = null; - } - } - - ngOnDestroy() { - if(this.documentClickListener) { - this.documentClickListener(); - this.documentClickListener = null; - } - - } - -} - -@Component({ - selector: 'p-menubar', - template: ` -
- - - -
- -
-
- `, - providers: [DomHandler] -}) -export class Menubar { - - @Input() model: MenuItem[]; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() autoDisplay: boolean = true; - - @Input() autoZIndex: boolean = true; - - @Input() baseZIndex: number = 0; - - constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2) { } -} - -@NgModule({ - imports: [CommonModule, RouterModule], - exports: [Menubar, RouterModule], - declarations: [Menubar, MenubarSub] -}) -export class MenubarModule { } diff --git a/dashboard/src/app/components/message/message.css b/dashboard/src/app/components/message/message.css deleted file mode 100644 index 897befc80..000000000 --- a/dashboard/src/app/components/message/message.css +++ /dev/null @@ -1,10 +0,0 @@ -.ui-message { - border: 1px solid; - margin: 0px .25em; - padding: .25em .5em; - display: inline-block; -} - -.ui-fluid .ui-message { - display: block; -} \ No newline at end of file diff --git a/dashboard/src/app/components/message/message.spec.ts b/dashboard/src/app/components/message/message.spec.ts deleted file mode 100644 index 2b1bde599..000000000 --- a/dashboard/src/app/components/message/message.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { UIMessage } from './message'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('UIMessage', () => { - - let message: UIMessage; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - UIMessage - ] - }); - - fixture = TestBed.createComponent(UIMessage); - message = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/message/message.ts b/dashboard/src/app/components/message/message.ts deleted file mode 100644 index f4ab23122..000000000 --- a/dashboard/src/app/components/message/message.ts +++ /dev/null @@ -1,59 +0,0 @@ -import {NgModule,Component,Input,Output,EventEmitter,Optional} from '@angular/core'; -import {CommonModule} from '@angular/common'; - -@Component({ - selector: 'p-message', - template: ` -
- - {{text}} -
- ` -}) -export class UIMessage { - - @Input() severity: string; - - @Input() text: string; - - get icon(): string { - let icon: string = null; - - if(this.severity) { - switch(this.severity) { - case 'success': - icon = 'fa fa-check'; - break; - - case 'info': - icon = 'fa fa-info-circle'; - break; - - case 'error': - icon = 'fa fa-close'; - break; - - case 'warn': - icon = 'fa fa-warning'; - break; - - default: - icon = 'fa fa-info-circle'; - break; - } - } - - return icon; - } -} - -@NgModule({ - imports: [CommonModule], - exports: [UIMessage], - declarations: [UIMessage] -}) -export class MessageModule { } diff --git a/dashboard/src/app/components/messages/messages.css b/dashboard/src/app/components/messages/messages.css deleted file mode 100644 index 4617a322d..000000000 --- a/dashboard/src/app/components/messages/messages.css +++ /dev/null @@ -1,81 +0,0 @@ -.ui-messages { - border: 1px solid; - margin: .5em 0; - padding: 1em 1em 1em .5em; - display: none; - position: relative; -} - -.ui-messages-icon { - display:inline-block; - padding: 0; - vertical-align: middle; -} - -.ui-messages-summary { - font-weight: bold; - margin-left: .25em; -} - -.ui-messages-detail { - margin-left: .25em; -} - -.ui-messages-success { - color: #2C832f; - background-color: #B4F0B6; - border-color: #B4F0B6; -} - -.ui-messages-success .ui-messages-close { - color: #2C832f; -} - -.ui-messages-info { - color: #1765A3; - background-color: #BFE0FA; - border-color: #BFE0FA; -} - -.ui-messages-info .ui-messages-close { - color: #1765A3; -} - -.ui-messages-warn { - color: #8A6714; - background-color: #FFE9B5; - border-color: #FFE9B5; -} - -.ui-messages-warn .ui-messages-close { - color: #8A6714; -} - -.ui-messages-error { - color: #AB1A0F; - background-color: #FFCBC8; - border-color: #FFCBC8; -} - -.ui-messages-error .ui-messages-close { - color: #AB1A0F; -} - -.ui-messages ul { - margin: 0; - padding: 0; - list-style-type: none; - display: inline-block; - vertical-align: middle; -} - -.ui-messages.ui-messages-noicon ul { - margin: 0 1.5em 0 0; -} - -.ui-messages .ui-messages-close { - cursor: pointer; - position: absolute; - top: 5px; - right: 5px; -} \ No newline at end of file diff --git a/dashboard/src/app/components/messages/messages.spec.ts b/dashboard/src/app/components/messages/messages.spec.ts deleted file mode 100644 index 19ded9142..000000000 --- a/dashboard/src/app/components/messages/messages.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Messages } from './messages'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Messages', () => { - - let messages: Messages; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Messages - ] - }); - - fixture = TestBed.createComponent(Messages); - messages = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/messages/messages.ts b/dashboard/src/app/components/messages/messages.ts deleted file mode 100644 index c4a5b40ef..000000000 --- a/dashboard/src/app/components/messages/messages.ts +++ /dev/null @@ -1,125 +0,0 @@ -import {NgModule,Component,OnInit,OnDestroy,Input,Output,EventEmitter,Optional} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {Message} from '../common/message'; -import {MessageService} from '../common/messageservice'; -import {Subscription} from 'rxjs/Subscription'; - -@Component({ - selector: 'p-messages', - template: ` -
- - - - -
    -
  • - - -
  • -
-
- ` -}) -export class Messages implements OnInit, OnDestroy { - - @Input() value: Message[]; - - @Input() closable: boolean = true; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() enableService: boolean = true; - - @Input() key: string; - - @Output() valueChange: EventEmitter = new EventEmitter(); - - subscription: Subscription; - - constructor(@Optional() public messageService: MessageService) {} - - ngOnInit() { - if(this.messageService && this.enableService) { - this.subscription = this.messageService.messageObserver.subscribe((messages: any) => { - if(messages) { - if(messages instanceof Array) { - let filteredMessages = messages.filter(m => this.key === m.key); - this.value = this.value ? [...this.value, ...filteredMessages] : [...filteredMessages]; - } - else if (this.key === messages.key) { - this.value = this.value ? [...this.value, ...[messages]] : [messages]; - } - } - else { - this.value = null; - } - }); - } - } - - hasMessages() { - return this.value && this.value.length > 0; - } - - getSeverityClass() { - return this.value[0].severity; - } - - clear(event) { - this.value = []; - this.valueChange.emit(this.value); - - event.preventDefault(); - } - - get icon(): string { - let icon: string = null; - if(this.hasMessages()) { - let msg = this.value[0]; - switch(msg.severity) { - case 'success': - icon = 'fa-check'; - break; - - case 'info': - icon = 'fa-info-circle'; - break; - - case 'error': - icon = 'fa-close'; - break; - - case 'warn': - icon = 'fa-warning'; - break; - - default: - icon = 'fa-info-circle'; - break; - } - } - - return icon; - } - - ngOnDestroy() { - if(this.subscription) { - this.subscription.unsubscribe(); - } - } -} - -@NgModule({ - imports: [CommonModule], - exports: [Messages], - declarations: [Messages] -}) -export class MessagesModule { } diff --git a/dashboard/src/app/components/msgbox/msgbox.ts b/dashboard/src/app/components/msgbox/msgbox.ts deleted file mode 100644 index 5fd43330c..000000000 --- a/dashboard/src/app/components/msgbox/msgbox.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { NgModule, Component, Input, Pipe } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; -import { DialogModule } from '../dialog/dialog'; - -@Pipe({ name: 'safeHtml'}) -export class Safe{ - constructor(private sanitizer: DomSanitizer){} - - transform (style): SafeHtml { - return this.sanitizer.bypassSecurityTrustHtml(style); - } -} - -@Component({ - template:` - -
-
- -
-
-

{{config.title}}

-

-
-
-
` -}) - -export class MsgBox{ - @Input() config; -} - -@NgModule({ - imports: [DialogModule, CommonModule], - entryComponents: [MsgBox], - exports: [MsgBox], - declarations: [MsgBox, Safe] -}) - -export class MsgBoxModule{} \ No newline at end of file diff --git a/dashboard/src/app/components/multiselect/multiselect.css b/dashboard/src/app/components/multiselect/multiselect.css deleted file mode 100644 index f0d98e5ca..000000000 --- a/dashboard/src/app/components/multiselect/multiselect.css +++ /dev/null @@ -1,149 +0,0 @@ -.ui-multiselect { - display: inline-block; - position: relative; - width: 220px; - height: 32px; - cursor: pointer; -} - -.ui-multiselect .ui-multiselect-trigger { - border-right: none; - border-top: none; - border-bottom: none; - cursor: pointer; - width: 1.5em; - height: 100%; - position: absolute; - right: 0; - top: 0; - padding: 0 .25em; -} - -.ui-multiselect .ui-multiselect-trigger .fa { - margin-top: .4em; - margin-left: -0.25em; -} - -.ui-multiselect .ui-multiselect-label-container { - overflow: hidden; -} - -.ui-multiselect .ui-multiselect-label { - display: block; - padding: .25em 2em .25em .25em; - line-height: 22px; - width: auto; - border: none; - cursor: pointer; - text-overflow: ellipsis; - overflow: hidden; -} - -.ui-multiselect.ui-state-disabled .ui-multiselect-trigger, -.ui-multiselect.ui-state-disabled .ui-multiselect-label { - cursor: auto -} - -.ui-multiselect-panel { - padding: 0.2em; - position: absolute; - min-width: 12em; -} - -.ui-multiselect .ui-multiselect-panel { - min-width: 100%; - display: none; -} - -.ui-multiselect-panel .ui-multiselect-items-wrapper { - overflow: auto; - position: relative; - padding: 0.2em 0; -} - -.ui-multiselect-panel .ui-multiselect-list { - border: 0 none; -} - -.ui-multiselect-panel .ui-multiselect-item { - border: 0 none; - cursor: pointer; - font-weight: normal; - margin: 1px 0; - padding: .125em .25em; - text-align: left; - white-space: nowrap; - display: block; - position: relative; -} - -.ui-multiselect-panel .ui-multiselect-item .ui-chkbox { - display: inline-block; - vertical-align: middle; -} - -.ui-multiselect-panel .ui-multiselect-item label { - display: inline-block; - vertical-align: middle; -} - -.ui-multiselect-header { - margin-bottom: 0.3em; - padding: .25em; - position: relative; - text-align: left; - min-height: 2em; -} - -.ui-multiselect-header .ui-chkbox { - display: inline-block; - vertical-align: middle; - cursor:pointer; -} - -.ui-multiselect-header .ui-multiselect-filter-container { - position: relative; - display: inline-block; - vertical-align: middle; - width: 65%; -} - -.ui-multiselect-header.ui-multiselect-header-no-toggleall .ui-multiselect-filter-container { - width: 85%; -} - -.ui-multiselect-header .ui-multiselect-filter-container .fa { - position: absolute; - top: .25em; - left: .125em; -} - -.ui-multiselect-header .ui-inputtext { - padding: .125em .125em .125em 1.25em; - width: 100%; -} - -.ui-multiselect-header .ui-multiselect-close { - position: absolute; - right: .375em; - top: .375em; - display: block; - font-size: 1em; - border: 0 none; -} - -.ui-multiselect-header a.ui-multiselect-all, -.ui-multiselect-header a.ui-multiselect-none { - float:left; - margin-right: 10px; - display: block; -} - -.ui-multiselect-header .ui-multiselect-close.ui-state-hover { - padding:0px; -} - -.ui-fluid .ui-multiselect { - width: 100%; - box-sizing: border-box; -} diff --git a/dashboard/src/app/components/multiselect/multiselect.spec.ts b/dashboard/src/app/components/multiselect/multiselect.spec.ts deleted file mode 100644 index 028afa5e0..000000000 --- a/dashboard/src/app/components/multiselect/multiselect.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { MultiSelect } from './multiselect'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('MultiSelect', () => { - - let multiselect: MultiSelect; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - MultiSelect - ] - }); - - fixture = TestBed.createComponent(MultiSelect); - multiselect = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/multiselect/multiselect.ts b/dashboard/src/app/components/multiselect/multiselect.ts deleted file mode 100644 index 288114225..000000000 --- a/dashboard/src/app/components/multiselect/multiselect.ts +++ /dev/null @@ -1,504 +0,0 @@ -import {NgModule,Component,ElementRef,OnInit,AfterViewInit,AfterContentInit,AfterViewChecked,OnDestroy,Input,Output,Renderer2,EventEmitter, - forwardRef,ViewChild,ChangeDetectorRef,TemplateRef,ContentChildren,QueryList} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {SelectItem} from '../common/selectitem'; -import {DomHandler} from '../dom/domhandler'; -import {ObjectUtils} from '../utils/objectutils'; -import {SharedModule,PrimeTemplate} from '../common/shared'; -import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; - -export const MULTISELECT_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MultiSelect), - multi: true -}; - -@Component({ - selector: 'p-multiSelect', - template: ` -
-
- -
-
- -
-
- -
-
-
-
-
- -
-
- -
-
-
- - -
- - - -
-
-
    -
  • -
    -
    - -
    -
    - -
    -
    - - -
  • -
-
-
-
- `, - host: { - '[class.ui-inputwrapper-filled]': 'filled', - '[class.ui-inputwrapper-focus]': 'focus' - }, - providers: [DomHandler,ObjectUtils,MULTISELECT_VALUE_ACCESSOR] -}) -export class MultiSelect implements OnInit,AfterViewInit,AfterContentInit,AfterViewChecked,OnDestroy,ControlValueAccessor { - - @Input() scrollHeight: string = '200px'; - - @Input() defaultLabel: string = 'Choose'; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() panelStyle: any; - - @Input() panelStyleClass: string; - - @Input() inputId: string; - - @Input() disabled: boolean; - - @Input() filter: boolean = true; - - @Input() filterPlaceHolder: string; - - @Input() overlayVisible: boolean; - - @Input() tabindex: number; - - @Input() appendTo: any; - - @Input() dataKey: string; - - @Input() displaySelectedLabel: boolean = true; - - @Input() maxSelectedLabels: number = 3; - - @Input() selectedItemsLabel: string = '{0} items selected'; - - @Input() showToggleAll: boolean = true; - - @Input() resetFilterOnHide: boolean = false; - - @Input() dropdownIcon: string = 'fa fa-fw fa-caret-down'; - - @Input() optionLabel: string; - - @ViewChild('container') containerViewChild: ElementRef; - - @ViewChild('panel') panelViewChild: ElementRef; - - @ViewChild('filterInput') filterInputChild: ElementRef; - - @ContentChildren(PrimeTemplate) templates: QueryList; - - @Output() onChange: EventEmitter = new EventEmitter(); - - @Output() onFocus: EventEmitter = new EventEmitter(); - - @Output() onBlur: EventEmitter = new EventEmitter(); - - @Output() onPanelShow: EventEmitter = new EventEmitter(); - - @Output() onPanelHide: EventEmitter = new EventEmitter(); - - public value: any[]; - - public onModelChange: Function = () => {}; - - public onModelTouched: Function = () => {}; - - public valuesAsString: string; - - public focus: boolean; - - filled: boolean; - - public documentClickListener: any; - - public container: HTMLDivElement; - - public panel: HTMLDivElement; - - public selfClick: boolean; - - public panelClick: boolean; - - public filterValue: string; - - public visibleOptions: SelectItem[]; - - public filtered: boolean; - - public itemTemplate: TemplateRef; - - public focusedItemCheckbox: HTMLInputElement; - - _options: any[]; - - constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2, public objectUtils: ObjectUtils, private cd: ChangeDetectorRef) {} - - @Input() get options(): any[] { - return this._options; - } - - set options(val: any[]) { - let opts = this.optionLabel ? this.objectUtils.generateSelectItems(val, this.optionLabel) : val; - this._options = opts; - this.updateLabel(); - } - - ngOnInit() { - this.updateLabel(); - } - - ngAfterContentInit() { - this.templates.forEach((item) => { - switch(item.getType()) { - case 'item': - this.itemTemplate = item.template; - break; - - default: - this.itemTemplate = item.template; - break; - } - }); - } - - ngAfterViewInit() { - this.container = this.containerViewChild.nativeElement; - this.panel = this.panelViewChild.nativeElement; - - if(this.appendTo) { - if(this.appendTo === 'body') - document.body.appendChild(this.panel); - else - this.domHandler.appendChild(this.panel, this.appendTo); - } - - if(this.overlayVisible) { - this.show(); - } - } - - ngAfterViewChecked() { - if(this.filtered) { - if(this.appendTo) - this.domHandler.absolutePosition(this.panel, this.container); - else - this.domHandler.relativePosition(this.panel, this.container); - - this.filtered = false; - } - } - - writeValue(value: any) : void { - this.value = value; - this.updateLabel(); - this.updateFilledState(); - this.cd.markForCheck(); - } - - updateFilledState() { - this.filled = (this.valuesAsString != null && this.valuesAsString.length > 0); - } - - registerOnChange(fn: Function): void { - this.onModelChange = fn; - } - - registerOnTouched(fn: Function): void { - this.onModelTouched = fn; - } - - setDisabledState(val: boolean): void { - this.disabled = val; - } - - onItemClick(event, value) { - let selectionIndex = this.findSelectionIndex(value); - if(selectionIndex != -1) - this.value = this.value.filter((val,i) => i!=selectionIndex); - else - this.value = [...this.value||[],value]; - - this.onModelChange(this.value); - this.onChange.emit({originalEvent: event, value: this.value, itemValue: value}); - this.updateLabel(); - this.updateFilledState(); - } - - isSelected(value) { - return this.findSelectionIndex(value) != -1; - } - - findSelectionIndex(val: any): number { - let index = -1; - - if(this.value) { - for(let i = 0; i < this.value.length; i++) { - if(this.objectUtils.equals(this.value[i], val, this.dataKey)) { - index = i; - break; - } - } - } - - return index; - } - - toggleAll(event, checkbox) { - if(checkbox.checked) { - this.value = []; - } - else { - let opts = this.getVisibleOptions(); - if(opts) { - this.value = []; - for(let i = 0; i < opts.length; i++) { - this.value.push(opts[i].value); - } - } - } - - checkbox.checked = !checkbox.checked; - this.onModelChange(this.value); - this.onChange.emit({originalEvent: event, value: this.value}); - this.updateLabel(); - } - - isAllChecked() { - if(this.filterValue && this.filterValue.trim().length) - return this.value&&this.visibleOptions&&this.visibleOptions.length&&(this.value.length == this.visibleOptions.length); - else - return this.value&&this.options&&(this.value.length == this.options.length); - } - - show() { - this.overlayVisible = true; - this.panel.style.zIndex = String(++DomHandler.zindex); - this.bindDocumentClickListener(); - - if(this.appendTo) - this.domHandler.absolutePosition(this.panel, this.container); - else - this.domHandler.relativePosition(this.panel, this.container); - - this.domHandler.fadeIn(this.panel, 250); - this.onPanelShow.emit(); - } - - hide() { - this.overlayVisible = false; - this.unbindDocumentClickListener(); - if(this.resetFilterOnHide){ - this.filterValue = null; - this.filterInputChild.nativeElement.value = null; - } - this.onPanelHide.emit(); - } - - close(event) { - this.hide(); - event.preventDefault(); - event.stopPropagation(); - } - - onMouseclick(event,input) { - if(this.disabled) { - return; - } - - if(!this.panelClick) { - if(this.overlayVisible) { - this.hide(); - } - else { - input.focus(); - this.show(); - } - } - - this.selfClick = true; - } - - onInputFocus(event) { - this.focus = true; - this.onFocus.emit({originalEvent: event}); - } - - onInputBlur(event) { - this.focus = false; - this.onBlur.emit({originalEvent: event}); - this.onModelTouched(); - } - - onInputKeydown(event) { - switch(event.which) { - //down - case 40: - if(!this.overlayVisible && event.altKey) { - this.show(); - } - - event.preventDefault(); - break; - - //escape and tab - case 27: - case 9: - this.hide(); - break; - } - } - - updateLabel() { - if(this.value && this.options && this.value.length && this.displaySelectedLabel) { - let label = ''; - for(let i = 0; i < this.value.length; i++) { - let itemLabel = this.findLabelByValue(this.value[i]); - if (itemLabel) { - if(label.length > 0) { - label = label + ', '; - } - label = label + itemLabel; - } - } - - if(this.value.length <= this.maxSelectedLabels) { - this.valuesAsString = label; - } - else { - let pattern = /{(.*?)}/, - newSelectedItemsLabel = this.selectedItemsLabel.replace(this.selectedItemsLabel.match(pattern)[0], this.value.length + ''); - this.valuesAsString = newSelectedItemsLabel; - } - } - else { - this.valuesAsString = this.defaultLabel; - } - } - - findLabelByValue(val: any): string { - let label = null; - for(let i = 0; i < this.options.length; i++) { - let option = this.options[i]; - if(val == null && option.value == null || this.objectUtils.equals(val, option.value, this.dataKey)) { - label = option.label; - break; - } - } - return label; - } - - onFilter(event) { - this.filterValue = event.target.value.trim().toLowerCase(); - this.visibleOptions = []; - for(let i = 0; i < this.options.length; i++) { - let option = this.options[i]; - if(option.label.toLowerCase().indexOf(this.filterValue.toLowerCase()) > -1) { - this.visibleOptions.push(option); - } - } - this.filtered = true; - } - - isItemVisible(option: SelectItem): boolean { - if(this.filterValue && this.filterValue.trim().length) { - for(let i = 0; i < this.visibleOptions.length; i++) { - if(this.visibleOptions[i].value == option.value) { - return true; - } - } - } - else { - return true; - } - } - - getVisibleOptions(): SelectItem[] { - if(this.filterValue && this.filterValue.trim().length) { - let items = []; - for(let i = 0; i < this.options.length; i++) { - let option = this.options[i]; - if(option.label.toLowerCase().includes(this.filterValue.toLowerCase())) { - items.push(option); - } - } - return items; - } - else { - return this.options; - } - } - - bindDocumentClickListener() { - if(!this.documentClickListener) { - this.documentClickListener = this.renderer.listen('document', 'click', () => { - if(!this.selfClick && !this.panelClick && this.overlayVisible) { - this.hide(); - } - - this.selfClick = false; - this.panelClick = false; - this.cd.markForCheck(); - }); - } - } - - unbindDocumentClickListener() { - if(this.documentClickListener) { - this.documentClickListener(); - this.documentClickListener = null; - } - } - - ngOnDestroy() { - this.unbindDocumentClickListener(); - - if(this.appendTo) { - this.container.appendChild(this.panel); - } - } - -} - -@NgModule({ - imports: [CommonModule,SharedModule], - exports: [MultiSelect,SharedModule], - declarations: [MultiSelect] -}) -export class MultiSelectModule { } diff --git a/dashboard/src/app/components/orderlist/orderlist.css b/dashboard/src/app/components/orderlist/orderlist.css deleted file mode 100644 index 714660176..000000000 --- a/dashboard/src/app/components/orderlist/orderlist.css +++ /dev/null @@ -1,118 +0,0 @@ -.ui-orderlist { - display: table; -} - -.ui-orderlist .ui-orderlist-controls { - height: 12.5em; - padding: 0 .25em; - vertical-align: middle; - display: table-cell; -} - -.ui-orderlist .ui-orderlist-controls .ui-button { - display: block; - margin-bottom: 0.25em; -} - -.ui-orderlist .ui-orderlist-container { - display: table-cell; - vertical-align: top; -} - -.ui-orderlist .ui-orderlist-list { - list-style-type: none; - margin: 0; - padding: 0; - overflow:auto; - height: 12.5em; - width: 12.5em; -} - -.ui-orderlist .ui-orderlist-caption { - text-align: center; - padding: .5em .75em; - border-bottom: 0 none; -} - -.ui-orderlist .ui-orderlist-list .ui-orderlist-item { - margin: 1px; - padding: .125em; - cursor: pointer; - border: 0 none; - font-weight: inherit; -} - -.ui-orderlist .ui-orderlist-filter-container { - position: relative; - width: 100%; - padding: .5em .6em; - border-bottom: 0 none; -} - -.ui-orderlist .ui-orderlist-filter-container .ui-inputtext { - text-indent: 1.1em; - width: 100%; -} - -.ui-orderlist .ui-orderlist-filter-container .fa { - position: absolute; - top: 50%; - left: 1em; - margin-top: -.6em; -} - -.ui-orderlist.ui-state-disabled .ui-orderlist-item, -.ui-orderlist.ui-state-disabled .ui-button { - cursor: default; -} - -.ui-orderlist.ui-state-disabled .ui-orderlist-list { - overflow:hidden; -} - -/* Responsive */ -.ui-orderlist.ui-orderlist-responsive { - width: 100%; -} - -.ui-orderlist.ui-orderlist-responsive .ui-orderlist-controls { - width: 16.66666%; - padding-right: .5em; -} - -.ui-orderlist.ui-orderlist-responsive .ui-orderlist-list-container { - width: 83.33333%; -} - -.ui-orderlist.ui-orderlist-responsive .ui-orderlist-list, -.ui-orderlist.ui-orderlist-responsive .ui-orderlist-caption { - width: 100%; -} - -.ui-orderlist.ui-orderlist-responsive .ui-orderlist-controls > .ui-button { - width: 100%; -} - -.ui-orderlist .ui-orderlist-droppoint { - height: 6px; - list-style-type: none; -} - -@media (max-width: 40em) { - .ui-orderlist.ui-orderlist-responsive .ui-orderlist-controls { - text-align: center; - width: 100%; - display: inline-block; - height: auto; - } - - .ui-orderlist.ui-orderlist-responsive .ui-orderlist-controls .ui-button { - display: inline; - width: 20%; - display: inline-block; - } - - .ui-orderlist.ui-orderlist-responsive .ui-orderlist-list-container { - width: 100%; - } -} \ No newline at end of file diff --git a/dashboard/src/app/components/orderlist/orderlist.spec.ts b/dashboard/src/app/components/orderlist/orderlist.spec.ts deleted file mode 100644 index e7f1a9295..000000000 --- a/dashboard/src/app/components/orderlist/orderlist.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { OrderList } from './orderlist'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('OrderList', () => { - - let orderlist: OrderList; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - OrderList - ] - }); - - fixture = TestBed.createComponent(OrderList); - orderlist = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/orderlist/orderlist.ts b/dashboard/src/app/components/orderlist/orderlist.ts deleted file mode 100644 index 33df69d37..000000000 --- a/dashboard/src/app/components/orderlist/orderlist.ts +++ /dev/null @@ -1,354 +0,0 @@ -import {NgModule,Component,ElementRef,AfterViewChecked,AfterContentInit,Input,Output,ContentChildren,QueryList,TemplateRef,EventEmitter,ViewChild} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {ButtonModule} from '../button/button'; -import {SharedModule,PrimeTemplate} from '../common/shared'; -import {DomHandler} from '../dom/domhandler'; -import {ObjectUtils} from '../utils/objectutils'; - -@Component({ - selector: 'p-orderList', - template: ` -
-
- - - - -
-
-
{{header}}
-
- - -
-
    - -
  • -
  • - -
  • -
  • -
    -
-
-
- `, - providers: [DomHandler,ObjectUtils] -}) -export class OrderList implements AfterViewChecked,AfterContentInit { - - @Input() header: string; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() listStyle: any; - - @Input() responsive: boolean; - - @Input() filterBy: string; - - @Input() filterPlaceholder: string; - - @Input() metaKeySelection: boolean = true; - - @Input() dragdrop: boolean; - - @Input() dragdropScope: string; - - @Output() onReorder: EventEmitter = new EventEmitter(); - - @Output() onSelectionChange: EventEmitter = new EventEmitter(); - - @Output() onFilterEvent: EventEmitter = new EventEmitter(); - - @ViewChild('listelement') listViewChild: ElementRef; - - @ContentChildren(PrimeTemplate) templates: QueryList; - - public itemTemplate: TemplateRef; - - selectedItems: any[]; - - movedUp: boolean; - - movedDown: boolean; - - listContainer: any; - - itemTouched: boolean; - - draggedItemIndex: number; - - dragOverItemIndex: number; - - dragging: boolean; - - public filterValue: string; - - public visibleOptions: any[]; - - public _value: any[]; - - constructor(public el: ElementRef, public domHandler: DomHandler, public objectUtils: ObjectUtils) {} - - ngAfterViewInit() { - this.listContainer = this.domHandler.findSingle(this.el.nativeElement, 'ul.ui-orderlist-list'); - } - - ngAfterContentInit() { - this.templates.forEach((item) => { - switch(item.getType()) { - case 'item': - this.itemTemplate = item.template; - break; - - default: - this.itemTemplate = item.template; - break; - } - }); - } - - ngAfterViewChecked() { - if(this.movedUp||this.movedDown) { - let listItems = this.domHandler.find(this.listContainer, 'li.ui-state-highlight'); - let listItem; - - if(listItems.length > 0) { - if(this.movedUp) - listItem = listItems[0]; - else - listItem = listItems[listItems.length - 1]; - - this.domHandler.scrollInView(this.listContainer, listItem); - } - this.movedUp = false; - this.movedDown = false; - } - } - - get value(): any[] { - return this._value; - } - - @Input() set value(val:any[]) { - this._value = val; - if(this.filterValue) { - this.filter(); - } - } - - onItemClick(event, item, index) { - let selectedIndex = this.objectUtils.findIndexInList(item, this.selectedItems); - let selected = (selectedIndex != -1); - let metaSelection = this.itemTouched ? false : this.metaKeySelection; - - if(metaSelection) { - let metaKey = (event.metaKey||event.ctrlKey); - - if(selected && metaKey) { - this.selectedItems.splice(selectedIndex, 1); - } - else { - this.selectedItems = (metaKey) ? this.selectedItems||[] : []; - this.selectItem(item, index); - } - } - else { - if(selected) { - this.selectedItems.splice(selectedIndex, 1); - } - else { - this.selectedItems = this.selectedItems||[]; - this.selectItem(item, index); - } - } - - this.onSelectionChange.emit({originalEvent:event, value:this.selectedItems}); - this.itemTouched = false; - } - - selectItem(item, index) { - this.selectedItems = this.selectedItems||[]; - this.objectUtils.insertIntoOrderedArray(item, index, this.selectedItems, this.value); - } - - onFilterKeyup(event) { - this.filterValue = event.target.value.trim().toLowerCase(); - this.filter(); - - this.onFilterEvent.emit({ - originalEvent: event, - value: this.visibleOptions - }); - } - - filter() { - let searchFields: string[] = this.filterBy.split(','); - this.visibleOptions = this.objectUtils.filter(this.value, searchFields, this.filterValue); - } - - isItemVisible(item: any): boolean { - if(this.filterValue && this.filterValue.trim().length) { - for(let i = 0; i < this.visibleOptions.length; i++) { - if(item == this.visibleOptions[i]) { - return true; - } - } - } - else { - return true; - } - } - - onItemTouchEnd(event) { - this.itemTouched = true; - } - - isSelected(item: any) { - return this.objectUtils.findIndexInList(item, this.selectedItems) != -1; - } - - moveUp(event,listElement) { - if(this.selectedItems) { - for(let i = 0; i < this.selectedItems.length; i++) { - let selectedItem = this.selectedItems[i]; - let selectedItemIndex: number = this.objectUtils.findIndexInList(selectedItem, this.value); - - if(selectedItemIndex != 0) { - let movedItem = this.value[selectedItemIndex]; - let temp = this.value[selectedItemIndex-1]; - this.value[selectedItemIndex-1] = movedItem; - this.value[selectedItemIndex] = temp; - } - else { - break; - } - } - - this.movedUp = true; - this.onReorder.emit(event); - } - } - - moveTop(event,listElement) { - if(this.selectedItems) { - for(let i = 0; i < this.selectedItems.length; i++) { - let selectedItem = this.selectedItems[i]; - let selectedItemIndex: number = this.objectUtils.findIndexInList(selectedItem, this.value); - - if(selectedItemIndex != 0) { - let movedItem = this.value.splice(selectedItemIndex,1)[0]; - this.value.unshift(movedItem); - listElement.scrollTop = 0; - } - else { - break; - } - } - - this.onReorder.emit(event); - listElement.scrollTop = 0; - } - } - - moveDown(event,listElement) { - if(this.selectedItems) { - for(let i = this.selectedItems.length - 1; i >= 0; i--) { - let selectedItem = this.selectedItems[i]; - let selectedItemIndex: number = this.objectUtils.findIndexInList(selectedItem, this.value); - - if(selectedItemIndex != (this.value.length - 1)) { - let movedItem = this.value[selectedItemIndex]; - let temp = this.value[selectedItemIndex+1]; - this.value[selectedItemIndex+1] = movedItem; - this.value[selectedItemIndex] = temp; - } - else { - break; - } - } - - this.movedDown = true; - this.onReorder.emit(event); - } - } - - moveBottom(event,listElement) { - if(this.selectedItems) { - for(let i = this.selectedItems.length - 1; i >= 0; i--) { - let selectedItem = this.selectedItems[i]; - let selectedItemIndex: number = this.objectUtils.findIndexInList(selectedItem, this.value); - - if(selectedItemIndex != (this.value.length - 1)) { - let movedItem = this.value.splice(selectedItemIndex,1)[0]; - this.value.push(movedItem); - } - else { - break; - } - } - - this.onReorder.emit(event); - listElement.scrollTop = listElement.scrollHeight; - } - } - - onDragStart(event: DragEvent, index: number) { - this.dragging = true; - this.draggedItemIndex = index; - if(this.dragdropScope) { - event.dataTransfer.setData("text", this.dragdropScope); - } - } - - onDragOver(event: DragEvent, index: number) { - if(this.draggedItemIndex !== index && this.draggedItemIndex + 1 !== index) { - this.dragOverItemIndex = index; - event.preventDefault(); - } - } - - onDragLeave(event: DragEvent, index: number) { - this.dragOverItemIndex = null; - } - - onDrop(event: DragEvent, index: number) { - let dropIndex = (this.draggedItemIndex > index) ? index : (index === 0) ? 0 : index - 1; - this.objectUtils.reorderArray(this.value, this.draggedItemIndex, dropIndex); - this.dragOverItemIndex = null; - this.onReorder.emit(event); - event.preventDefault(); - } - - onDragEnd(event: DragEvent) { - this.dragging = false; - } - - onListMouseMove(event: MouseEvent) { - if(this.dragging) { - let offsetY = this.listViewChild.nativeElement.getBoundingClientRect().top + document.body.scrollTop; - let bottomDiff = (offsetY + this.listViewChild.nativeElement.clientHeight) - event.pageY; - let topDiff = (event.pageY - offsetY); - if(bottomDiff < 25 && bottomDiff > 0) - this.listViewChild.nativeElement.scrollTop += 15; - else if(topDiff < 25 && topDiff > 0) - this.listViewChild.nativeElement.scrollTop -= 15; - } - } -} - -@NgModule({ - imports: [CommonModule,ButtonModule,SharedModule], - exports: [OrderList,SharedModule], - declarations: [OrderList] -}) -export class OrderListModule { } diff --git a/dashboard/src/app/components/organizationchart/organizationchart.css b/dashboard/src/app/components/organizationchart/organizationchart.css deleted file mode 100644 index ed3ba6a99..000000000 --- a/dashboard/src/app/components/organizationchart/organizationchart.css +++ /dev/null @@ -1,46 +0,0 @@ -.ui-organizationchart .ui-organizationchart-table { - border-spacing: 0; - border-collapse: separate; -} - -.ui-organizationchart .ui-organizationchart-table > tr > td { - text-align: center; - vertical-align: top; - padding: 0; - padding: 0 .75em; -} - -.ui-organizationchart .ui-organizationchart-node-content { - padding: .5em .75em; - display: inline-block; - position: relative; -} - -.ui-organizationchart .ui-organizationchart-node-content .ui-node-toggler { - position: absolute; - bottom: -9px; - margin-left: -8px; - z-index: 2; - left: 50%; -} - -.ui-organizationchart .ui-organizationchart-line-down { - margin: 0 auto; - height: 20px; - width: 1px; - float: none; -} - -.ui-organizationchart .ui-organizationchart-line-right { - float: none; - border-radius: 0px; -} - -.ui-organizationchart .ui-organizationchart-line-left { - float: none; - border-radius: 0; -} - -.ui-organizationchart .ui-organizationchart-node-content.ui-organizationchart-selectable-node { - cursor: pointer; -} diff --git a/dashboard/src/app/components/organizationchart/organizationchart.spec.ts b/dashboard/src/app/components/organizationchart/organizationchart.spec.ts deleted file mode 100644 index f2a13aabd..000000000 --- a/dashboard/src/app/components/organizationchart/organizationchart.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { OrganizationChart } from './organizationchart'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('OrganizationChart', () => { - - let organizationchart: OrganizationChart; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - OrganizationChart - ] - }); - - fixture = TestBed.createComponent(OrganizationChart); - organizationchart = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/organizationchart/organizationchart.ts b/dashboard/src/app/components/organizationchart/organizationchart.ts deleted file mode 100644 index 88c09e484..000000000 --- a/dashboard/src/app/components/organizationchart/organizationchart.ts +++ /dev/null @@ -1,215 +0,0 @@ -import {NgModule,Component,ElementRef,Input,Output,OnInit,AfterContentInit,OnDestroy,EventEmitter,TemplateRef,EmbeddedViewRef,ViewContainerRef, - Inject,forwardRef,ContentChildren,QueryList} from '@angular/core'; -import {trigger,state,style,transition,animate} from '@angular/animations'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; -import {SharedModule} from '../common/shared'; -import {TreeNode} from '../common/treenode'; -import {PrimeTemplate} from '../common/shared'; - -@Component({ - selector: '[pOrganizationChartNode]', - template: ` - - -
-
{{node.label}}
-
- -
- - - -
- - - - -
- - - - -   -   - - - - -
- - - `, - animations: [ - trigger('childState', [ - state('in', style({opacity: 1})), - transition('void => *', [ - style({opacity: 0}), - animate(150) - ]), - transition('* => void', [ - animate(150, style({opacity:0})) - ]) - ]) - ], -}) -export class OrganizationChartNode { - - @Input() node: TreeNode; - - @Input() root: boolean; - - @Input() first: boolean; - - @Input() last: boolean; - - constructor(@Inject(forwardRef(() => OrganizationChart)) public chart:OrganizationChart) {} - - get leaf(): boolean { - return this.node.leaf == false ? false : !(this.node.children&&this.node.children.length); - } - - get colspan() { - return (this.node.children && this.node.children.length) ? this.node.children.length * 2: null; - } - - onNodeClick(event: Event, node: TreeNode) { - this.chart.onNodeClick(event, node) - } - - toggleNode(event: Event, node: TreeNode) { - node.expanded = !node.expanded; - event.preventDefault(); - } - - isSelected() { - return this.chart.isSelected(this.node); - } -} - -@Component({ - selector: 'p-organizationChart', - template: ` -
-
-
- `, - providers: [DomHandler] -}) -export class OrganizationChart implements AfterContentInit { - - @Input() value: TreeNode[]; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() selectionMode: string; - - @Input() selection: any; - - @Output() selectionChange: EventEmitter = new EventEmitter(); - - @Output() onNodeSelect: EventEmitter = new EventEmitter(); - - @Output() onNodeUnselect: EventEmitter = new EventEmitter(); - - @ContentChildren(PrimeTemplate) templates: QueryList; - - public templateMap: any; - - constructor(public el: ElementRef, public domHandler: DomHandler) {} - - get root(): TreeNode { - return this.value && this.value.length ? this.value[0] : null; - } - - ngAfterContentInit() { - if(this.templates.length) { - this.templateMap = {}; - } - - this.templates.forEach((item) => { - this.templateMap[item.getType()] = item.template; - }); - } - - getTemplateForNode(node: TreeNode): TemplateRef { - if(this.templateMap) - return node.type ? this.templateMap[node.type] : this.templateMap['default']; - else - return null; - } - - onNodeClick(event: Event, node: TreeNode) { - let eventTarget = ( event.target); - - if(eventTarget.className && (eventTarget.className.indexOf('ui-node-toggler') !== -1 || eventTarget.className.indexOf('ui-node-toggler-icon') !== -1)) { - return; - } - else if(this.selectionMode) { - if(node.selectable === false) { - return; - } - - let index = this.findIndexInSelection(node); - let selected = (index >= 0); - - if(this.selectionMode === 'single') { - if(selected) { - this.selection = null; - this.onNodeUnselect.emit({originalEvent: event, node: node}); - } - else { - this.selection = node; - this.onNodeSelect.emit({originalEvent: event, node: node}); - } - } - else if(this.selectionMode === 'multiple') { - if(selected) { - this.selection = this.selection.filter((val,i) => i!=index); - this.onNodeUnselect.emit({originalEvent: event, node: node}); - } - else { - this.selection = [...this.selection||[],node]; - this.onNodeSelect.emit({originalEvent: event, node: node}); - } - } - - this.selectionChange.emit(this.selection); - } - } - - findIndexInSelection(node: TreeNode) { - let index: number = -1; - - if(this.selectionMode && this.selection) { - if(this.selectionMode === 'single') { - index = (this.selection == node) ? 0 : - 1; - } - else if(this.selectionMode === 'multiple') { - for(let i = 0; i < this.selection.length; i++) { - if(this.selection[i] == node) { - index = i; - break; - } - } - } - } - - return index; - } - - isSelected(node: TreeNode) { - return this.findIndexInSelection(node) != -1; - } -} - -@NgModule({ - imports: [CommonModule], - exports: [OrganizationChart,SharedModule], - declarations: [OrganizationChart,OrganizationChartNode] -}) -export class OrganizationChartModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/overlaypanel/overlaypanel.css b/dashboard/src/app/components/overlaypanel/overlaypanel.css deleted file mode 100644 index b4955daf1..000000000 --- a/dashboard/src/app/components/overlaypanel/overlaypanel.css +++ /dev/null @@ -1,18 +0,0 @@ -.ui-overlaypanel { - padding: 0; - margin: 0; - position: absolute; -} - -.ui-overlaypanel-content { - padding: 0.5em 1em; -} - -.ui-overlaypanel-close { - position: absolute; - top: -.5em; - right: -.5em; - -moz-border-radius: 100%; - -webkit-border-radius: 100%; - border-radius: 100%; -} \ No newline at end of file diff --git a/dashboard/src/app/components/overlaypanel/overlaypanel.spec.ts b/dashboard/src/app/components/overlaypanel/overlaypanel.spec.ts deleted file mode 100644 index 3b20ccc9f..000000000 --- a/dashboard/src/app/components/overlaypanel/overlaypanel.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { OverlayPanel } from './overlaypanel'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('OverlayPanel', () => { - - let overlaypanel: OverlayPanel; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - OverlayPanel - ] - }); - - fixture = TestBed.createComponent(OverlayPanel); - overlaypanel = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/overlaypanel/overlaypanel.ts b/dashboard/src/app/components/overlaypanel/overlaypanel.ts deleted file mode 100644 index 57edf5bf4..000000000 --- a/dashboard/src/app/components/overlaypanel/overlaypanel.ts +++ /dev/null @@ -1,186 +0,0 @@ -import {NgModule,Component,Input,Output,AfterViewInit,AfterViewChecked,OnDestroy,EventEmitter,Renderer2,ElementRef,ChangeDetectorRef} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; -import {trigger,state,style,transition,animate} from '@angular/animations'; - -@Component({ - selector: 'p-overlayPanel', - template: ` -
-
- -
- - - -
- `, - animations: [ - trigger('panelState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]) - ], - providers: [DomHandler] -}) -export class OverlayPanel implements AfterViewInit,AfterViewChecked,OnDestroy { - - @Input() dismissable: boolean = true; - - @Input() showCloseIcon: boolean; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() appendTo: any; - - @Output() onBeforeShow: EventEmitter = new EventEmitter(); - - @Output() onAfterShow: EventEmitter = new EventEmitter(); - - @Output() onBeforeHide: EventEmitter = new EventEmitter(); - - @Output() onAfterHide: EventEmitter = new EventEmitter(); - - container: any; - - visible: boolean = false; - - documentClickListener: any; - - selfClick: boolean; - - target: any; - - willHide: boolean; - - willShow: boolean; - - targetClickEvent: boolean; - - closeClick: boolean; - - constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2, private cd: ChangeDetectorRef) {} - - ngAfterViewInit() { - this.container = this.el.nativeElement.children[0]; - - if(this.appendTo) { - if(this.appendTo === 'body') - document.body.appendChild(this.container); - else - this.domHandler.appendChild(this.container, this.appendTo); - } - } - - ngAfterViewChecked() { - if(this.willShow) { - this.domHandler.absolutePosition(this.container, this.target); - this.bindDocumentClickListener(); - this.onAfterShow.emit(null); - this.willShow = false; - } - - if(this.willHide) { - this.onAfterHide.emit(null); - this.willHide = false; - } - } - - bindDocumentClickListener() { - if(!this.documentClickListener && this.dismissable) { - this.documentClickListener = this.renderer.listen('document', 'click', () => { - if(!this.selfClick && !this.targetClickEvent) { - this.hide(); - } - - this.selfClick = false; - this.targetClickEvent = false; - this.cd.markForCheck(); - }); - } - } - - unbindDocumentClickListener() { - if(this.documentClickListener) { - this.documentClickListener(); - this.documentClickListener = null; - } - } - - toggle(event, target?) { - if(!this.target || this.target === (target||event.currentTarget||event.target)) { - if(this.visible) - this.hide(); - else - this.show(event, target); - } - else { - this.show(event, target); - } - } - - show(event, target?) { - this.onBeforeShow.emit(null); - this.target = target||event.currentTarget||event.target; - this.container.style.zIndex = ++DomHandler.zindex; - - this.visible = true; - this.willShow = true; - - if(event.type === 'click') { - this.targetClickEvent = true; - } - } - - hide() { - if(this.visible) { - this.onBeforeHide.emit(null); - this.willHide = true; - this.visible = false; - this.selfClick = false; - this.targetClickEvent = false; - this.unbindDocumentClickListener(); - } - } - - onPanelClick(event) { - if(this.closeClick) { - this.hide(); - this.closeClick = false; - } - else if(this.dismissable) { - this.selfClick = true; - } - } - - onCloseClick(event) { - this.closeClick = true; - event.preventDefault(); - } - - ngOnDestroy() { - this.unbindDocumentClickListener(); - - if(this.appendTo) { - this.el.nativeElement.appendChild(this.container); - } - - this.target = null; - } -} - -@NgModule({ - imports: [CommonModule], - exports: [OverlayPanel], - declarations: [OverlayPanel] -}) -export class OverlayPanelModule { } diff --git a/dashboard/src/app/components/paginator/paginator.scss b/dashboard/src/app/components/paginator/paginator.scss deleted file mode 100644 index 1722a8e1d..000000000 --- a/dashboard/src/app/components/paginator/paginator.scss +++ /dev/null @@ -1,114 +0,0 @@ -.ui-paginator { - margin: 0; - text-align: center; - padding: .125em; -} - -.ui-paginator .ui-paginator-top { - border-bottom: 0 none; -} - -.ui-paginator .ui-paginator-bottom { - border-top:0 none; -} - -.ui-paginator .ui-paginator-left-content { - float: left; -} - -.ui-paginator .ui-paginator-right-content { - float: right; -} - -.ui-paginator .ui-paginator-pages, -.ui-paginator .ui-paginator-page, -.ui-paginator .ui-paginator-next, -.ui-paginator .ui-paginator-last, -.ui-paginator .ui-paginator-first, -.ui-paginator .ui-paginator-prev, -.ui-paginator .ui-paginator-current { - width: .26rem; - height: .26rem; - border: none; - display: inline-block; - padding: .04rem; - zoom: 1; - text-decoration: none; - vertical-align: middle; -} - -.ui-paginator .ui-paginator-pages{ - width: auto; - padding: 0 0.04rem; - text-align: center; - .ui-paginator-page{ - margin: 0 .03rem; - border: 1px solid #ddd; - @extend .ui-corner-all-small; - } -} - -.ui-paginator .fa{ - display: inline-block; - width: .18rem; - height: .18rem; -} - -.ui-paginator .ui-paginator-next, -.ui-paginator .ui-paginator-prev{ - padding: 0; - .fa{ - width: .26rem; - height: .26rem; - font-size: .26rem; - text-align: center; - } -} - -.ui-paginator .ui-paginator-last, -.ui-paginator .ui-paginator-first{ - padding: .05rem; - .fa{ - width: .18rem; - height: .18rem; - font-size: .18rem; - text-align: center; - } -} - -.ui-paginator .ui-paginator-page, -.ui-paginator .ui-paginator-next, -.ui-paginator .ui-paginator-last, -.ui-paginator .ui-paginator-first, -.ui-paginator .ui-paginator-prev{ - cursor: pointer; -} - -.ui-paginator .ui-paginator-current, -.ui-paginator .ui-paginator-rpp-options { - margin-left: 1em; - margin-right: 1em; - background-image: none; -} - -.ui-paginator .ui-paginator-jtp-select option, -.ui-paginator .ui-paginator-rpp-options option { - background-image: none; - border: 0 none; - box-shadow: none; - -moz-box-shadow: none; - -webkit-box-shadow: none; -} - -.ui-paginator a.ui-state-disabled { - outline: 0 none; -} - -.ui-paginator .ui-dropdown { - min-width: 4em; - margin-left: .375em; -} - -.ui-fluid .ui-paginator .ui-dropdown { - width: auto; -} \ No newline at end of file diff --git a/dashboard/src/app/components/paginator/paginator.spec.ts b/dashboard/src/app/components/paginator/paginator.spec.ts deleted file mode 100644 index ba6ef692a..000000000 --- a/dashboard/src/app/components/paginator/paginator.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Paginator } from './paginator'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Paginator', () => { - - let paginator: Paginator; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Paginator - ] - }); - - fixture = TestBed.createComponent(Paginator); - paginator = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/paginator/paginator.ts b/dashboard/src/app/components/paginator/paginator.ts deleted file mode 100644 index 63308cc61..000000000 --- a/dashboard/src/app/components/paginator/paginator.ts +++ /dev/null @@ -1,231 +0,0 @@ -import {NgModule,Component,OnInit,ElementRef,Input,Output,SimpleChange,EventEmitter,TemplateRef} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {FormsModule} from '@angular/forms'; -import {DropdownModule} from '../dropdown/dropdown'; -import {SelectItem} from '../common/selectitem'; -import {SharedModule} from '../common/shared'; - -@Component({ - selector: 'p-paginator', - template: ` -
-
- -
- - - - - - - - {{pageLink}} - - - - - - - - -
- -
-
- ` -}) -export class Paginator implements OnInit { - - @Input() pageLinkSize: number = 5; - - @Output() onPageChange: EventEmitter = new EventEmitter(); - - @Input() style: any; - - @Input() styleClass: string; - - @Input() alwaysShow: boolean = true; - - @Input() templateLeft: TemplateRef; - - @Input() templateRight: TemplateRef; - - @Input() dropdownAppendTo: any; - - pageLinks: number[]; - - _totalRecords: number = 0; - - _first: number = 0; - - _rows: number = 0; - - _rowsPerPageOptions: number[]; - - rowsPerPageItems: SelectItem[]; - - paginatorState: any; - - ngOnInit() { - this.updatePaginatorState(); - } - - @Input() get totalRecords(): number { - return this._totalRecords; - } - - set totalRecords(val:number) { - this._totalRecords = val; - this.updatePageLinks(); - } - - @Input() get first(): number { - return this._first; - } - - set first(val:number) { - this._first = val; - this.updatePageLinks(); - } - - @Input() get rows(): number { - return this._rows; - } - - set rows(val:number) { - this._rows = val; - this.updatePageLinks(); - } - - @Input() get rowsPerPageOptions(): number[] { - return this._rowsPerPageOptions; - } - - set rowsPerPageOptions(val:number[]) { - this._rowsPerPageOptions = val; - if(this._rowsPerPageOptions) { - this.rowsPerPageItems = []; - for(let opt of this._rowsPerPageOptions) { - this.rowsPerPageItems.push({label: String(opt), value: opt}); - } - } - } - - isFirstPage() { - return this.getPage() === 0; - } - - isLastPage() { - return this.getPage() === this.getPageCount() - 1; - } - - getPageCount() { - return Math.ceil(this.totalRecords/this.rows)||1; - } - - calculatePageLinkBoundaries() { - let numberOfPages = this.getPageCount(), - visiblePages = Math.min(this.pageLinkSize, numberOfPages); - - //calculate range, keep current in middle if necessary - let start = Math.max(0, Math.ceil(this.getPage() - ((visiblePages) / 2))), - end = Math.min(numberOfPages - 1, start + visiblePages - 1); - - //check when approaching to last page - var delta = this.pageLinkSize - (end - start + 1); - start = Math.max(0, start - delta); - - return [start, end]; - } - - updatePageLinks() { - this.pageLinks = []; - let boundaries = this.calculatePageLinkBoundaries(), - start = boundaries[0], - end = boundaries[1]; - - for(let i = start; i <= end; i++) { - this.pageLinks.push(i + 1); - } - } - - changePage(p :number) { - var pc = this.getPageCount(); - - if(p >= 0 && p < pc) { - this.first = this.rows * p; - var state = { - page: p, - first: this.first, - rows: this.rows, - pageCount: pc - }; - this.updatePageLinks(); - - this.onPageChange.emit(state); - this.updatePaginatorState(); - } - } - - getPage(): number { - return Math.floor(this.first / this.rows); - } - - changePageToFirst(event) { - if(!this.isFirstPage()){ - this.changePage(0); - } - - event.preventDefault(); - } - - changePageToPrev(event) { - this.changePage(this.getPage() - 1); - event.preventDefault(); - } - - changePageToNext(event) { - this.changePage(this.getPage() + 1); - event.preventDefault(); - } - - changePageToLast(event) { - if(!this.isLastPage()){ - this.changePage(this.getPageCount() - 1); - } - - event.preventDefault(); - } - - onPageLinkClick(event, page) { - this.changePage(page); - event.preventDefault(); - } - - onRppChange(event) { - this.changePage(this.getPage()); - } - - updatePaginatorState() { - this.paginatorState = { - page: this.getPage(), - rows: this.rows, - first: this.first, - totalRecords: this.totalRecords - } - } -} - -@NgModule({ - imports: [CommonModule,DropdownModule,FormsModule,SharedModule], - exports: [Paginator,DropdownModule,FormsModule,SharedModule], - declarations: [Paginator] -}) -export class PaginatorModule { } diff --git a/dashboard/src/app/components/panel/panel.css b/dashboard/src/app/components/panel/panel.css deleted file mode 100644 index d29522867..000000000 --- a/dashboard/src/app/components/panel/panel.css +++ /dev/null @@ -1,33 +0,0 @@ -.ui-panel { - padding: 0.2em; -} - -.ui-panel .ui-panel-titlebar { - padding: .5em .75em; -} - -.ui-panel .ui-panel-titlebar-icon { - float: right; - cursor: pointer; -} - -.ui-panel .ui-panel-titlebar-icon { - margin-left: 0.2em; - margin-top: -0.1em; -} - -.ui-panel .ui-panel-content { - border: 0; - background: none; - padding: .5em .75em; -} - -.ui-panel .ui-panel-footer { - border-width: 1px 0 0; - padding: .25em .5em; - text-align:left; -} - -.ui-panel-content-wrapper-overflown { - overflow: hidden; -} \ No newline at end of file diff --git a/dashboard/src/app/components/panel/panel.spec.ts b/dashboard/src/app/components/panel/panel.spec.ts deleted file mode 100644 index 8c7b6936a..000000000 --- a/dashboard/src/app/components/panel/panel.spec.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { TestBed, ComponentFixture, fakeAsync, tick } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Panel } from './panel'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Panel', () => { - - let panel: Panel; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Panel - ] - }); - - fixture = TestBed.createComponent(Panel); - panel = fixture.componentInstance; - }); - - it('should display the header', () => { - panel.header = 'PrimeNG Panel Header'; - fixture.detectChanges(); - const headerEl = fixture.debugElement.query(By.css('.ui-panel-title')); - expect(headerEl.nativeElement.textContent).toContain('PrimeNG Panel Header') - }); - - it('should not render toggle icon when not toggleable', () => { - fixture.detectChanges(); - const togglerEl = fixture.debugElement.query(By.css('.ui-panel-titlebar-toggler')); - expect(togglerEl).toBeNull(); - }); - - it('should render toggle icon when toggleable', () => { - panel.toggleable = true; - fixture.detectChanges(); - const togglerEl = fixture.debugElement.query(By.css('.ui-panel-titlebar-toggler')); - expect(togglerEl).not.toBeNull(); - }); - - it('should toggle the panel when toggler is clicked', fakeAsync(() => { - panel.toggleable = true; - fixture.detectChanges(); - const togglerEl = fixture.nativeElement.querySelector('.ui-panel-titlebar-toggler'); - - togglerEl.click(); - expect(panel.collapsed).toEqual(true); - - tick(500); - - togglerEl.click(); - expect(panel.collapsed).toEqual(false); - })); - -}); diff --git a/dashboard/src/app/components/panel/panel.ts b/dashboard/src/app/components/panel/panel.ts deleted file mode 100644 index 8a54e2e05..000000000 --- a/dashboard/src/app/components/panel/panel.ts +++ /dev/null @@ -1,122 +0,0 @@ -import {NgModule,Component,Input,Output,EventEmitter,ElementRef,ContentChild} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {SharedModule,Footer} from '../common/shared'; -import {BlockableUI} from '../common/blockableui'; -import {trigger,state,style,transition,animate} from '@angular/animations'; - -let idx: number = 0; - -@Component({ - selector: 'p-panel', - template: ` -
-
- {{header}} - - - - -
-
-
- -
- - -
-
- `, - animations: [ - trigger('panelContent', [ - state('hidden', style({ - height: '0' - })), - state('visible', style({ - height: '*' - })), - transition('visible <=> hidden', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')) - ]) - ] -}) -export class Panel implements BlockableUI { - - @Input() toggleable: boolean; - - @Input() header: string; - - @Input() collapsed: boolean = false; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() expandIcon: string = 'fa-plus'; - - @Input() collapseIcon: string = 'fa-minus'; - - @Input() showHeader: boolean = true; - - @Output() collapsedChange: EventEmitter = new EventEmitter(); - - @Output() onBeforeToggle: EventEmitter = new EventEmitter(); - - @Output() onAfterToggle: EventEmitter = new EventEmitter(); - - @ContentChild(Footer) footerFacet; - - animating: boolean; - - id: string = `ui-panel-${idx++}`; - - constructor(private el: ElementRef) {} - - toggle(event) { - if(this.animating) { - return false; - } - - this.animating = true; - this.onBeforeToggle.emit({originalEvent: event, collapsed: this.collapsed}); - - if(this.toggleable) { - if(this.collapsed) - this.expand(event); - else - this.collapse(event); - } - - event.preventDefault(); - } - - expand(event) { - this.collapsed = false; - this.collapsedChange.emit(this.collapsed); - } - - collapse(event) { - this.collapsed = true; - this.collapsedChange.emit(this.collapsed); - } - - getBlockableElement(): HTMLElement { - return this.el.nativeElement.children[0]; - } - - onToggleDone(event: Event) { - this.animating = false; - this.onAfterToggle.emit({originalEvent: event, collapsed: this.collapsed}); - } - -} - -@NgModule({ - imports: [CommonModule], - exports: [Panel,SharedModule], - declarations: [Panel] -}) -export class PanelModule { } diff --git a/dashboard/src/app/components/panelmenu/panelmenu.css b/dashboard/src/app/components/panelmenu/panelmenu.css deleted file mode 100644 index 969878b8f..000000000 --- a/dashboard/src/app/components/panelmenu/panelmenu.css +++ /dev/null @@ -1,54 +0,0 @@ -.ui-panelmenu { - width: auto; -} - -.ui-panelmenu .ui-menu-separator { - border-width: 1px 0 0 0; -} - -.ui-panelmenu .ui-panelmenu-content-wrapper { - overflow: hidden; -} - -.ui-panelmenu .ui-panelmenu-header { - margin: -1px 0 0 0; - zoom: 1; -} - -.ui-panelmenu .ui-panelmenu-header-link { - padding: .5em; - display: block; - text-decoration: none; -} - -.ui-panelmenu .ui-menuitem-icon { - margin-right: .25em; -} - -.ui-panelmenu .ui-panelmenu-content { - padding: 0.25em; - border-top: 0; - margin-bottom: 1px; -} - -.ui-panelmenu .ui-submenu-list { - margin: 0; - padding: 0; - list-style: none; - margin-left: 1.5em; -} - -.ui-panelmenu .ui-panelmenu-content > .ui-panelmenu-root-submenu >.ui-submenu-list { - margin-left: 0; -} - -.ui-panelmenu .ui-menuitem { - overflow: hidden; - margin: .125em 0; -} - -.ui-panelmenu .ui-menuitem-link { - padding: .25em; - display: block; - text-decoration: none; -} \ No newline at end of file diff --git a/dashboard/src/app/components/panelmenu/panelmenu.spec.ts b/dashboard/src/app/components/panelmenu/panelmenu.spec.ts deleted file mode 100644 index adeb7e295..000000000 --- a/dashboard/src/app/components/panelmenu/panelmenu.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { PanelMenu } from './panelmenu'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('PanelMenu', () => { - - let panelmenu: PanelMenu; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - PanelMenu - ] - }); - - fixture = TestBed.createComponent(PanelMenu); - panelmenu = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/panelmenu/panelmenu.ts b/dashboard/src/app/components/panelmenu/panelmenu.ts deleted file mode 100644 index 964c7ce21..000000000 --- a/dashboard/src/app/components/panelmenu/panelmenu.ts +++ /dev/null @@ -1,164 +0,0 @@ -import {NgModule,Component,ElementRef,OnDestroy,Input} from '@angular/core'; -import {trigger,state,style,transition,animate} from '@angular/animations'; -import {CommonModule} from '@angular/common'; -import {MenuItem} from '../common/menuitem'; -import {RouterModule} from '@angular/router'; - -export class BasePanelMenuItem { - - handleClick(event, item) { - if(item.disabled) { - event.preventDefault(); - return; - } - - item.expanded = !item.expanded; - - if(!item.url) { - event.preventDefault(); - } - - if(item.command) { - item.command({ - originalEvent: event, - item: item - }); - } - } -} - -@Component({ - selector: 'p-panelMenuSub', - template: ` - - `, - animations: [ - trigger('submenu', [ - state('hidden', style({ - height: '0px' - })), - state('visible', style({ - height: '*' - })), - transition('visible => hidden', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')), - transition('hidden => visible', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')) - ]) - ] -}) -export class PanelMenuSub extends BasePanelMenuItem { - - @Input() item: MenuItem; - - @Input() expanded: boolean; -} - -@Component({ - selector: 'p-panelMenu', - template: ` -
- - - -
- `, - animations: [ - trigger('rootItem', [ - state('hidden', style({ - height: '0px' - })), - state('visible', style({ - height: '*' - })), - transition('visible => hidden', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')), - transition('hidden => visible', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')) - ]) - ] -}) -export class PanelMenu extends BasePanelMenuItem { - - @Input() model: MenuItem[]; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() multiple: boolean = true; - - public animating: boolean; - - collapseAll() { - for(let item of this.model) { - if(item.expanded) { - item.expanded = false; - } - } - } - - handleClick(event, item) { - if(!this.multiple) { - for(let modelItem of this.model) { - if(item !== modelItem && modelItem.expanded) { - modelItem.expanded = false; - } - } - } - - this.animating = true; - super.handleClick(event, item); - } - - onToggleDone() { - this.animating = false; - } - -} - -@NgModule({ - imports: [CommonModule,RouterModule], - exports: [PanelMenu,RouterModule], - declarations: [PanelMenu,PanelMenuSub] -}) -export class PanelMenuModule { } diff --git a/dashboard/src/app/components/password/images/password-meter.png b/dashboard/src/app/components/password/images/password-meter.png deleted file mode 100644 index eec05cfb4345d68368150665b40c63f65fad9ea8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1565 zcmV+&2IBdNP)^wHESkTKoI^1F3Q}3eo9w#%`L==Mym;2bZ%VxH@tQ zg@RB!8q{jFhBJUp49CE54vvATGeFYZJT`l*T0po$aO#bXsEnwlk+(5n8BrNgO-ocF ze|vj-fAR^>&4aRuX$6by*k(~}^M2i=!^D)L4o&f*-o_l(HTf_xrFh4h`W4Rmcja<9 zH?Pinv)QD2y-sUuYo?@{Iqx}`Tcw>Hx!NOIUWP$|)gICLIg#{ik}@0v!#OwxrYtaN zX^D6>81G+R60ZjTGxJ`*7K_rm%s%71Yv8=o@iDArqV;v6iwh!{U?(RdaU^9B6?X4&biYo zI%z^L=ly5w&vQqNsPuH+-|?GslMfTdd0$M&dLh0+xb3`me~C%Z;#J-KF|Y8ASX{$g}kNSzo&1?JaSOkvC-#Wl~a@HOpt>z?u8X=um#>39&R z|EXm$oOkc{>te|kt)BkL0BB;{q*}$0$g5iJ=uz9FrN!n+vP$A`Z2g9U=Um6$1G4hv*PAx=4u>r^-lF< z*=N*n8pCf87R!0RDJnZPxyU*&DXLUyvZ!*alZ&hiV^LA*#R5C;MpXa1sH6yt^KQa? zgRscX`=Z2xe1kA_-hbdXKbf+cn6~q7er?9YOq_S|YcqdTcSeiB^b)17o#BpmNqxmN zPRi0wf%2K9co7-2sH3?1j+LfDc9}m4Yzm`3wR-3L*&J!dEPmDjb8L7;kzk?X?$07` z^Hz&bGq1*-_XZ3*jzV^Y{ID&ykKHr!6xTQ@%eW;<<#N>aD%A7q+@O)W@7NhC<=44$ z7Zij&ZpX=}u^KUm3asbXC>n%k_oE&{#*x>UoISC!AwvKov2(@FDqj7sB>J}Q387sbs)?33&>Dwke}QPJ%FMgKH^8%@VJ~yJytEgdiwRaL0Y^v@$PDD5+*w$ggc=lj-8s=SRI%Y zRVG!MD5`1aZ5HgYYjMkYH=;74nue&P^KO1^#>7mVck^pACZ_JZ|0}=%BR7F~LOkOy P00000NkvXXu0mjf!c_V* diff --git a/dashboard/src/app/components/password/password.css b/dashboard/src/app/components/password/password.css deleted file mode 100644 index f72f179a3..000000000 --- a/dashboard/src/app/components/password/password.css +++ /dev/null @@ -1,20 +0,0 @@ -.ui-password-panel { - padding: .25em .5em; - width: 10em; - margin-top: 2px; -} - -.ui-password-panel .ui-password-meter { - height: 10px; - background:transparent url("./images/password-meter.png") no-repeat left top; - padding: 0; - margin: 0; -} - -.ui-password-info { - margin-top: .25em; -} - -.ui-password-panel-overlay { - position: absolute; -} \ No newline at end of file diff --git a/dashboard/src/app/components/password/password.spec.ts b/dashboard/src/app/components/password/password.spec.ts deleted file mode 100644 index 16d9ca301..000000000 --- a/dashboard/src/app/components/password/password.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Password } from './password'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Password', () => { - - let password: Password; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Password - ] - }); - - fixture = TestBed.createComponent(Password); - password = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/password/password.ts b/dashboard/src/app/components/password/password.ts deleted file mode 100644 index 5a1bcbc7c..000000000 --- a/dashboard/src/app/components/password/password.ts +++ /dev/null @@ -1,164 +0,0 @@ -import {NgModule,Directive,ElementRef,HostListener,Input,AfterViewInit,OnDestroy,DoCheck} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; - -@Directive({ - selector: '[pPassword]', - host: { - '[class.ui-inputtext]': 'true', - '[class.ui-corner-all]': 'true', - '[class.ui-state-default]': 'true', - '[class.ui-widget]': 'true', - '[class.ui-state-filled]': 'filled' - }, - providers: [DomHandler] -}) -export class Password implements AfterViewInit,OnDestroy,DoCheck { - - @Input() promptLabel: string = 'Please enter a password'; - - @Input() weakLabel: string = 'Weak'; - - @Input() mediumLabel: string = 'Medium'; - - @Input() strongLabel: string = 'Strong'; - - @Input() feedback: boolean = true; - - panel: any; - - meter: any; - - info: any; - - filled: boolean; - - constructor(public el: ElementRef, public domHandler: DomHandler) {} - - ngAfterViewInit() { - this.panel = document.createElement('div'); - this.panel.className = 'ui-password-panel ui-widget ui-state-highlight ui-corner-all ui-helper-hidden ui-password-panel-overlay'; - this.meter = document.createElement('div'); - this.meter.className = 'ui-password-meter'; - this.info = document.createElement('div'); - this.info.className = 'ui-password-info'; - this.info.textContent = this.promptLabel; - - if(this.feedback) { - this.panel.appendChild(this.meter); - this.panel.appendChild(this.info); - document.body.appendChild(this.panel); - } - } - - ngDoCheck() { - this.updateFilledState(); - } - - //To trigger change detection to manage ui-state-filled for material labels when there is no value binding - @HostListener('input', ['$event']) - onInput(e) { - this.updateFilledState(); - } - - updateFilledState() { - this.filled = this.el.nativeElement.value && this.el.nativeElement.value.length; - } - - @HostListener('focus', ['$event']) - onFocus(e) { - this.panel.style.zIndex = String(++DomHandler.zindex); - this.domHandler.removeClass(this.panel, 'ui-helper-hidden'); - this.domHandler.absolutePosition(this.panel, this.el.nativeElement); - this.domHandler.fadeIn(this.panel, 250); - } - - @HostListener('blur', ['$event']) - onBlur(e) { - this.domHandler.addClass(this.panel, 'ui-helper-hidden'); - } - - @HostListener('keyup', ['$event']) - onKeyup(e) { - let value = e.target.value, - label = null, - meterPos = null; - - if(value.length === 0) { - label = this.promptLabel; - meterPos = '0px 0px'; - } - else { - var score = this.testStrength(value); - - if(score < 30) { - label = this.weakLabel; - meterPos = '0px -10px'; - } - else if(score >= 30 && score < 80) { - label = this.mediumLabel; - meterPos = '0px -20px'; - } - else if(score >= 80) { - label = this.strongLabel; - meterPos = '0px -30px'; - } - } - - this.meter.style.backgroundPosition = meterPos; - this.info.textContent = label; - } - - testStrength(str: string) { - let grade: number = 0; - let val; - - val = str.match('[0-9]'); - grade += this.normalize(val ? val.length : 1/4, 1) * 25; - - val = str.match('[a-zA-Z]'); - grade += this.normalize(val ? val.length : 1/2, 3) * 10; - - val = str.match('[!@#$%^&*?_~.,;=]'); - grade += this.normalize(val ? val.length : 1/6, 1) * 35; - - val = str.match('[A-Z]'); - grade += this.normalize(val ? val.length : 1/6, 1) * 30; - - grade *= str.length / 8; - - return grade > 100 ? 100 : grade; - } - - normalize(x, y) { - let diff = x - y; - - if(diff <= 0) - return x / y; - else - return 1 + 0.5 * (x / (x + y/4)); - } - - get disabled(): boolean { - return this.el.nativeElement.disabled; - } - - ngOnDestroy() { - if (!this.feedback) - return; - - this.panel.removeChild(this.meter); - this.panel.removeChild(this.info); - document.body.removeChild(this.panel); - this.panel = null; - this.meter = null; - this.info = null; - } -} - -@NgModule({ - imports: [CommonModule], - exports: [Password], - declarations: [Password] -}) -export class PasswordModule { } diff --git a/dashboard/src/app/components/picklist/picklist.css b/dashboard/src/app/components/picklist/picklist.css deleted file mode 100644 index d6605d49f..000000000 --- a/dashboard/src/app/components/picklist/picklist.css +++ /dev/null @@ -1,202 +0,0 @@ -.ui-picklist > div { - float: left; -} - -.ui-picklist .ui-picklist-buttons { - height: 12.5em; - padding: 0 .25em; -} - -.ui-picklist .ui-picklist-list { - list-style-type: none; - margin: 0; - padding: 0; - overflow:auto; - height: 12.5em; - width: 12.5em; -} - -.ui-picklist .ui-picklist-list li { - margin: 1px; - padding: .125em; -} - -.ui-picklist .ui-button { - display:block; - margin-bottom: 0.25em; -} - -.ui-picklist .ui-button-text-icon-left { - width: 100%; -} - -.ui-picklist .ui-picklist-item { - cursor: pointer; - border: 0 none; - font-weight: inherit; -} - -.ui-picklist .ui-picklist-caption { - text-align: center; - padding: .5em .75em; - border-bottom:0 none; -} - -.ui-picklist table { - width: 100%; - border-collapse:collapse; -} - -.ui-picklist .ui-picklist-filter-container { - position: relative; - width: 100%; - padding: .5em .6em; - border-bottom: 0 none; -} - -.ui-picklist .ui-picklist-filter-container .ui-picklist-filter { - text-indent: 1.1em; - width: 100%; -} - -.ui-picklist .ui-picklist-filter-container .fa { - position: absolute; - top: 50%; - left: 1em; - margin-top: -.6em; -} - -.ui-picklist { - display: table; -} - -.ui-picklist > div { - float: none; - display: table-cell; - vertical-align: top; -} - -.ui-picklist .ui-picklist-buttons { - vertical-align: middle; -} - -/* Vertical */ -.ui-picklist.ui-picklist-vertical { - display: table; -} - -.ui-picklist.ui-picklist-vertical > div { - float: none; - display: table-row; - vertical-align: top; -} - -.ui-picklist.ui-picklist-vertical .ui-picklist-buttons { - text-align:center; - height: auto; -} - -.ui-picklist.ui-picklist-vertical .ui-picklist-buttons .ui-button { - display: inline-block; -} - -.ui-picklist.ui-picklist-vertical .ui-button { - margin-top: 0.25em; -} - -.ui-picklist-outline { - outline: 1px dotted black; - z-index: 1; -} - -.ui-picklist .ui-picklist-droppoint { - height: 6px; - list-style-type: none; -} - -.ui-picklist .ui-picklist-list .ui-picklist-droppoint-empty { - height: 100%; - list-style-type: none; -} - -.ui-picklist-list.ui-picklist-source, -.ui-picklist-list.ui-picklist-target { - outline: none; -} - -/* Responsive */ -.ui-picklist.ui-picklist-responsive * { - box-sizing: border-box; -} - -.ui-picklist.ui-picklist-responsive { - width: 100%; -} - -.ui-picklist.ui-picklist-responsive .ui-picklist-listwrapper { - width: 35%; -} - -.ui-picklist.ui-picklist-responsive .ui-picklist-listwrapper.ui-picklist-listwrapper-nocontrols { - width: 45%; -} - -.ui-picklist.ui-picklist-responsive .ui-picklist-buttons { - width: 10%; -} - -.ui-picklist.ui-picklist-responsive .ui-picklist-buttons button { - width: 100%; -} - -.ui-picklist.ui-picklist-responsive .ui-picklist-list { - width: auto; -} - -/* Responsive */ -@media (max-width: 40em) { - .ui-picklist.ui-picklist-responsive { - display: block; - } - - .ui-picklist.ui-picklist-responsive > div { - display: block; - width: 100% !important; - } - - .ui-picklist.ui-picklist-responsive .ui-picklist-buttons { - text-align: center; - height: auto; - padding: .4em 0; - } - - .ui-picklist.ui-picklist-responsive .ui-picklist-buttons button { - display: inline; - width: 20%; - margin-bottom: 0; - } - - .ui-picklist.ui-picklist-responsive .ui-picklist-source-controls.ui-picklist-buttons { - padding-bottom: .4em; - } - - .ui-picklist.ui-picklist-responsive .ui-picklist-target-controls.ui-picklist-buttons { - padding-top: .4em; - } - - .ui-picklist.ui-picklist-responsive .ui-picklist-buttons .fa-angle-right::before { - content: "\f107"; - } - - .ui-picklist.ui-picklist-responsive .ui-picklist-buttons .fa-angle-double-right::before { - content: "\f103"; - } - - .ui-picklist.ui-picklist-responsive .ui-picklist-buttons .fa-angle-left::before { - content: "\f106"; - } - - .ui-picklist.ui-picklist-responsive .ui-picklist-buttons .fa-angle-double-left::before { - content: "\f102"; - } -} diff --git a/dashboard/src/app/components/picklist/picklist.spec.ts b/dashboard/src/app/components/picklist/picklist.spec.ts deleted file mode 100644 index d1886f6b7..000000000 --- a/dashboard/src/app/components/picklist/picklist.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { PickList } from './picklist'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('PickList', () => { - - let picklist: PickList; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - PickList - ] - }); - - fixture = TestBed.createComponent(PickList); - picklist = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/picklist/picklist.ts b/dashboard/src/app/components/picklist/picklist.ts deleted file mode 100644 index 46a6b62dd..000000000 --- a/dashboard/src/app/components/picklist/picklist.ts +++ /dev/null @@ -1,660 +0,0 @@ -import {NgModule,Component,ElementRef,AfterViewInit,AfterContentInit,AfterViewChecked,DoCheck,Input,Output,ContentChildren,QueryList,TemplateRef,EventEmitter,ViewChild} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {ButtonModule} from '../button/button'; -import {SharedModule,PrimeTemplate} from '../common/shared'; -import {DomHandler} from '../dom/domhandler'; -import {ObjectUtils} from '../utils/objectutils'; - -@Component({ - selector: 'p-pickList', - template: ` -
-
-
- - - - -
-
-
-
{{sourceHeader}}
-
- - -
-
    - -
  • -
  • - -
  • -
  • -
    -
-
-
-
- - - - -
-
-
-
{{targetHeader}}
-
- - -
-
    - -
  • -
  • - -
  • -
  • -
    -
-
-
-
- - - - -
-
-
- `, - providers: [DomHandler,ObjectUtils] -}) -export class PickList implements AfterViewChecked,AfterContentInit { - - @Input() source: any[]; - - @Input() target: any[]; - - @Input() sourceHeader: string; - - @Input() targetHeader: string; - - @Input() responsive: boolean; - - @Input() filterBy: string; - - @Input() showSourceFilter: boolean = true; - - @Input() showTargetFilter: boolean = true; - - @Input() metaKeySelection: boolean = true; - - @Input() dragdrop: boolean; - - @Input() dragdropScope: string; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() sourceStyle: any; - - @Input() targetStyle: any; - - @Input() showSourceControls: boolean = true; - - @Input() showTargetControls: boolean = true; - - @Input() sourceFilterPlaceholder: string; - - @Input() targetFilterPlaceholder: string; - - @Input() disabled: boolean = false; - - @Output() onMoveToSource: EventEmitter = new EventEmitter(); - - @Output() onMoveAllToSource: EventEmitter = new EventEmitter(); - - @Output() onMoveAllToTarget: EventEmitter = new EventEmitter(); - - @Output() onMoveToTarget: EventEmitter = new EventEmitter(); - - @Output() onSourceReorder: EventEmitter = new EventEmitter(); - - @Output() onTargetReorder: EventEmitter = new EventEmitter(); - - @Output() onSourceSelect: EventEmitter = new EventEmitter(); - - @Output() onTargetSelect: EventEmitter = new EventEmitter(); - - @ViewChild('sourcelist') listViewSourceChild: ElementRef; - - @ViewChild('targetlist') listViewTargetChild: ElementRef; - - @ViewChild('sourceFilter') sourceFilterViewChild: ElementRef; - - @ViewChild('targetFilter') targetFilterViewChild: ElementRef; - - @ContentChildren(PrimeTemplate) templates: QueryList; - - public itemTemplate: TemplateRef; - - public visibleOptionsSource: any[]; - - public visibleOptionsTarget: any[]; - - selectedItemsSource: any[] = []; - - selectedItemsTarget: any[] = []; - - reorderedListElement: any; - - draggedItemIndexSource: number; - - draggedItemIndexTarget: number; - - dragOverItemIndexSource: number; - - dragOverItemIndexTarget: number; - - dragging: boolean; - - movedUp: boolean; - - movedDown: boolean; - - itemTouched: boolean; - - filterValueSource: string; - - filterValueTarget: string; - - fromListType: number; - - toListType: number; - - onListItemDroppoint: boolean; - - listHighlightTarget: boolean; - - listHighlightSource: boolean; - - constructor(public el: ElementRef, public domHandler: DomHandler, public objectUtils: ObjectUtils) {} - - ngAfterContentInit() { - this.templates.forEach((item) => { - switch(item.getType()) { - case 'item': - this.itemTemplate = item.template; - break; - - default: - this.itemTemplate = item.template; - break; - } - }); - } - - ngAfterViewChecked() { - if(this.movedUp||this.movedDown) { - let listItems = this.domHandler.find(this.reorderedListElement, 'li.ui-state-highlight'); - let listItem; - - if(this.movedUp) - listItem = listItems[0]; - else - listItem = listItems[listItems.length - 1]; - - this.domHandler.scrollInView(this.reorderedListElement, listItem); - this.movedUp = false; - this.movedDown = false; - this.reorderedListElement = null; - } - } - - onItemClick(event, item: any, selectedItems: any[], callback: EventEmitter) { - if(this.disabled) { - return; - } - - let index = this.findIndexInSelection(item,selectedItems); - let selected = (index != -1); - let metaSelection = this.itemTouched ? false : this.metaKeySelection; - - if(metaSelection) { - let metaKey = (event.metaKey||event.ctrlKey); - - if(selected && metaKey) { - selectedItems.splice(index, 1); - } - else { - if(!metaKey) { - selectedItems.length = 0; - } - selectedItems.push(item); - } - } - else { - if(selected) - selectedItems.splice(index, 1); - else - selectedItems.push(item); - } - - callback.emit({originalEvent: event, items: selectedItems}); - - this.itemTouched = false; - } - - onSourceItemDblClick() { - if(this.disabled) { - return; - } - - this.moveRight(); - } - - onTargetItemDblClick() { - if(this.disabled) { - return; - } - - this.moveLeft(); - } - - onFilter(event: KeyboardEvent, data: any[], listType: number) { - let query = ( event.target).value.trim().toLowerCase(); - - if(listType === -1) - this.filterValueSource = query; - else - this.filterValueTarget = query; - - this.activateFilter(data, listType); - } - - activateFilter(data: any[], listType: number) { - let searchFields = this.filterBy.split(','); - - if(listType === -1) - this.visibleOptionsSource = this.objectUtils.filter(data, searchFields, this.filterValueSource); - else - this.visibleOptionsTarget = this.objectUtils.filter(data, searchFields, this.filterValueTarget); - } - - isItemVisible(item: any, listType: number): boolean { - if(listType == -1) - return this.isVisibleInList(this.visibleOptionsSource, item, this.filterValueSource); - else - return this.isVisibleInList(this.visibleOptionsTarget, item, this.filterValueTarget); - } - - isVisibleInList(data: any[], item: any, filterValue: string): boolean { - if(filterValue && filterValue.trim().length) { - for(let i = 0; i < data.length; i++) { - if(item == data[i]) { - return true; - } - } - } - else { - return true; - } - } - - onItemTouchEnd(event) { - if(this.disabled) { - return; - } - - this.itemTouched = true; - } - - private sortByIndexInList(items: any[], list: any) { - return items.sort((item1, item2) => - this.findIndexInList(item1, list) - this.findIndexInList(item2, list)); - } - - moveUp(listElement, list, selectedItems, callback) { - if(selectedItems && selectedItems.length) { - selectedItems = this.sortByIndexInList(selectedItems, list); - for(let i = 0; i < selectedItems.length; i++) { - let selectedItem = selectedItems[i]; - let selectedItemIndex: number = this.findIndexInList(selectedItem, list); - - if(selectedItemIndex != 0) { - let movedItem = list[selectedItemIndex]; - let temp = list[selectedItemIndex-1]; - list[selectedItemIndex-1] = movedItem; - list[selectedItemIndex] = temp; - } - else { - break; - } - } - - this.movedUp = true; - this.reorderedListElement = listElement; - callback.emit({items: selectedItems}); - } - } - - moveTop(listElement, list, selectedItems, callback) { - if(selectedItems && selectedItems.length) { - selectedItems = this.sortByIndexInList(selectedItems, list); - for(let i = 0; i < selectedItems.length; i++) { - let selectedItem = selectedItems[i]; - let selectedItemIndex: number = this.findIndexInList(selectedItem, list); - - if(selectedItemIndex != 0) { - let movedItem = list.splice(selectedItemIndex,1)[0]; - list.unshift(movedItem); - } - else { - break; - } - } - - listElement.scrollTop = 0; - callback.emit({items: selectedItems}); - } - } - - moveDown(listElement, list, selectedItems, callback) { - if(selectedItems && selectedItems.length) { - selectedItems = this.sortByIndexInList(selectedItems, list); - for(let i = selectedItems.length - 1; i >= 0; i--) { - let selectedItem = selectedItems[i]; - let selectedItemIndex: number = this.findIndexInList(selectedItem, list); - - if(selectedItemIndex != (list.length - 1)) { - let movedItem = list[selectedItemIndex]; - let temp = list[selectedItemIndex+1]; - list[selectedItemIndex+1] = movedItem; - list[selectedItemIndex] = temp; - } - else { - break; - } - } - - this.movedDown = true; - this.reorderedListElement = listElement; - callback.emit({items: selectedItems}); - } - } - - moveBottom(listElement, list, selectedItems, callback) { - if(selectedItems && selectedItems.length) { - selectedItems = this.sortByIndexInList(selectedItems, list); - for(let i = selectedItems.length - 1; i >= 0; i--) { - let selectedItem = selectedItems[i]; - let selectedItemIndex: number = this.findIndexInList(selectedItem, list); - - if(selectedItemIndex != (list.length - 1)) { - let movedItem = list.splice(selectedItemIndex,1)[0]; - list.push(movedItem); - } - else { - break; - } - } - - listElement.scrollTop = listElement.scrollHeight; - callback.emit({items: selectedItems}); - } - } - - moveRight() { - if(this.selectedItemsSource && this.selectedItemsSource.length) { - for(let i = 0; i < this.selectedItemsSource.length; i++) { - let selectedItem = this.selectedItemsSource[i]; - if(this.findIndexInList(selectedItem, this.target) == -1) { - this.target.push(this.source.splice(this.findIndexInList(selectedItem, this.source),1)[0]); - } - } - this.onMoveToTarget.emit({ - items: this.selectedItemsSource - }); - this.selectedItemsSource = []; - } - } - - moveAllRight() { - if(this.source) { - let movedItems = []; - - for(let i = 0; i < this.source.length; i++) { - if(this.isItemVisible(this.source[i], -1)) { - let removedItem = this.source.splice(i, 1)[0]; - this.target.push(removedItem); - movedItems.push(removedItem); - i--; - } - } - - this.onMoveToTarget.emit({ - items: movedItems - }); - - this.onMoveAllToTarget.emit({ - items: movedItems - }); - - this.selectedItemsSource = []; - } - } - - moveLeft() { - if(this.selectedItemsTarget && this.selectedItemsTarget.length) { - for(let i = 0; i < this.selectedItemsTarget.length; i++) { - let selectedItem = this.selectedItemsTarget[i]; - if(this.findIndexInList(selectedItem, this.source) == -1) { - this.source.push(this.target.splice(this.findIndexInList(selectedItem, this.target),1)[0]); - } - } - this.onMoveToSource.emit({ - items: this.selectedItemsTarget - }); - - this.selectedItemsTarget = []; - } - } - - moveAllLeft() { - if(this.target) { - let movedItems = []; - - for(let i = 0; i < this.target.length; i++) { - if(this.isItemVisible(this.target[i], 1)) { - let removedItem = this.target.splice(i, 1)[0]; - this.source.push(removedItem); - movedItems.push(removedItem); - i--; - } - } - - this.onMoveToSource.emit({ - items: movedItems - }); - - this.onMoveAllToSource.emit({ - items: movedItems - }); - - this.selectedItemsTarget = []; - } - } - - isSelected(item: any, selectedItems: any[]) { - return this.findIndexInSelection(item, selectedItems) != -1; - } - - findIndexInSelection(item: any, selectedItems: any[]): number { - return this.findIndexInList(item, selectedItems); - } - - findIndexInList(item: any, list: any): number { - let index: number = -1; - - if(list) { - for(let i = 0; i < list.length; i++) { - if(list[i] == item) { - index = i; - break; - } - } - } - - return index; - } - - onDragStart(event: DragEvent, index: number, listType: number) { - this.dragging = true; - this.fromListType = listType; - if(listType === -1) - this.draggedItemIndexSource = index; - else - this.draggedItemIndexTarget = index; - - if(this.dragdropScope) { - event.dataTransfer.setData("text", this.dragdropScope); - } - } - - onDragOver(event: DragEvent, index: number, listType: number) { - if(listType == -1) { - if(this.draggedItemIndexSource !== index && this.draggedItemIndexSource + 1 !== index || (this.fromListType === 1)) { - this.dragOverItemIndexSource = index; - event.preventDefault(); - } - } - else { - if(this.draggedItemIndexTarget !== index && this.draggedItemIndexTarget + 1 !== index || (this.fromListType === -1)) { - this.dragOverItemIndexTarget = index; - event.preventDefault(); - } - } - this.onListItemDroppoint = true; - } - - onDragLeave(event: DragEvent, listType: number) { - this.dragOverItemIndexSource = null; - this.dragOverItemIndexTarget = null; - this.onListItemDroppoint = false; - } - - onDrop(event: DragEvent, index: number, listType: number) { - if(this.onListItemDroppoint) { - if(listType === -1) { - if(this.fromListType === 1) - this.insert(this.draggedItemIndexTarget, this.target, index, this.source, this.onMoveToSource); - else - this.objectUtils.reorderArray(this.source, this.draggedItemIndexSource, (this.draggedItemIndexSource > index) ? index : (index === 0) ? 0 : index - 1); - - this.dragOverItemIndexSource = null; - } - else { - if(this.fromListType === -1) - this.insert(this.draggedItemIndexSource, this.source, index, this.target, this.onMoveToTarget); - else - this.objectUtils.reorderArray(this.target, this.draggedItemIndexTarget, (this.draggedItemIndexTarget > index) ? index : (index === 0) ? 0 : index - 1); - - this.dragOverItemIndexTarget = null; - } - - this.listHighlightTarget = false; - this.listHighlightSource = false; - event.preventDefault(); - } - } - - onDragEnd(event: DragEvent) { - this.dragging = false; - } - - onListDrop(event: DragEvent, listType: number) { - if(!this.onListItemDroppoint) { - if(listType === -1) { - if(this.fromListType === 1) - this.insert(this.draggedItemIndexTarget, this.target, null, this.source, this.onMoveToSource); - } - else { - if(this.fromListType === -1) - this.insert(this.draggedItemIndexSource, this.source, null, this.target, this.onMoveToTarget); - } - - this.listHighlightTarget = false; - this.listHighlightSource = false; - event.preventDefault(); - } - } - - insert(fromIndex, fromList, toIndex, toList, callback) { - const elementtomove = fromList[fromIndex]; - - if(toIndex === null) - toList.push(fromList.splice(fromIndex, 1)[0]); - else - toList.splice(toIndex, 0, fromList.splice(fromIndex, 1)[0]); - - callback.emit({ - items: [elementtomove] - }); - } - - onListMouseMove(event: MouseEvent, listType: number) { - if(this.dragging) { - let moveListType = (listType == 0 ? this.listViewSourceChild : this.listViewTargetChild); - let offsetY = moveListType.nativeElement.getBoundingClientRect().top + document.body.scrollTop; - let bottomDiff = (offsetY + moveListType.nativeElement.clientHeight) - event.pageY; - let topDiff = (event.pageY - offsetY); - if(bottomDiff < 25 && bottomDiff > 0) - moveListType.nativeElement.scrollTop += 15; - else if(topDiff < 25 && topDiff > 0) - moveListType.nativeElement.scrollTop -= 15; - } - - if(listType === -1) { - if(this.fromListType === 1) - this.listHighlightSource = true; - } - else { - if(this.fromListType === -1) - this.listHighlightTarget = true; - } - event.preventDefault(); - } - - onListDragLeave() { - this.listHighlightTarget = false; - this.listHighlightSource = false; - } - - resetFilter() { - this.visibleOptionsSource = null; - this.filterValueSource = null; - this.visibleOptionsTarget = null; - this.filterValueTarget = null; - - ( this.sourceFilterViewChild.nativeElement).value = ''; - ( this.targetFilterViewChild.nativeElement).value = ''; - } -} - -@NgModule({ - imports: [CommonModule,ButtonModule,SharedModule], - exports: [PickList,SharedModule], - declarations: [PickList] -}) -export class PickListModule { } diff --git a/dashboard/src/app/components/progressbar/progressbar.css b/dashboard/src/app/components/progressbar/progressbar.css deleted file mode 100644 index d2e100039..000000000 --- a/dashboard/src/app/components/progressbar/progressbar.css +++ /dev/null @@ -1,110 +0,0 @@ -.ui-progressbar { - height: 1.2em; - text-align: left; - position: relative; - overflow: hidden; -} - -.ui-progressbar-determinate .ui-progressbar-value { - height: 100%; - width: 0%; - position: absolute; - display: none; - border: 0 none; -} - -.ui-progressbar-determinate .ui-progressbar-value-animate { - -webkit-transition: width 1s ease-in-out; - -moz-transition: width 1s ease-in-out; - -o-transition: width 1s ease-in-out; - transition: width 1s ease-in-out; -} - -.ui-progressbar-determinate .ui-progressbar-label { - text-align: center; - height: 100%; - width: 100%; - position: absolute; - display: none; - font-weight: bold; -} - -.ui-progressbar-indeterminate { - height: .5em; -} - -.ui-progressbar-indeterminate .ui-progressbar-value { - border: 0 none; -} - -.ui-progressbar-indeterminate .ui-progressbar-value::before { - content: ''; - position: absolute; - background-color: inherit; - top: 0; - left: 0; - bottom: 0; - will-change: left, right; - -webkit-animation: ui-progressbar-indeterminate-anim 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite; - animation: ui-progressbar-indeterminate-anim 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite; -} - -.ui-progressbar-indeterminate .ui-progressbar-value::after { - content: ''; - position: absolute; - background-color: inherit; - top: 0; - left: 0; - bottom: 0; - will-change: left, right; - -webkit-animation: ui-progressbar-indeterminate-anim-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite; - animation: ui-progressbar-indeterminate-anim-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite; - -webkit-animation-delay: 1.15s; - animation-delay: 1.15s; -} - -@-webkit-keyframes ui-progressbar-indeterminate-anim { - 0% { - left: -35%; - right: 100%; } - 60% { - left: 100%; - right: -90%; } - 100% { - left: 100%; - right: -90%; } -} -@keyframes ui-progressbar-indeterminate-anim { - 0% { - left: -35%; - right: 100%; } - 60% { - left: 100%; - right: -90%; } - 100% { - left: 100%; - right: -90%; } -} - -@-webkit-keyframes ui-progressbar-indeterminate-anim-short { - 0% { - left: -200%; - right: 100%; } - 60% { - left: 107%; - right: -8%; } - 100% { - left: 107%; - right: -8%; } -} -@keyframes ui-progressbar-indeterminate-anim-short { - 0% { - left: -200%; - right: 100%; } - 60% { - left: 107%; - right: -8%; } - 100% { - left: 107%; - right: -8%; } -} \ No newline at end of file diff --git a/dashboard/src/app/components/progressbar/progressbar.spec.ts b/dashboard/src/app/components/progressbar/progressbar.spec.ts deleted file mode 100644 index 8579e46f5..000000000 --- a/dashboard/src/app/components/progressbar/progressbar.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { ProgressBar } from './progressbar'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('ProgressBar', () => { - - let progressbar: ProgressBar; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - ProgressBar - ] - }); - - fixture = TestBed.createComponent(ProgressBar); - progressbar = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/progressbar/progressbar.ts b/dashboard/src/app/components/progressbar/progressbar.ts deleted file mode 100644 index b102759fb..000000000 --- a/dashboard/src/app/components/progressbar/progressbar.ts +++ /dev/null @@ -1,35 +0,0 @@ -import {NgModule,Component,Input} from '@angular/core'; -import {CommonModule} from '@angular/common'; - -@Component({ - selector: 'p-progressBar', - template: ` -
-
-
{{value}}{{unit}}
-
- ` -}) -export class ProgressBar { - - @Input() value: any; - - @Input() showValue: boolean = true; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() unit: string = '%'; - - @Input() mode: string = 'determinate'; - -} - -@NgModule({ - imports: [CommonModule], - exports: [ProgressBar], - declarations: [ProgressBar] -}) -export class ProgressBarModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/progressspinner/progressspinner.css b/dashboard/src/app/components/progressspinner/progressspinner.css deleted file mode 100644 index 0a0396e2c..000000000 --- a/dashboard/src/app/components/progressspinner/progressspinner.css +++ /dev/null @@ -1,71 +0,0 @@ -.ui-progress-spinner { - position: relative; - margin: 0 auto; - width: 100px; - height: 100px; - display: inline-block; -} - -.ui-progress-spinner::before { - content: ''; - display: block; - padding-top: 100%; -} - -.ui-progress-spinner-svg { - animation: ui-progress-spinner-rotate 2s linear infinite; - height: 100%; - transform-origin: center center; - width: 100%; - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - margin: auto; -} - -.ui-progress-spinner-circle { - stroke-dasharray: 1, 200; - stroke-dashoffset: 0; - animation: ui-progress-spinner-dash 1.5s ease-in-out infinite, ui-progress-spinner-color 6s ease-in-out infinite; - stroke-linecap: round; -} - -@keyframes ui-progress-spinner-rotate { - 100% { - transform: rotate(360deg); - } -} - -@keyframes ui-progress-spinner-dash { - 0% { - stroke-dasharray: 1, 200; - stroke-dashoffset: 0; - } - 50% { - stroke-dasharray: 89, 200; - stroke-dashoffset: -35px; - } - 100% { - stroke-dasharray: 89, 200; - stroke-dashoffset: -124px; - } -} - -@keyframes ui-progress-spinner-color { - 100%, - 0% { - stroke: #d62d20; - } - 40% { - stroke: #0057e7; - } - 66% { - stroke: #008744; - } - 80%, - 90% { - stroke: #ffa700; - } -} \ No newline at end of file diff --git a/dashboard/src/app/components/progressspinner/progressspinner.spec.ts b/dashboard/src/app/components/progressspinner/progressspinner.spec.ts deleted file mode 100644 index ffec9c8b0..000000000 --- a/dashboard/src/app/components/progressspinner/progressspinner.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { ProgressSpinner } from './progressspinner'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('ProgressSpinner', () => { - - let progressspinner: ProgressSpinner; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - ProgressSpinner - ] - }); - - fixture = TestBed.createComponent(ProgressSpinner); - progressspinner = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/progressspinner/progressspinner.ts b/dashboard/src/app/components/progressspinner/progressspinner.ts deleted file mode 100644 index db6fe47e9..000000000 --- a/dashboard/src/app/components/progressspinner/progressspinner.ts +++ /dev/null @@ -1,33 +0,0 @@ -import {NgModule,Component,Input} from '@angular/core'; -import {CommonModule} from '@angular/common'; - -@Component({ - selector: 'p-progressSpinner', - template: ` -
- - - -
- ` -}) -export class ProgressSpinner { - - @Input() style: any; - - @Input() styleClass: string; - - @Input() strokeWidth: string = "2"; - - @Input() fill: string = "none"; - - @Input() animationDuration: string = "2s"; - -} - -@NgModule({ - imports: [CommonModule], - exports: [ProgressSpinner], - declarations: [ProgressSpinner] -}) -export class ProgressSpinnerModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/radiobutton/radiobutton.css b/dashboard/src/app/components/radiobutton/radiobutton.css deleted file mode 100644 index 15831a41c..000000000 --- a/dashboard/src/app/components/radiobutton/radiobutton.css +++ /dev/null @@ -1,33 +0,0 @@ -.ui-radiobutton { - display:inline-block; - cursor: pointer; - vertical-align: middle; - margin-right: .25em; -} - -.ui-radiobutton-box { - width: .16rem; - height: .16rem; - line-height: .16rem; - -moz-border-radius: 100%; - -webkit-border-radius: 100%; - border-radius: 100%; - text-align: center; -} - -.ui-radiobutton-icon { - display: block; - margin: .04rem; - background: #fff; - - width: .06rem; - height: .06rem; - line-height: .06rem; - -moz-border-radius: 100%; - -webkit-border-radius: 100%; - border-radius: 100%; -} - -.ui-radiobutton, .ui-radiobutton-label { - vertical-align: middle; -} \ No newline at end of file diff --git a/dashboard/src/app/components/radiobutton/radiobutton.spec.ts b/dashboard/src/app/components/radiobutton/radiobutton.spec.ts deleted file mode 100644 index d118f7e1d..000000000 --- a/dashboard/src/app/components/radiobutton/radiobutton.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { RadioButton } from './radiobutton'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('RadioButton', () => { - - let radiobutton: RadioButton; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - RadioButton - ] - }); - - fixture = TestBed.createComponent(RadioButton); - radiobutton = fixture.componentInstance; - }); - - it('should display active state initially when checked by default', () => { - radiobutton.checked = true; - fixture.detectChanges(); - - const boxEl = fixture.nativeElement.querySelector('.ui-radiobutton-box'); - expect(boxEl.class).toContain('ui-state-active'); - }); -}); diff --git a/dashboard/src/app/components/radiobutton/radiobutton.ts b/dashboard/src/app/components/radiobutton/radiobutton.ts deleted file mode 100644 index f3001a785..000000000 --- a/dashboard/src/app/components/radiobutton/radiobutton.ts +++ /dev/null @@ -1,119 +0,0 @@ -import {NgModule,Component,Input,Output,ElementRef,EventEmitter,forwardRef,ViewChild,ChangeDetectorRef} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; - -export const RADIO_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => RadioButton), - multi: true -}; - -@Component({ - selector: 'p-radioButton', - template: ` -
-
- -
-
- -
-
- - `, - providers: [RADIO_VALUE_ACCESSOR] -}) -export class RadioButton implements ControlValueAccessor { - - @Input() value: any; - - @Input() name: string; - - @Input() disabled: boolean; - - @Input() label: string; - - @Input() tabindex: number; - - @Input() inputId: string; - - @Input() style: any; - - @Input() styleClass: string; - - @Output() onClick: EventEmitter = new EventEmitter(); - - @ViewChild('rb') inputViewChild: ElementRef; - - public onModelChange: Function = () => {}; - - public onModelTouched: Function = () => {}; - - public checked: boolean; - - public focused: boolean; - - constructor(private cd: ChangeDetectorRef) {} - - handleClick() { - if(!this.disabled) { - this.select(); - } - } - - select() { - if(!this.disabled) { - this.onClick.emit(null); - this.inputViewChild.nativeElement.checked = true; - this.checked = true; - this.onModelChange(this.value); - } - } - - writeValue(value: any) : void { - this.checked = (value == this.value); - - if(this.inputViewChild.nativeElement) { - this.inputViewChild.nativeElement.checked = this.checked; - } - - this.cd.markForCheck(); - } - - registerOnChange(fn: Function): void { - this.onModelChange = fn; - } - - registerOnTouched(fn: Function): void { - this.onModelTouched = fn; - } - - setDisabledState(val: boolean): void { - this.disabled = val; - } - - onFocus(event) { - this.focused = true; - } - - onBlur(event) { - this.focused = false; - this.onModelTouched(); - } - - onChange(event) { - this.select(); - } -} - -@NgModule({ - imports: [CommonModule], - exports: [RadioButton], - declarations: [RadioButton] -}) -export class RadioButtonModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/rating/rating.spec.ts b/dashboard/src/app/components/rating/rating.spec.ts deleted file mode 100644 index 4a16d55b6..000000000 --- a/dashboard/src/app/components/rating/rating.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Rating } from './rating'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Rating', () => { - - let rating: Rating; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Rating - ] - }); - - fixture = TestBed.createComponent(Rating); - rating = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/rating/rating.ts b/dashboard/src/app/components/rating/rating.ts deleted file mode 100644 index 686143644..000000000 --- a/dashboard/src/app/components/rating/rating.ts +++ /dev/null @@ -1,117 +0,0 @@ -import {NgModule,Component,ElementRef,OnInit,Input,Output,EventEmitter,forwardRef,ChangeDetectorRef} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; - -export const RATING_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => Rating), - multi: true -}; - -@Component({ - selector: 'p-rating', - template: ` - - `, - providers: [RATING_VALUE_ACCESSOR] -}) -export class Rating implements ControlValueAccessor { - - @Input() disabled: boolean; - - @Input() readonly: boolean; - - @Input() stars: number = 5; - - @Input() cancel: boolean = true; - - @Input() iconOnClass: string = 'fa-star'; - - @Input() iconOnStyle: any; - - @Input() iconOffClass: string = 'fa-star-o'; - - @Input() iconOffStyle: any; - - @Input() iconCancelClass: string = 'fa-ban'; - - @Input() iconCancelStyle: any; - - @Output() onRate: EventEmitter = new EventEmitter(); - - @Output() onCancel: EventEmitter = new EventEmitter(); - - constructor(private cd: ChangeDetectorRef) {} - - value: number; - - onModelChange: Function = () => {}; - - onModelTouched: Function = () => {}; - - public starsArray: number[]; - - ngOnInit() { - this.starsArray = []; - for(let i = 0; i < this.stars; i++) { - this.starsArray[i] = i; - } - } - - rate(event, i: number): void { - if(!this.readonly&&!this.disabled) { - this.value = (i + 1); - this.onModelChange(this.value); - this.onModelTouched(); - this.onRate.emit({ - originalEvent: event, - value: (i+1) - }); - } - event.preventDefault(); - } - - clear(event): void { - if(!this.readonly&&!this.disabled) { - this.value = null; - this.onModelChange(this.value); - this.onModelTouched(); - this.onCancel.emit(event); - } - event.preventDefault(); - } - - writeValue(value: any) : void { - this.value = value; - this.cd.detectChanges(); - } - - registerOnChange(fn: Function): void { - this.onModelChange = fn; - } - - registerOnTouched(fn: Function): void { - this.onModelTouched = fn; - } - - setDisabledState(val: boolean): void { - this.disabled = val; - } -} - -@NgModule({ - imports: [CommonModule], - exports: [Rating], - declarations: [Rating] -}) -export class RatingModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/schedule/schedule.css b/dashboard/src/app/components/schedule/schedule.css deleted file mode 100644 index 838a51d44..000000000 --- a/dashboard/src/app/components/schedule/schedule.css +++ /dev/null @@ -1,3 +0,0 @@ -.ui-fluid .fc .ui-button { - width: auto; -} \ No newline at end of file diff --git a/dashboard/src/app/components/schedule/schedule.spec.ts b/dashboard/src/app/components/schedule/schedule.spec.ts deleted file mode 100644 index ab080446e..000000000 --- a/dashboard/src/app/components/schedule/schedule.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Schedule } from './schedule'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Schedule', () => { - - let schedule: Schedule; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Schedule - ] - }); - - fixture = TestBed.createComponent(Schedule); - schedule = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/schedule/schedule.ts b/dashboard/src/app/components/schedule/schedule.ts deleted file mode 100644 index 2f133ad82..000000000 --- a/dashboard/src/app/components/schedule/schedule.ts +++ /dev/null @@ -1,402 +0,0 @@ -import {NgModule,Component,ElementRef,OnDestroy,DoCheck,OnChanges,Input,Output,EventEmitter,IterableDiffers,OnInit,AfterViewChecked,SimpleChanges} from '@angular/core'; -import {CommonModule} from '@angular/common'; - -declare var jQuery: any; - -@Component({ - selector: 'p-schedule', - template: '
' -}) -export class Schedule implements DoCheck,OnDestroy,OnInit,OnChanges,AfterViewChecked { - - @Input() events: any[]; - - @Input() header: any; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() rtl: boolean; - - @Input() weekends: boolean; - - @Input() hiddenDays: number[]; - - @Input() fixedWeekCount: boolean; - - @Input() weekNumbers: boolean; - - @Input() businessHours: any; - - @Input() height: any; - - @Input() contentHeight: any; - - @Input() aspectRatio: number = 1.35; - - @Input() eventLimit: any; - - @Input() defaultDate: any; - - @Input() editable: boolean; - - @Input() droppable: boolean; - - @Input() eventStartEditable: boolean; - - @Input() eventDurationEditable: boolean; - - @Input() defaultView: string = 'month'; - - @Input() allDaySlot: boolean = true; - - @Input() allDayText: string = 'all-day'; - - @Input() slotDuration: any = '00:30:00'; - - @Input() slotLabelInterval: any; - - @Input() snapDuration: any; - - @Input() scrollTime: any = '06:00:00'; - - @Input() minTime: any = '00:00:00'; - - @Input() maxTime: any = '24:00:00'; - - @Input() slotEventOverlap: boolean = true; - - @Input() nowIndicator: boolean; - - @Input() dragRevertDuration: number = 500; - - @Input() dragOpacity: number = .75; - - @Input() dragScroll: boolean = true; - - @Input() eventOverlap: any; - - @Input() eventConstraint: any; - - @Input() locale: string; - - @Input() timezone: boolean | string = false; - - @Input() timeFormat:string | null = null; - - @Input() eventRender: Function; - - @Input() dayRender: Function; - - @Input() navLinks: boolean; - - @Input() options: any; - - @Output() onDayClick: EventEmitter = new EventEmitter(); - - @Output() onDrop: EventEmitter = new EventEmitter(); - - @Output() onEventClick: EventEmitter = new EventEmitter(); - - @Output() onEventMouseover: EventEmitter = new EventEmitter(); - - @Output() onEventMouseout: EventEmitter = new EventEmitter(); - - @Output() onEventDragStart: EventEmitter = new EventEmitter(); - - @Output() onEventDragStop: EventEmitter = new EventEmitter(); - - @Output() onEventDrop: EventEmitter = new EventEmitter(); - - @Output() onEventResizeStart: EventEmitter = new EventEmitter(); - - @Output() onEventResizeStop: EventEmitter = new EventEmitter(); - - @Output() onEventResize: EventEmitter = new EventEmitter(); - - @Output() onViewRender: EventEmitter = new EventEmitter(); - - @Output() onViewDestroy: EventEmitter = new EventEmitter(); - - initialized: boolean; - - stopNgOnChangesPropagation: boolean; - - differ: any; - - schedule: any; - - config: any; - - constructor(public el: ElementRef, differs: IterableDiffers) { - this.differ = differs.find([]).create(null); - this.initialized = false; - } - - ngOnInit() { - this.config = { - theme: true, - header: this.header, - isRTL: this.rtl, - weekends: this.weekends, - hiddenDays: this.hiddenDays, - fixedWeekCount: this.fixedWeekCount, - weekNumbers: this.weekNumbers, - businessHours: this.businessHours, - height: this.height, - contentHeight: this.contentHeight, - aspectRatio: this.aspectRatio, - eventLimit: this.eventLimit, - defaultDate: this.defaultDate, - locale: this.locale, - timezone: this.timezone, - timeFormat: this.timeFormat, - editable: this.editable, - droppable: this.droppable, - eventStartEditable: this.eventStartEditable, - eventDurationEditable: this.eventDurationEditable, - defaultView: this.defaultView, - allDaySlot: this.allDaySlot, - allDayText: this.allDayText, - slotDuration: this.slotDuration, - slotLabelInterval: this.slotLabelInterval, - snapDuration: this.snapDuration, - scrollTime: this.scrollTime, - minTime: this.minTime, - maxTime: this.maxTime, - slotEventOverlap: this.slotEventOverlap, - nowIndicator: this.nowIndicator, - dragRevertDuration: this.dragRevertDuration, - dragOpacity: this.dragOpacity, - dragScroll: this.dragScroll, - eventOverlap: this.eventOverlap, - eventConstraint: this.eventConstraint, - eventRender: this.eventRender, - dayRender: this.dayRender, - navLinks: this.navLinks, - dayClick: (date, jsEvent, view) => { - this.onDayClick.emit({ - 'date': date, - 'jsEvent': jsEvent, - 'view': view - }); - }, - drop: (date, jsEvent, ui, resourceId) => { - this.onDrop.emit({ - 'date': date, - 'jsEvent': jsEvent, - 'ui': ui, - 'resourceId': resourceId - }); - }, - eventClick: (calEvent, jsEvent, view) => { - this.onEventClick.emit({ - 'calEvent': calEvent, - 'jsEvent': jsEvent, - 'view': view - }); - }, - eventMouseover: (calEvent, jsEvent, view) => { - this.onEventMouseover.emit({ - 'calEvent': calEvent, - 'jsEvent': jsEvent, - 'view': view - }); - }, - eventMouseout: (calEvent, jsEvent, view) => { - this.onEventMouseout.emit({ - 'calEvent': calEvent, - 'jsEvent': jsEvent, - 'view': view - }); - }, - eventDragStart: (event, jsEvent, ui, view) => { - this.onEventDragStart.emit({ - 'event': event, - 'jsEvent': jsEvent, - 'view': view - }); - }, - eventDragStop: (event, jsEvent, ui, view) => { - this.onEventDragStop.emit({ - 'event': event, - 'jsEvent': jsEvent, - 'view': view - }); - }, - eventDrop: (event, delta, revertFunc, jsEvent, ui, view) => { - this._updateEvent(event); - - this.onEventDrop.emit({ - 'event': event, - 'delta': delta, - 'revertFunc': revertFunc, - 'jsEvent': jsEvent, - 'view': view - }); - }, - eventResizeStart: (event, jsEvent, ui, view) => { - this.onEventResizeStart.emit({ - 'event': event, - 'jsEvent': jsEvent, - 'view': view - }); - }, - eventResizeStop: (event, jsEvent, ui, view) => { - this.onEventResizeStop.emit({ - 'event': event, - 'jsEvent': jsEvent, - 'view': view - }); - }, - eventResize: (event, delta, revertFunc, jsEvent, ui, view) => { - this._updateEvent(event); - - this.onEventResize.emit({ - 'event': event, - 'delta': delta, - 'revertFunc': revertFunc, - 'jsEvent': jsEvent, - 'view': view - }); - }, - viewRender: (view, element) => { - this.onViewRender.emit({ - 'view': view, - 'element': element - }); - }, - viewDestroy: (view, element) => { - this.onViewDestroy.emit({ - 'view': view, - 'element': element - }); - } - }; - - if(this.options) { - for(let prop in this.options) { - this.config[prop] = this.options[prop]; - } - } - } - - ngAfterViewChecked() { - if(!this.initialized && this.el.nativeElement.offsetParent) { - this.initialize(); - } - } - - ngOnChanges(changes: SimpleChanges) { - if(this.schedule) { - let options = {}; - for(let change in changes) { - if(change !== 'events') { - options[change] = changes[change].currentValue; - } - } - - if(Object.keys(options).length) { - this.schedule.fullCalendar('option', options); - } - } - } - - initialize() { - this.schedule = jQuery(this.el.nativeElement.children[0]); - this.schedule.fullCalendar(this.config); - if(this.events) { - this.schedule.fullCalendar('addEventSource', this.events); - } - this.initialized = true; - } - - ngDoCheck() { - let changes = this.differ.diff(this.events); - - if(this.schedule && changes) { - this.schedule.fullCalendar('removeEventSources'); - - if(this.events) { - this.schedule.fullCalendar('addEventSource', this.events); - } - } - } - - ngOnDestroy() { - jQuery(this.el.nativeElement.children[0]).fullCalendar('destroy'); - this.initialized = false; - this.schedule = null; - } - - gotoDate(date: any) { - this.schedule.fullCalendar('gotoDate', date); - } - - prev() { - this.schedule.fullCalendar('prev'); - } - - next() { - this.schedule.fullCalendar('next'); - } - - prevYear() { - this.schedule.fullCalendar('prevYear'); - } - - nextYear() { - this.schedule.fullCalendar('nextYear'); - } - - today() { - this.schedule.fullCalendar('today'); - } - - incrementDate(duration: any) { - this.schedule.fullCalendar('incrementDate', duration); - } - - changeView(viewName: string) { - this.schedule.fullCalendar('changeView', viewName); - } - - getDate() { - return this.schedule.fullCalendar('getDate'); - } - - updateEvent(event: any) { - this.schedule.fullCalendar('updateEvent', event); - } - - _findEvent(id: string) { - let event; - if(this.events) { - for(let e of this.events) { - if(e.id === id) { - event = e; - break; - } - } - } - return event; - } - - _updateEvent(event: any) { - let sourceEvent = this._findEvent(event.id); - if(sourceEvent) { - sourceEvent.start = event.start.format(); - if(event.end) { - sourceEvent.end = event.end.format(); - } - } - } -} - -@NgModule({ - imports: [CommonModule], - exports: [Schedule], - declarations: [Schedule] -}) -export class ScheduleModule { } diff --git a/dashboard/src/app/components/scrollpanel/scrollpanel.css b/dashboard/src/app/components/scrollpanel/scrollpanel.css deleted file mode 100644 index c44787c76..000000000 --- a/dashboard/src/app/components/scrollpanel/scrollpanel.css +++ /dev/null @@ -1,54 +0,0 @@ -.ui-scrollpanel-wrapper { - overflow: hidden; - width: 100%; - height: 100%; - position: relative; - z-index: 1; - float: left; -} - -.ui-scrollpanel-content { - height: calc(100% + 18px); - width: calc(100% + 18px); - padding: 0 0 0 0; - position: relative; - overflow: auto; - box-sizing: border-box; -} - -.ui-scrollpanel-bar { - position: relative; - background: #c1c1c1; - border-radius: 3px; - z-index: 2; - cursor: pointer; - opacity: 0; - transition: opacity 0.25s linear; -} - -.ui-scrollpanel-bar-y { - width: 9px; - top: 0; -} - -.ui-scrollpanel-bar-x { - height: 9px; - bottom: 0; -} - -.ui-scrollpanel-hidden { - visibility: hidden; -} - -.ui-scrollpanel:hover .ui-scrollpanel-bar, -.ui-scrollpanel:active .ui-scrollpanel-bar { - opacity: 1; -} - -.ui-scrollpanel-grabbed { - -o-user-select: none; - -ms-user-select: none; - -moz-user-select: none; - -webkit-user-select: none; - user-select: none; -} \ No newline at end of file diff --git a/dashboard/src/app/components/scrollpanel/scrollpanel.spec.ts b/dashboard/src/app/components/scrollpanel/scrollpanel.spec.ts deleted file mode 100644 index 092c92dc0..000000000 --- a/dashboard/src/app/components/scrollpanel/scrollpanel.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { ScrollPanel } from './scrollpanel'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('ScrollPanel', () => { - - let scrollpanel: ScrollPanel; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - ScrollPanel - ] - }); - - fixture = TestBed.createComponent(ScrollPanel); - scrollpanel = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/scrollpanel/scrollpanel.ts b/dashboard/src/app/components/scrollpanel/scrollpanel.ts deleted file mode 100644 index c404a21d0..000000000 --- a/dashboard/src/app/components/scrollpanel/scrollpanel.ts +++ /dev/null @@ -1,202 +0,0 @@ -import { NgModule, Component, Input, AfterViewInit, OnDestroy, ElementRef, NgZone, ViewChild } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { DomHandler } from '../dom/domhandler'; - -@Component({ - selector: 'p-scrollPanel', - template: ` -
-
-
- -
-
-
-
-
- `, - providers: [DomHandler] -}) -export class ScrollPanel implements AfterViewInit, OnDestroy { - - @Input() style: any; - - @Input() styleClass: string; - - constructor(public el: ElementRef, public zone: NgZone, public domHandler: DomHandler) {} - - @ViewChild('container') containerViewChild: ElementRef; - - @ViewChild('content') contentViewChild: ElementRef; - - @ViewChild('xBar') xBarViewChild: ElementRef; - - @ViewChild('yBar') yBarViewChild: ElementRef; - - scrollYRatio: number; - - scrollXRatio: number; - - timeoutFrame: any = (fn) => setTimeout(fn, 0); - - initialized: boolean; - - lastPageY: number; - - lastPageX: number; - - isXBarClicked: boolean; - - isYBarClicked: boolean; - - ngAfterViewInit() { - this.zone.runOutsideAngular(() => { - this.moveBar(); - this.moveBar = this.moveBar.bind(this); - this.onXBarMouseDown = this.onXBarMouseDown.bind(this); - this.onYBarMouseDown = this.onYBarMouseDown.bind(this); - this.onDocumentMouseMove = this.onDocumentMouseMove.bind(this); - this.onDocumentMouseUp = this.onDocumentMouseUp.bind(this); - - window.addEventListener('resize', this.moveBar); - this.contentViewChild.nativeElement.addEventListener('scroll', this.moveBar); - this.contentViewChild.nativeElement.addEventListener('mouseenter', this.moveBar); - this.xBarViewChild.nativeElement.addEventListener('mousedown', this.onXBarMouseDown); - this.yBarViewChild.nativeElement.addEventListener('mousedown', this.onYBarMouseDown); - this.initialized = true; - }); - } - - moveBar() { - let container = this.containerViewChild.nativeElement; - let content = this.contentViewChild.nativeElement; - - /* horizontal scroll */ - let xBar = this.xBarViewChild.nativeElement; - let totalWidth = content.scrollWidth; - let ownWidth = content.clientWidth; - let bottom = (container.clientHeight - xBar.clientHeight) * -1; - - this.scrollXRatio = ownWidth / totalWidth; - - /* vertical scroll */ - let yBar = this.yBarViewChild.nativeElement; - let totalHeight = content.scrollHeight; - let ownHeight = content.clientHeight; - let right = (container.clientWidth - yBar.clientWidth) * -1; - - this.scrollYRatio = ownHeight / totalHeight; - - this.requestAnimationFrame(() => { - if (this.scrollXRatio >= 1) { - this.domHandler.addClass(xBar, 'ui-scrollpanel-hidden'); - } - else { - this.domHandler.removeClass(xBar, 'ui-scrollpanel-hidden'); - xBar.style.cssText = 'width:' + Math.max(this.scrollXRatio * 100, 10) + '%; left:' + (content.scrollLeft / totalWidth) * 100 + '%;bottom:' + bottom + 'px;'; - } - - if (this.scrollYRatio >= 1) { - this.domHandler.addClass(yBar, 'ui-scrollpanel-hidden'); - } - else { - this.domHandler.removeClass(yBar, 'ui-scrollpanel-hidden'); - yBar.style.cssText = 'height:' + Math.max(this.scrollYRatio * 100, 10) + '%; top: calc(' + (content.scrollTop / totalHeight) * 100 + '% - ' + xBar.clientHeight + 'px);right:' + right + 'px;'; - } - }); - } - - onYBarMouseDown(e: MouseEvent) { - this.isYBarClicked = true; - this.lastPageY = e.pageY; - this.domHandler.addClass(this.yBarViewChild.nativeElement, 'ui-scrollpanel-grabbed'); - - this.domHandler.addClass(document.body, 'ui-scrollpanel-grabbed'); - - document.addEventListener('mousemove', this.onDocumentMouseMove); - document.addEventListener('mouseup', this.onDocumentMouseUp); - e.preventDefault(); - } - - onXBarMouseDown(e: MouseEvent) { - this.isXBarClicked = true; - this.lastPageX = e.pageX; - this.domHandler.addClass(this.xBarViewChild.nativeElement, 'ui-scrollpanel-grabbed'); - - this.domHandler.addClass(document.body, 'ui-scrollpanel-grabbed'); - - document.addEventListener('mousemove', this.onDocumentMouseMove); - document.addEventListener('mouseup', this.onDocumentMouseUp); - e.preventDefault(); - } - - onDocumentMouseMove(e: MouseEvent) { - if(this.isXBarClicked) { - this.onMouseMoveForXBar(e); - } - else if(this.isYBarClicked) { - this.onMouseMoveForYBar(e); - } - else { - this.onMouseMoveForXBar(e); - this.onMouseMoveForYBar(e); - } - - } - - onMouseMoveForXBar(e: MouseEvent) { - let deltaX = e.pageX - this.lastPageX; - this.lastPageX = e.pageX; - - this.requestAnimationFrame(() => { - this.contentViewChild.nativeElement.scrollLeft += deltaX / this.scrollXRatio; - }); - } - - onMouseMoveForYBar(e: MouseEvent) { - let deltaY = e.pageY - this.lastPageY; - this.lastPageY = e.pageY; - - this.requestAnimationFrame(() => { - this.contentViewChild.nativeElement.scrollTop += deltaY / this.scrollYRatio; - }); - } - - onDocumentMouseUp(e: Event) { - this.domHandler.removeClass(this.yBarViewChild.nativeElement, 'ui-scrollpanel-grabbed'); - this.domHandler.removeClass(this.xBarViewChild.nativeElement, 'ui-scrollpanel-grabbed'); - this.domHandler.removeClass(document.body, 'ui-scrollpanel-grabbed'); - - document.removeEventListener('mousemove', this.onDocumentMouseMove); - document.removeEventListener('mouseup', this.onDocumentMouseUp); - this.isXBarClicked = false; - this.isYBarClicked = false; - } - - requestAnimationFrame(f: Function) { - let frame = window.requestAnimationFrame || this.timeoutFrame; - frame(f); - } - - ngOnDestroy() { - if (this.initialized) { - window.removeEventListener('resize', this.moveBar); - this.contentViewChild.nativeElement.removeEventListener('scroll', this.moveBar); - this.contentViewChild.nativeElement.removeEventListener('mouseenter', this.moveBar); - this.xBarViewChild.nativeElement.removeEventListener('mousedown', this.onXBarMouseDown); - this.yBarViewChild.nativeElement.removeEventListener('mousedown', this.onYBarMouseDown); - } - } - - refresh() { - this.moveBar(); - } - -} - -@NgModule({ - imports: [CommonModule], - exports: [ScrollPanel], - declarations: [ScrollPanel] -}) -export class ScrollPanelModule { } diff --git a/dashboard/src/app/components/selectbutton/selectbutton.css b/dashboard/src/app/components/selectbutton/selectbutton.css deleted file mode 100644 index 58dba7378..000000000 --- a/dashboard/src/app/components/selectbutton/selectbutton.css +++ /dev/null @@ -1,19 +0,0 @@ -.ui-selectbutton { - display: inline-block; -} - -.ui-selectbutton.ui-state-error { - padding: 0; -} - -.ui-selectbutton .ui-button.ui-state-focus { - outline: none; -} - - -/* 自定义部分 */ - -.week-select-list { - width: 70px !important; - margin-right: 0.5em !important; -} \ No newline at end of file diff --git a/dashboard/src/app/components/selectbutton/selectbutton.spec.ts b/dashboard/src/app/components/selectbutton/selectbutton.spec.ts deleted file mode 100644 index 0ae95e0f3..000000000 --- a/dashboard/src/app/components/selectbutton/selectbutton.spec.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { TestBed, ComponentFixture, tick, fakeAsync } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { SelectButton } from './selectbutton'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('SelectButton', () => { - - let selectButton: SelectButton; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - SelectButton - ] - }); - - fixture = TestBed.createComponent(SelectButton); - selectButton = fixture.componentInstance; - }); - - it('should display the label', () => { - selectButton.options = [{label: 'Apartment', value: 'Apartment'},{label: 'House', value: 'House'},{label: 'Studio', value: 'Studio'}]; - fixture.detectChanges(); - const labelEl = fixture.debugElement.query(By.css('.ui-selectbutton')).children[0]; - expect(labelEl.nativeElement.querySelector('.ui-button-text').textContent).toContain('Apartment') - }); - - it('should display the preselected button', () => { - - selectButton.options = [{label: 'Apartment', value: {name:'Apartment'}},{label: 'House', value: {name:'House'}},{label: 'Studio', value: {name:'Studio'}}]; - selectButton.dataKey = 'name'; - selectButton.writeValue({name:'Studio'}); - fixture.detectChanges(); - - const active = fixture.nativeElement.querySelector('.ui-state-active').children[0]; - expect(active.textContent).toContain('Studio'); - }); - - it('should display the active when click', fakeAsync(() => { - selectButton.options = [{label: 'Apartment', value: 'Apartment'},{label: 'House', value: 'House'},{label: 'Studio', value: 'Studio'}]; - fixture.detectChanges(); - - const activeEl = fixture.nativeElement.querySelector('.ui-selectbutton').children[0]; - activeEl.click(); - - fixture.detectChanges(); - - const active = fixture.nativeElement.querySelector('.ui-state-active').children[0]; - expect(active.textContent).toContain('Apartment'); - })); -}); diff --git a/dashboard/src/app/components/selectbutton/selectbutton.ts b/dashboard/src/app/components/selectbutton/selectbutton.ts deleted file mode 100644 index d86c13386..000000000 --- a/dashboard/src/app/components/selectbutton/selectbutton.ts +++ /dev/null @@ -1,155 +0,0 @@ -import {NgModule,Component,Input,Output,EventEmitter,forwardRef,ChangeDetectorRef} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {SelectItem} from '../common/selectitem'; -import {ObjectUtils} from '../utils/objectutils'; -import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; - -export const SELECTBUTTON_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => SelectButton), - multi: true -}; - -@Component({ - selector: 'p-selectButton', - template: ` -
-
- - {{option.label||'ui-btn'}} -
- -
-
-
- `, - providers: [ObjectUtils,SELECTBUTTON_VALUE_ACCESSOR] -}) -export class SelectButton implements ControlValueAccessor { - - @Input() tabindex: number; - - @Input() multiple: boolean; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() disabled: boolean; - - @Input() dataKey: string - - @Input() optionLabel: string; - - @Output() onOptionClick: EventEmitter = new EventEmitter(); - - @Output() onChange: EventEmitter = new EventEmitter(); - - value: any; - - focusedItem: HTMLInputElement; - - _options: any[]; - - onModelChange: Function = () => {}; - - onModelTouched: Function = () => {}; - - constructor(public objectUtils: ObjectUtils, private cd: ChangeDetectorRef) {} - - @Input() get options(): any[] { - return this._options; - } - - set options(val: any[]) { - let opts = this.optionLabel ? this.objectUtils.generateSelectItems(val, this.optionLabel) : val; - this._options = opts; - } - - writeValue(value: any) : void { - this.value = value; - this.cd.markForCheck(); - } - - registerOnChange(fn: Function): void { - this.onModelChange = fn; - } - - registerOnTouched(fn: Function): void { - this.onModelTouched = fn; - } - - setDisabledState(val: boolean): void { - this.disabled = val; - } - - onItemClick(event, option: SelectItem, checkbox: HTMLInputElement, index: number) { - if(this.disabled) { - return; - } - - checkbox.focus(); - - if(this.multiple) { - let itemIndex = this.findItemIndex(option); - if(itemIndex != -1) - this.value = this.value.filter((val,i) => i!=itemIndex); - else - this.value = [...this.value||[], option.value]; - } - else { - this.value = option.value; - } - - this.onOptionClick.emit({ - originalEvent: event, - option: option, - index: index - }); - - this.onModelChange(this.value); - - this.onChange.emit({ - originalEvent: event, - value: this.value - }); - } - - onFocus(event: Event) { - this.focusedItem = event.target; - } - - onBlur(event) { - this.focusedItem = null; - this.onModelTouched(); - } - - isSelected(option: SelectItem) { - if(this.multiple) - return this.findItemIndex(option) != -1; - else - return this.objectUtils.equals(option.value, this.value, this.dataKey); - } - - findItemIndex(option: SelectItem) { - let index = -1; - if(this.value) { - for(let i = 0; i < this.value.length; i++) { - if(this.value[i] == option.value) { - index = i; - break; - } - } - } - return index; - } -} - -@NgModule({ - imports: [CommonModule], - exports: [SelectButton], - declarations: [SelectButton] -}) -export class SelectButtonModule { } diff --git a/dashboard/src/app/components/sidebar/sidebar.css b/dashboard/src/app/components/sidebar/sidebar.css deleted file mode 100644 index 49848fd98..000000000 --- a/dashboard/src/app/components/sidebar/sidebar.css +++ /dev/null @@ -1,117 +0,0 @@ -.ui-sidebar { - position: fixed; - padding: .5em 1em; - -webkit-transition: transform .3s; - transition: transform .3s; -} - -.ui-sidebar-left { - top: 0; - left: 0; - width: 20em; - height: 100%; - -webkit-transform: translateX(-100%); - -ms-transform: translateX(-100%); - transform: translateX(-100%); -} - -.ui-sidebar-right { - top: 0; - right: 0; - width: 20em; - height: 100%; - -webkit-transform: translateX(100%); - -ms-transform: translateX(100%); - transform: translateX(100%); -} - -.ui-sidebar-top { - top: 0; - left: 0; - width: 100%; - height: 10em; - -webkit-transform: translateY(-100%); - -ms-transform: translateY(-100%); - transform: translateY(-100%); -} - -.ui-sidebar-bottom { - bottom: 0; - left: 0; - width: 100%; - height: 10em; - -webkit-transform: translateY(100%); - -ms-transform: translateY(100%); - transform: translateY(100%); -} - -.ui-sidebar-full { - width: 100%; - height: 100%; - left: 0; - -webkit-transition: transform 0s; - transition: transform 0s; -} - -.ui-sidebar-left.ui-sidebar-active, -.ui-sidebar-right.ui-sidebar-active { - -webkit-transform: translateX(0); - -ms-transform: translateX(0); - transform: translateX(0) -} - -.ui-sidebar-left.ui-sidebar-sm, -.ui-sidebar-right.ui-sidebar-sm { - width: 20em; -} - -.ui-sidebar-left.ui-sidebar-md, -.ui-sidebar-right.ui-sidebar-md { - width: 40em; -} - -.ui-sidebar-left.ui-sidebar-lg, -.ui-sidebar-right.ui-sidebar-lg { - width: 60em; -} - -.ui-sidebar-top.ui-sidebar-active, -.ui-sidebar-bottom.ui-sidebar-active { - -webkit-transform: translateY(0); - -ms-transform: translateY(0); - transform: translateY(0) -} - -.ui-sidebar-top.ui-sidebar-sm, -.ui-sidebar-bottom.ui-sidebar-sm { - height: 10em; -} - -.ui-sidebar-top.ui-sidebar-md, -.ui-sidebar-bottom.ui-sidebar-md { - height: 20em; -} - -.ui-sidebar-top.ui-sidebar-lg, -.ui-sidebar-bottom.ui-sidebar-lg { - height: 30em; -} - -.ui-sidebar-mask { - position: fixed; - width: 100%; - height: 100%; -} - -.ui-sidebar-close { - float: right; -} - -@media screen and (max-width: 64em) { - .ui-sidebar-left.ui-sidebar-lg, - .ui-sidebar-left.ui-sidebar-md, - .ui-sidebar-right.ui-sidebar-lg, - .ui-sidebar-right.ui-sidebar-md { - width: 20em; - } -} \ No newline at end of file diff --git a/dashboard/src/app/components/sidebar/sidebar.spec.ts b/dashboard/src/app/components/sidebar/sidebar.spec.ts deleted file mode 100644 index 359a481c1..000000000 --- a/dashboard/src/app/components/sidebar/sidebar.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Sidebar } from './sidebar'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Sidebar', () => { - - let sidebar: Sidebar; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Sidebar - ] - }); - - fixture = TestBed.createComponent(Sidebar); - sidebar = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/sidebar/sidebar.ts b/dashboard/src/app/components/sidebar/sidebar.ts deleted file mode 100644 index cdf400d81..000000000 --- a/dashboard/src/app/components/sidebar/sidebar.ts +++ /dev/null @@ -1,188 +0,0 @@ -import {NgModule,Component,AfterViewInit,AfterViewChecked,OnDestroy,Input,Output,EventEmitter,ViewChild,ElementRef,Renderer2} from '@angular/core'; -import {trigger, state, style, transition, animate} from '@angular/animations'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; - -@Component({ - selector: 'p-sidebar', - template: ` -
- - - - -
- `, - animations: [ - trigger('panelState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('300ms ease-in')), - transition('hidden => visible', animate('300ms ease-out')) - ]) - ], - providers: [DomHandler] -}) -export class Sidebar implements AfterViewInit, AfterViewChecked, OnDestroy { - - @Input() position: string = 'left'; - - @Input() fullScreen: boolean; - - @Input() appendTo: string; - - @Input() blockScroll: boolean = false; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() autoZIndex: boolean = true; - - @Input() baseZIndex: number = 0; - - @ViewChild('container') containerViewChild: ElementRef; - - @Output() onShow: EventEmitter = new EventEmitter(); - - @Output() onHide: EventEmitter = new EventEmitter(); - - @Output() visibleChange:EventEmitter = new EventEmitter(); - - initialized: boolean; - - _visible: boolean; - - preventVisibleChangePropagation: boolean; - - mask: HTMLDivElement; - - maskClickListener: Function; - - executePostDisplayActions: boolean; - - constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2) {} - - ngAfterViewInit() { - this.initialized = true; - - if(this.appendTo) { - if(this.appendTo === 'body') - document.body.appendChild(this.containerViewChild.nativeElement); - else - this.domHandler.appendChild(this.containerViewChild.nativeElement, this.appendTo); - } - - if(this.visible) { - this.show(); - } - } - - @Input() get visible(): boolean { - return this._visible; - } - - set visible(val:boolean) { - this._visible = val; - - if(this.initialized && this.containerViewChild && this.containerViewChild.nativeElement) { - if(this._visible) - this.show(); - else { - if(this.preventVisibleChangePropagation) - this.preventVisibleChangePropagation = false; - else - this.hide(); - } - } - } - - ngAfterViewChecked() { - if(this.executePostDisplayActions) { - this.onShow.emit({}); - this.executePostDisplayActions = false; - } - } - - show() { - this.executePostDisplayActions = true; - if(this.autoZIndex) { - this.containerViewChild.nativeElement.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex)); - } - this.enableModality(); - } - - hide() { - this.onHide.emit({}); - this.disableModality(); - } - - close(event: Event) { - this.preventVisibleChangePropagation = true; - this.hide(); - this.visibleChange.emit(false); - event.preventDefault(); - } - - enableModality() { - if(!this.mask) { - this.mask = document.createElement('div'); - this.mask.style.zIndex = String(parseInt(this.containerViewChild.nativeElement.style.zIndex) - 1); - this.domHandler.addMultipleClasses(this.mask, 'ui-widget-overlay ui-sidebar-mask'); - this.maskClickListener = this.renderer.listen(this.mask, 'click', (event: any) => { - this.close(event); - }); - document.body.appendChild(this.mask); - if(this.blockScroll) { - this.domHandler.addClass(document.body, 'ui-overflow-hidden'); - } - } - } - - disableModality() { - if(this.mask) { - this.unbindMaskClickListener(); - document.body.removeChild(this.mask); - if(this.blockScroll) { - this.domHandler.removeClass(document.body, 'ui-overflow-hidden'); - } - this.mask = null; - } - } - - unbindMaskClickListener() { - if(this.maskClickListener) { - this.maskClickListener(); - this.maskClickListener = null; - } - } - - ngOnDestroy() { - this.initialized = false; - - if(this.visible) { - this.hide(); - } - - if(this.appendTo) { - this.el.nativeElement.appendChild(this.containerViewChild.nativeElement); - } - - this.unbindMaskClickListener(); - } -} - -@NgModule({ - imports: [CommonModule], - exports: [Sidebar], - declarations: [Sidebar] -}) -export class SidebarModule { } diff --git a/dashboard/src/app/components/slidemenu/slidemenu.css b/dashboard/src/app/components/slidemenu/slidemenu.css deleted file mode 100644 index fa05ac8e6..000000000 --- a/dashboard/src/app/components/slidemenu/slidemenu.css +++ /dev/null @@ -1,86 +0,0 @@ -.ui-slidemenu { - width: 12.5em; - padding: .25em; -} - -.ui-slidemenu.ui-slidemenu-dynamic { - position: absolute; - display: none; -} - -.ui-slidemenu .ui-menu-separator { - border-width: 1px 0 0 0; -} - -.ui-slidemenu ul { - list-style: none; - margin: 0; - padding: 0; -} - -.ui-slidemenu .ui-slidemenu-rootlist { - position: absolute; - top: 0; -} - -.ui-slidemenu .ui-submenu-list { - display: none; - position: absolute; - top: 0; - width: 12.5em; - padding: .25em; -} - -.ui-slidemenu .ui-menuitem-link { - padding: .25em; - display: block; - position: relative; - text-decoration: none; -} - -.ui-slidemenu .ui-menuitem { - position: relative; - margin: .125em 0; -} - -.ui-slidemenu .ui-menuitem-link .ui-submenu-icon { - position: absolute; - margin-top: -.5em; - right: 0; - top: 50%; -} - -.ui-slidemenu .ui-slidemenu-wrapper { - position: relative; -} - -.ui-slidemenu .ui-slidemenu-content { - overflow-x: hidden; - overflow-y: auto; - position: relative; -} - -.ui-slidemenu-backward { - position: absolute; - bottom: 0; - width: 100%; - padding: 0.25em; - cursor: pointer; - display: none; -} - -.ui-slidemenu-backward .ui-slidemenu-backward-icon { - vertical-align: middle; -} - -.ui-slidemenu-backward span { - vertical-align: middle; -} - -.ui-slidemenu .ui-menuitem-active { - position: static; -} - -.ui-slidemenu .ui-menuitem-active > .ui-submenu > .ui-submenu-list { - display: block; -} diff --git a/dashboard/src/app/components/slidemenu/slidemenu.spec.ts b/dashboard/src/app/components/slidemenu/slidemenu.spec.ts deleted file mode 100644 index f7f26bd6f..000000000 --- a/dashboard/src/app/components/slidemenu/slidemenu.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { SlideMenu } from './slidemenu'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('SlideMenu', () => { - - let slidemenu: SlideMenu; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - SlideMenu - ] - }); - - fixture = TestBed.createComponent(SlideMenu); - slidemenu = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/slidemenu/slidemenu.ts b/dashboard/src/app/components/slidemenu/slidemenu.ts deleted file mode 100644 index 15b5acd33..000000000 --- a/dashboard/src/app/components/slidemenu/slidemenu.ts +++ /dev/null @@ -1,228 +0,0 @@ -import {NgModule,Component,ElementRef,AfterViewInit,OnDestroy,Input,Output,Renderer2,Inject,forwardRef,ViewChild} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; -import {MenuItem} from '../common/menuitem'; -import {Location} from '@angular/common'; -import {RouterModule} from '@angular/router'; - -@Component({ - selector: 'p-slideMenuSub', - template: ` - - ` -}) -export class SlideMenuSub implements OnDestroy { - - @Input() item: MenuItem; - - @Input() root: boolean; - - @Input() backLabel: string = 'Back'; - - @Input() menuWidth: string; - - @Input() effectDuration: any; - - @Input() easing: string = 'ease-out'; - - constructor(@Inject(forwardRef(() => SlideMenu)) public slideMenu: SlideMenu) {} - - activeItem: any; - - itemClick(event, item: MenuItem, listitem: any) { - if(item.disabled) { - event.preventDefault(); - return; - } - - if(!item.url) { - event.preventDefault(); - } - - if(item.command) { - item.command({ - originalEvent: event, - item: item - }); - } - - if(item.items && !this.slideMenu.animating) { - this.slideMenu.left -= this.slideMenu.menuWidth; - this.activeItem = listitem; - this.slideMenu.animating = true; - setTimeout(() => this.slideMenu.animating = false, this.effectDuration); - } - } - - ngOnDestroy() { - this.activeItem = null; - } -} - -@Component({ - selector: 'p-slideMenu', - template: ` -
-
-
- -
-
- {{backLabel}} -
-
-
- `, - providers: [DomHandler] -}) -export class SlideMenu implements AfterViewInit,OnDestroy { - - @Input() model: MenuItem[]; - - @Input() popup: boolean; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() menuWidth: number = 190; - - @Input() viewportHeight: number = 180; - - @Input() effectDuration: any = 250; - - @Input() easing: string = 'ease-out'; - - @Input() backLabel: string = 'Back'; - - @Input() appendTo: any; - - @Input() autoZIndex: boolean = true; - - @Input() baseZIndex: number = 0; - - @ViewChild('container') containerViewChild: ElementRef; - - @ViewChild('backward') backwardViewChild: ElementRef; - - @ViewChild('slideMenuContent') slideMenuContentViewChild: ElementRef; - - public container: HTMLDivElement; - - public backwardElement: HTMLDivElement; - - public slideMenuContentElement: HTMLDivElement; - - public documentClickListener: any; - - public preventDocumentDefault: any; - - public left: number = 0; - - public animating: boolean = false; - - constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2) {} - - ngAfterViewInit() { - this.container = this.containerViewChild.nativeElement; - this.backwardElement = this.backwardViewChild.nativeElement; - this.slideMenuContentElement = this.slideMenuContentViewChild.nativeElement; - this.slideMenuContentElement.style.height = this.viewportHeight - this.domHandler.getHiddenElementOuterHeight(this.backwardElement) + 'px'; - - if(this.popup) { - if(this.appendTo) { - if(this.appendTo === 'body') - document.body.appendChild(this.container); - else - this.domHandler.appendChild(this.container, this.appendTo); - } - - this.documentClickListener = this.renderer.listen('document', 'click', () => { - if(!this.preventDocumentDefault) { - this.hide(); - } - this.preventDocumentDefault = false; - }); - } - } - - toggle(event) { - if(this.container.offsetParent) - this.hide(); - else - this.show(event); - } - - show(event) { - this.preventDocumentDefault = true; - this.moveOnTop(); - this.container.style.display = 'block'; - this.domHandler.absolutePosition(this.container, event.target); - this.domHandler.fadeIn(this.container, 250); - } - - hide() { - this.container.style.display = 'none'; - } - - moveOnTop() { - if(this.autoZIndex) { - this.container.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex)); - } - } - - onClick(event) { - this.preventDocumentDefault = true; - } - - goBack() { - this.left += this.menuWidth; - } - - ngOnDestroy() { - if(this.popup) { - if(this.documentClickListener) { - this.documentClickListener(); - } - - if(this.appendTo) { - this.el.nativeElement.appendChild(this.container); - } - } - } - -} - -@NgModule({ - imports: [CommonModule,RouterModule], - exports: [SlideMenu,RouterModule], - declarations: [SlideMenu,SlideMenuSub] -}) -export class SlideMenuModule { } diff --git a/dashboard/src/app/components/slider/slider.css b/dashboard/src/app/components/slider/slider.css deleted file mode 100644 index 00dafd730..000000000 --- a/dashboard/src/app/components/slider/slider.css +++ /dev/null @@ -1,65 +0,0 @@ -.ui-slider { - position: relative; - text-align: left; -} -.ui-slider .ui-slider-handle { - position: absolute; - width: 1.2em; - height: 1.2em; - cursor: default; - -ms-touch-action: none; - touch-action: none; - z-index: 1; -} -.ui-slider .ui-slider-handle.ui-slider-handle-active { - z-index: 2; -} -.ui-slider .ui-slider-range { - position: absolute; - font-size: .7em; - display: block; - border: 0; - background-position: 0 0; -} - -.ui-slider-horizontal { - height: .8em; -} -.ui-slider-horizontal .ui-slider-handle { - top: -.25em; - margin-left: -.6em; -} -.ui-slider-horizontal .ui-slider-range { - top: 0; - height: 100%; -} -.ui-slider-horizontal .ui-slider-range-min { - left: 0; -} -.ui-slider-horizontal .ui-slider-range-max { - right: 0; -} - -.ui-slider-vertical { - width: .8em; - height: 100px; -} -.ui-slider-vertical .ui-slider-handle { - left: -.25em; - margin-left: 0; - margin-bottom: -.6em; -} -.ui-slider-vertical .ui-slider-range { - left: 0; - width: 100%; -} -.ui-slider-vertical .ui-slider-range-min { - bottom: 0; -} -.ui-slider-vertical .ui-slider-range-max { - top: 0; -} - -.ui-slider-animate .ui-slider-handle { - transition: left .3s; -} \ No newline at end of file diff --git a/dashboard/src/app/components/slider/slider.spec.ts b/dashboard/src/app/components/slider/slider.spec.ts deleted file mode 100644 index f8684b76b..000000000 --- a/dashboard/src/app/components/slider/slider.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Slider } from './slider'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Slider', () => { - - let slider: Slider; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Slider - ] - }); - - fixture = TestBed.createComponent(Slider); - slider = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/slider/slider.ts b/dashboard/src/app/components/slider/slider.ts deleted file mode 100644 index f4cdf2c90..000000000 --- a/dashboard/src/app/components/slider/slider.ts +++ /dev/null @@ -1,369 +0,0 @@ -import { - NgModule, Component, ElementRef, OnDestroy, Input, Output, SimpleChange, EventEmitter, forwardRef, Renderer2, - NgZone -} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; -import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; - -export const SLIDER_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => Slider), - multi: true -}; - -@Component({ - selector: 'p-slider', - template: ` -
- - - - - - - -
- `, - providers: [SLIDER_VALUE_ACCESSOR,DomHandler] -}) -export class Slider implements OnDestroy,ControlValueAccessor { - - @Input() animate: boolean; - - @Input() disabled: boolean; - - @Input() min: number = 0; - - @Input() max: number = 100; - - @Input() orientation: string = 'horizontal'; - - @Input() step: number; - - @Input() range: boolean; - - @Input() style: any; - - @Input() styleClass: string; - - @Output() onChange: EventEmitter = new EventEmitter(); - - @Output() onSlideEnd: EventEmitter = new EventEmitter(); - - public value: number; - - public values: number; - - public handleValue: number; - - public handleValues: number[] = []; - - public onModelChange: Function = () => {}; - - public onModelTouched: Function = () => {}; - - public dragging: boolean; - - public dragListener: any; - - public mouseupListener: any; - - public initX: number; - - public initY: number; - - public barWidth: number; - - public barHeight: number; - - public sliderHandleClick: boolean; - - public handleIndex: number = 0; - - public startHandleValue: any; - - public startx: number; - - public starty: number; - - constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2, private ngZone: NgZone) {} - - onMouseDown(event:Event, index?:number) { - if(this.disabled) { - return; - } - - this.dragging = true; - this.updateDomData(); - this.sliderHandleClick = true; - this.handleIndex = index; - this.bindDragListeners(); - event.preventDefault(); - } - - onTouchStart(event, index?:number) { - var touchobj = event.changedTouches[0]; - this.startHandleValue = (this.range) ? this.handleValues[index] : this.handleValue; - this.dragging = true; - this.handleIndex = index; - - if (this.orientation === 'horizontal') { - this.startx = parseInt(touchobj.clientX, 10); - this.barWidth = this.el.nativeElement.children[0].offsetWidth; - } - else { - this.starty = parseInt(touchobj.clientY, 10); - this.barHeight = this.el.nativeElement.children[0].offsetHeight; - } - - event.preventDefault(); - } - - onTouchMove(event, index?:number) { - var touchobj = event.changedTouches[0], - handleValue = 0; - - if (this.orientation === 'horizontal') { - handleValue = Math.floor(((parseInt(touchobj.clientX, 10) - this.startx) * 100) / (this.barWidth)) + this.startHandleValue; - } - else { - handleValue = Math.floor(((this.starty - parseInt(touchobj.clientY, 10)) * 100) / (this.barHeight)) + this.startHandleValue; - } - - this.setValueFromHandle(event, handleValue); - - event.preventDefault(); - } - - onBarClick(event) { - if(this.disabled) { - return; - } - - if(!this.sliderHandleClick) { - this.updateDomData(); - this.handleChange(event); - } - - this.sliderHandleClick = false; - } - - handleChange(event: Event) { - let handleValue = this.calculateHandleValue(event); - this.setValueFromHandle(event, handleValue); - } - - bindDragListeners() { - this.ngZone.runOutsideAngular(() => { - if (!this.dragListener) { - this.dragListener = this.renderer.listen('document', 'mousemove', (event) => { - if (this.dragging) { - this.ngZone.run(() => { - this.handleChange(event); - }); - } - }); - } - - if (!this.mouseupListener) { - this.mouseupListener = this.renderer.listen('document', 'mouseup', (event) => { - if (this.dragging) { - this.dragging = false; - this.ngZone.run(() => { - if (this.range) { - this.onSlideEnd.emit({originalEvent: event, values: this.values}); - } else { - this.onSlideEnd.emit({originalEvent: event, value: this.value}); - } - }); - } - }); - } - }); - } - - unbindDragListeners() { - if(this.dragListener) { - this.dragListener(); - } - - if(this.mouseupListener) { - this.mouseupListener(); - } - } - - setValueFromHandle(event: Event, handleValue: any) { - let newValue = this.getValueFromHandle(handleValue); - - if(this.range) { - if(this.step) { - this.handleStepChange(newValue, this.values[this.handleIndex]); - } - else { - this.handleValues[this.handleIndex] = handleValue; - this.updateValue(newValue, event); - } - } - else { - if(this.step) { - this.handleStepChange(newValue, this.value); - } - else { - this.handleValue = handleValue; - this.updateValue(newValue, event); - } - } - } - - handleStepChange(newValue: number, oldValue: number) { - let diff = (newValue - oldValue); - let val = oldValue; - - if(diff < 0) { - val = oldValue + Math.ceil((newValue - oldValue) / this.step) * this.step; - } - else if(diff > 0) { - val = oldValue + Math.floor((newValue - oldValue) / this.step) * this.step; - } - - this.updateValue(val); - this.updateHandleValue(); - } - - writeValue(value: any) : void { - if(this.range) - this.values = value||[0,0]; - else - this.value = value||0; - - this.updateHandleValue(); - } - - registerOnChange(fn: Function): void { - this.onModelChange = fn; - } - - registerOnTouched(fn: Function): void { - this.onModelTouched = fn; - } - - setDisabledState(val: boolean): void { - this.disabled = val; - } - - get rangeStartLeft() { - return this.isVertical() ? 'auto' : this.handleValues[0] + '%'; - } - - get rangeStartBottom() { - return this.isVertical() ? this.handleValues[0] + '%' : 'auto'; - } - - get rangeEndLeft() { - return this.isVertical() ? 'auto' : this.handleValues[1] + '%'; - } - - get rangeEndBottom() { - return this.isVertical() ? this.handleValues[1] + '%' : 'auto'; - } - - isVertical(): boolean { - return this.orientation === 'vertical'; - } - - updateDomData(): void { - let rect = this.el.nativeElement.children[0].getBoundingClientRect(); - this.initX = rect.left + this.domHandler.getWindowScrollLeft(); - this.initY = rect.top + this.domHandler.getWindowScrollTop(); - this.barWidth = this.el.nativeElement.children[0].offsetWidth; - this.barHeight = this.el.nativeElement.children[0].offsetHeight; - } - - calculateHandleValue(event): number { - if(this.orientation === 'horizontal') - return ((event.pageX - this.initX) * 100) / (this.barWidth); - else - return(((this.initY + this.barHeight) - event.pageY) * 100) / (this.barHeight); - } - - updateHandleValue(): void { - if(this.range) { - this.handleValues[0] = (this.values[0] < this.min ? 0 : this.values[0] - this.min) * 100 / (this.max - this.min); - this.handleValues[1] = (this.values[1] > this.max ? 100 : this.values[1] - this.min) * 100 / (this.max - this.min); - } - else { - if(this.value < this.min) - this.handleValue = 0; - else if(this.value > this.max) - this.handleValue = 100; - else - this.handleValue = (this.value - this.min) * 100 / (this.max - this.min); - } - } - - updateValue(val: number, event?: Event): void { - if(this.range) { - let value = val; - - if(this.handleIndex == 0) { - if(value < this.min) { - value = this.min; - this.handleValues[0] = 0; - } - else if (value > this.values[1]) { - value = this.values[1]; - this.handleValues[0] = this.handleValues[1]; - } - } - else { - if(value > this.max) { - value = this.max; - this.handleValues[1] = 100; - } - else if (value < this.values[0]) { - value = this.values[0]; - this.handleValues[1] = this.handleValues[0]; - } - } - - this.values[this.handleIndex] = Math.floor(value); - this.onModelChange(this.values); - this.onChange.emit({event: event, values: this.values}); - } - else { - if(val < this.min) { - val = this.min; - this.handleValue = 0; - } - else if (val > this.max) { - val = this.max; - this.handleValue = 100; - } - - this.value = Math.floor(val); - this.onModelChange(this.value); - this.onChange.emit({event: event, value: this.value}); - } - } - - getValueFromHandle(handleValue: number): number { - return (this.max - this.min) * (handleValue / 100) + this.min; - } - - ngOnDestroy() { - this.unbindDragListeners(); - } -} - -@NgModule({ - imports: [CommonModule], - exports: [Slider], - declarations: [Slider] -}) -export class SliderModule { } diff --git a/dashboard/src/app/components/spinner/spinner.css b/dashboard/src/app/components/spinner/spinner.css deleted file mode 100644 index 90b58fd87..000000000 --- a/dashboard/src/app/components/spinner/spinner.css +++ /dev/null @@ -1,72 +0,0 @@ -.ui-spinner { - display: inline-block; - overflow: visible; - padding: 0; - position: relative; - vertical-align: middle; -} - -.ui-spinner-input { - vertical-align: middle; - padding-right: 1.5em; -} - -.ui-spinner-button { - cursor: default; - display: block; - height: 50%; - margin: 0 !important; - /* !important 覆盖掉.ui-button 给的样式*/ - overflow: hidden; - padding: 0 !important; - /* !important 覆盖掉.ui-button 给的样式*/ - position: absolute !important; - /* !important 覆盖掉.ui-button 给的样式*/ - right: 0; - text-align: center !important; - /* 覆盖掉.ui-button 给的样式*/ - vertical-align: middle; - width: 1.5em; - min-width: 2em !important; - /* 覆盖掉.ui-button 给的样式*/ - border-radius: 0 !important; - /* 覆盖掉.ui-button 给的样式*/ -} - -.ui-spinner .fa { - position: absolute; - top: 50%; - left: 50%; - margin-top: -.5em; - margin-left: -.5em; - width: 1em; -} - -.ui-spinner-up { - top: 0; -} - -.ui-spinner-down { - bottom: 0; -} - - -/* Fluid */ - -.ui-fluid .ui-spinner { - width: 100%; -} - -.ui-fluid .ui-spinner .ui-spinner-input { - padding-right: 2em; - width: 100%; -} - -.ui-fluid .ui-spinner .ui-spinner-button { - width: 1.5em; -} - -.ui-fluid .ui-spinner .ui-spinner-button .fa { - left: 50%; - /* 避免上下箭头没有居中 */ -} \ No newline at end of file diff --git a/dashboard/src/app/components/spinner/spinner.spec.ts b/dashboard/src/app/components/spinner/spinner.spec.ts deleted file mode 100644 index 6938eef49..000000000 --- a/dashboard/src/app/components/spinner/spinner.spec.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Spinner } from './spinner'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Spinner', () => { - - let spinner: Spinner; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Spinner - ] - }); - - fixture = TestBed.createComponent(Spinner); - spinner = fixture.componentInstance; - }); - - const triggerEvent = (el, type) => { - const e = document.createEvent('HTMLEvents'); - e.initEvent(type, false, true); - el.dispatchEvent(e); - }; - - it('should have value as 3 when up clicked 3 times', () => { - fixture.detectChanges(); - const spinnerUp = fixture.nativeElement.querySelector('.ui-spinner-up'); - triggerEvent(spinnerUp, 'mousedown'); - triggerEvent(spinnerUp, 'mousedown'); - triggerEvent(spinnerUp, 'mousedown'); - fixture.detectChanges(); - - expect(spinner.value).toBe(3); - expect(spinner.valueAsString).toBe('3'); - }); - - it('should have value as -3 when down clicked 3 times', () => { - fixture.detectChanges(); - const spinnerDown = fixture.nativeElement.querySelector('.ui-spinner-down'); - triggerEvent(spinnerDown, 'mousedown'); - triggerEvent(spinnerDown, 'mousedown'); - triggerEvent(spinnerDown, 'mousedown'); - fixture.detectChanges(); - - expect(spinner.value).toBe(-3); - expect(spinner.valueAsString).toBe('-3'); - }); - - it('Should display the spinner value 0.75 ', () => { - spinner.step = 0.25; - fixture.detectChanges(); - - const spinnerUp = fixture.nativeElement.querySelector('.ui-spinner-up'); - triggerEvent(spinnerUp, 'mousedown'); - triggerEvent(spinnerUp, 'mousedown'); - triggerEvent(spinnerUp, 'mousedown'); - - expect(spinner.value).toEqual(0.75); - expect(spinner.valueAsString).toEqual('0.75'); - }); -}); diff --git a/dashboard/src/app/components/spinner/spinner.ts b/dashboard/src/app/components/spinner/spinner.ts deleted file mode 100644 index f1a223531..000000000 --- a/dashboard/src/app/components/spinner/spinner.ts +++ /dev/null @@ -1,316 +0,0 @@ -import {NgModule,Component,ElementRef,OnInit,Input,Output,EventEmitter,forwardRef,ViewChild} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {InputTextModule} from '../inputtext/inputtext'; -import {DomHandler} from '../dom/domhandler'; -import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; - -export const SPINNER_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => Spinner), - multi: true -}; - -@Component({ - selector: 'p-spinner', - template: ` - - - - - - `, - host: { - '[class.ui-inputwrapper-filled]': 'filled', - '[class.ui-inputwrapper-focus]': 'focus' - }, - providers: [DomHandler,SPINNER_VALUE_ACCESSOR], -}) -export class Spinner implements OnInit,ControlValueAccessor { - - @Output() onChange: EventEmitter = new EventEmitter(); - - @Output() onFocus: EventEmitter = new EventEmitter(); - - @Output() onBlur: EventEmitter = new EventEmitter(); - - @Input() step: number = 1; - - @Input() min: number; - - @Input() max: number; - - @Input() maxlength: number; - - @Input() size: number; - - @Input() placeholder: string; - - @Input() inputId: string; - - @Input() disabled: boolean; - - @Input() readonly: boolean; - - @Input() decimalSeparator: string = '.'; - - @Input() thousandSeparator: string = ','; - - @Input() tabindex: number; - - @Input() formatInput: boolean = true; - - @Input() type: string = 'text'; - - @Input() required: boolean; - - value: number; - - valueAsString: string = ''; - - onModelChange: Function = () => {}; - - onModelTouched: Function = () => {}; - - keyPattern: RegExp = /[0-9\+\-]/; - - public precision: number; - - public timer: any; - - public focus: boolean; - - public filled: boolean; - - @ViewChild('inputfield') inputfieldViewChild: ElementRef; - - constructor(public el: ElementRef, public domHandler: DomHandler) {} - - ngOnInit() { - if(Math.floor(this.step) === 0) { - this.precision = this.step.toString().split(/[,]|[.]/)[1].length; - } - } - - repeat(event: Event, interval: number, dir: number) { - let i = interval||500; - - this.clearTimer(); - this.timer = setTimeout(() => { - this.repeat(event, 40, dir); - }, i); - - this.spin(event, dir); - } - - spin(event: Event, dir: number) { - let step = this.step * dir; - let currentValue = this.value||0; - let newValue: number = null; - - if(this.precision) - this.value = parseFloat(this.toFixed(currentValue + step, this.precision)); - else - this.value = currentValue + step; - - if(this.maxlength !== undefined && this.value.toString().length > this.maxlength) { - this.value = currentValue; - } - - if(this.min !== undefined && this.value < this.min) { - this.value = this.min; - } - - if(this.max !== undefined && this.value > this.max) { - this.value = this.max; - } - - this.formatValue(); - this.onModelChange(this.value); - this.onChange.emit(event); - } - - toFixed(value: number, precision: number) { - let power = Math.pow(10, precision||0); - return String(Math.round(value * power) / power); - } - - onUpButtonMousedown(event: Event) { - if(!this.disabled) { - this.inputfieldViewChild.nativeElement.focus(); - this.repeat(event, null, 1); - this.updateFilledState(); - } - } - - onUpButtonMouseup(event: Event) { - if(!this.disabled) { - this.clearTimer(); - } - } - - onUpButtonMouseleave(event: Event) { - if(!this.disabled) { - this.clearTimer(); - } - } - - onDownButtonMousedown(event: Event) { - if(!this.disabled) { - this.inputfieldViewChild.nativeElement.focus(); - this.repeat(event, null, -1); - this.updateFilledState(); - } - } - - onDownButtonMouseup(event: Event) { - if(!this.disabled) { - this.clearTimer(); - } - } - - onDownButtonMouseleave(event: Event) { - if(!this.disabled) { - this.clearTimer(); - } - } - - onInputKeydown(event: KeyboardEvent) { - if(event.which == 38) { - this.spin(event, 1); - event.preventDefault(); - } - else if(event.which == 40) { - this.spin(event, -1); - event.preventDefault(); - } - } - - onInputKeyPress(event: KeyboardEvent) { - let inputChar = String.fromCharCode(event.charCode); - if(!this.keyPattern.test(inputChar) && inputChar != this.decimalSeparator && event.keyCode != 9 && event.keyCode != 8 && event.keyCode != 37 && event.keyCode != 39 && event.keyCode != 46) { - event.preventDefault(); - } - } - - onInputKeyup(event: KeyboardEvent) { - let inputValue = ( event.target).value; - if (event.key !== this.decimalSeparator && event.key !== this.thousandSeparator) { - this.value = this.parseValue(inputValue); - this.formatValue(); - } - - this.onModelChange(this.value); - this.updateFilledState(); - } - - onInputBlur(event) { - this.focus = false; - this.onModelTouched(); - this.onBlur.emit(event); - } - - onInputFocus(event) { - this.focus = true; - this.onFocus.emit(event); - } - - parseValue(val: string): number { - let value: number; - - if(this.formatInput) { - val = val.split(this.thousandSeparator).join(''); - } - - if(val.trim() === '') { - value = null; - } - else { - if(this.precision) { - value = parseFloat(val.replace(',','.')); - } - else { - value = parseInt(val); - } - - if(!isNaN(value)) { - if(this.max !== undefined && value > this.max) { - value = this.max; - } - - if(this.min !== undefined && value < this.min) { - value = this.min; - } - } - else { - value = null; - } - } - - return value; - } - - formatValue(): void { - if(this.value !== null && this.value !== undefined) { - let textValue = String(this.value).replace('.', this.decimalSeparator); - - if(this.formatInput) { - textValue = textValue.replace(/\B(?=(\d{3})+(?!\d))/g, this.thousandSeparator); - } - - this.valueAsString = textValue; - } - else { - this.valueAsString = ''; - } - - this.inputfieldViewChild.nativeElement.value = this.valueAsString; - } - - handleChange(event: Event) { - this.onChange.emit(event); - } - - clearTimer() { - if(this.timer) { - clearInterval(this.timer); - } - } - - writeValue(value: any) : void { - this.value = value; - this.formatValue(); - this.updateFilledState(); - } - - registerOnChange(fn: Function): void { - this.onModelChange = fn; - } - - registerOnTouched(fn: Function): void { - this.onModelTouched = fn; - } - - setDisabledState(val: boolean): void { - this.disabled = val; - } - - updateFilledState() { - this.filled = (this.value !== undefined && this.value != null); - } -} - - -@NgModule({ - imports: [CommonModule,InputTextModule], - exports: [Spinner], - declarations: [Spinner] -}) -export class SpinnerModule { } diff --git a/dashboard/src/app/components/splitbutton/splitbutton.css b/dashboard/src/app/components/splitbutton/splitbutton.css deleted file mode 100644 index ae8f52a6f..000000000 --- a/dashboard/src/app/components/splitbutton/splitbutton.css +++ /dev/null @@ -1,29 +0,0 @@ -.ui-splitbutton { - position: relative; - display: inline-block; - zoom: 1; -} - -.ui-splitbutton .ui-button.ui-splitbutton-menubutton { - width: 2em; -} - -.ui-splitbutton .ui-button { - vertical-align: top; -} - -.ui-splitbutton.ui-state-disabled button { - cursor: default; -} - -.ui-fluid .ui-splitbutton { - width: 100%; -} - -.ui-fluid .ui-splitbutton .ui-button:first-child { - width: calc(100% - 2em); -} - -.ui-fluid .ui-splitbutton .ui-button.ui-splitbutton-menubutton { - width: 2em; -} \ No newline at end of file diff --git a/dashboard/src/app/components/splitbutton/splitbutton.spec.ts b/dashboard/src/app/components/splitbutton/splitbutton.spec.ts deleted file mode 100644 index f763c159e..000000000 --- a/dashboard/src/app/components/splitbutton/splitbutton.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { SplitButton } from './splitbutton'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('SplitButton', () => { - - let splitbutton: SplitButton; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - SplitButton - ] - }); - - fixture = TestBed.createComponent(SplitButton); - splitbutton = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/splitbutton/splitbutton.ts b/dashboard/src/app/components/splitbutton/splitbutton.ts deleted file mode 100644 index 294d7364e..000000000 --- a/dashboard/src/app/components/splitbutton/splitbutton.ts +++ /dev/null @@ -1,194 +0,0 @@ -import {NgModule,Component,ElementRef,AfterViewInit,AfterViewChecked,OnDestroy,Input,Output,ContentChildren,EventEmitter,QueryList,Renderer2,ChangeDetectorRef,ViewChild} from '@angular/core'; -import {trigger,state,style,transition,animate} from '@angular/animations'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; -import {MenuItem} from '../common/menuitem'; -import {ButtonModule} from '../button/button'; -import {Router} from '@angular/router'; -import {RouterModule} from '@angular/router'; - -@Component({ - selector: 'p-splitButton', - template: ` - - `, - animations: [ - trigger('overlayState', [ - state('hidden', style({ - opacity: 0 - })), - state('visible', style({ - opacity: 1 - })), - transition('visible => hidden', animate('400ms ease-in')), - transition('hidden => visible', animate('400ms ease-out')) - ]) - ], - providers: [DomHandler] -}) -export class SplitButton implements AfterViewInit,AfterViewChecked,OnDestroy { - - @Input() model: MenuItem[]; - - @Input() icon: string; - - @Input() iconPos: string = 'left'; - - @Input() label: string; - - @Output() onClick: EventEmitter = new EventEmitter(); - - @Output() onDropdownClick: EventEmitter = new EventEmitter(); - - @Input() style: any; - - @Input() styleClass: string; - - @Input() menuStyle: any; - - @Input() menuStyleClass: string; - - @Input() disabled: boolean; - - @Input() tabindex: number; - - @Input() appendTo: any; - - @Input() dir: string; - - @ViewChild('container') containerViewChild: ElementRef; - - @ViewChild('defaultbtn') buttonViewChild: ElementRef; - - @ViewChild('overlay') overlayViewChild: ElementRef; - - public menuVisible: boolean = false; - - public documentClickListener: any; - - public dropdownClick: boolean; - - public shown: boolean; - - constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2, public router: Router, public cd: ChangeDetectorRef) {} - - ngAfterViewInit() { - if(this.appendTo) { - if(this.appendTo === 'body') - document.body.appendChild(this.overlayViewChild.nativeElement); - else - this.domHandler.appendChild(this.overlayViewChild.nativeElement, this.appendTo); - } - } - - ngAfterViewChecked() { - if(this.shown) { - this.onShow(); - this.shown = false; - } - } - - onDefaultButtonClick(event: Event) { - this.onClick.emit(event); - } - - itemClick(event: Event, item: MenuItem) { - if(item.disabled) { - event.preventDefault(); - return; - } - - if(!item.url) { - event.preventDefault(); - } - - if(item.command) { - item.command({ - originalEvent: event, - item: item - }); - } - - this.menuVisible = false; - } - - show() { - this.shown = true; - this.menuVisible= !this.menuVisible; - this.alignPanel(); - this.overlayViewChild.nativeElement.style.zIndex = String(++DomHandler.zindex); - } - - onShow() { - this.alignPanel(); - this.bindDocumentClickListener(); - } - - onDropdownButtonClick(event: Event) { - this.onDropdownClick.emit(event); - this.dropdownClick = true; - this.show(); - } - - alignPanel() { - if(this.appendTo) - this.domHandler.absolutePosition(this.overlayViewChild.nativeElement, this.containerViewChild.nativeElement); - else - this.domHandler.relativePosition(this.overlayViewChild.nativeElement, this.containerViewChild.nativeElement); - } - - bindDocumentClickListener() { - if(!this.documentClickListener) { - this.documentClickListener = this.renderer.listen('document', 'click', () => { - if(this.dropdownClick) { - this.dropdownClick = false; - } - else { - this.menuVisible = false; - this.unbindDocumentClickListener(); - this.cd.markForCheck(); - } - }); - } - } - - unbindDocumentClickListener() { - if(this.documentClickListener) { - this.documentClickListener(); - this.documentClickListener = null; - } - } - - ngOnDestroy() { - this.unbindDocumentClickListener(); - } -} - -@NgModule({ - imports: [CommonModule,ButtonModule,RouterModule], - exports: [SplitButton,ButtonModule,RouterModule], - declarations: [SplitButton] -}) -export class SplitButtonModule { } diff --git a/dashboard/src/app/components/steps/steps.css b/dashboard/src/app/components/steps/steps.css deleted file mode 100644 index 0c6039c87..000000000 --- a/dashboard/src/app/components/steps/steps.css +++ /dev/null @@ -1,49 +0,0 @@ -.ui-steps ul { - list-style-type: none; - padding: 0; - margin: 0; -} - -.ui-steps .ui-steps-item { - float: left; - box-sizing: border-box; - cursor: pointer; -} - -.ui-steps.ui-steps-readonly .ui-steps-item { - cursor: auto; -} - -.ui-steps .ui-steps-item .ui-menuitem-link { - text-decoration: none; - display: block; - padding: 1em; - position: relative; - text-align: center; -} - -.ui-steps .ui-steps-item.ui-state-highlight .ui-menuitem-link, -.ui-steps .ui-steps-item.ui-state-disabled .ui-menuitem-link { - cursor: default; -} - -.ui-steps .ui-steps-number { - font-size: 200%; - display: block; -} - -.ui-steps .ui-steps-title { - display: block; - white-space: nowrap; -} - -/* Responsive */ -@media (max-width: 40em) { - .ui-steps .ui-steps-item .ui-menuitem-link { - padding: 0.5em; - } - - .ui-steps .ui-steps-item .ui-steps-title { - display: none; - } -} \ No newline at end of file diff --git a/dashboard/src/app/components/steps/steps.spec.ts b/dashboard/src/app/components/steps/steps.spec.ts deleted file mode 100644 index 4d04bb233..000000000 --- a/dashboard/src/app/components/steps/steps.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Steps } from './steps'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Steps', () => { - - let steps: Steps; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Steps - ] - }); - - fixture = TestBed.createComponent(Steps); - steps = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/steps/steps.ts b/dashboard/src/app/components/steps/steps.ts deleted file mode 100644 index 141ad056a..000000000 --- a/dashboard/src/app/components/steps/steps.ts +++ /dev/null @@ -1,69 +0,0 @@ -import {NgModule,Component,Input,Output,EventEmitter} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {MenuItem} from '../common/menuitem'; -import {RouterModule} from '@angular/router'; - -@Component({ - selector: 'p-steps', - template: ` - - ` -}) -export class Steps { - - @Input() activeIndex: number = 0; - - @Input() model: MenuItem[]; - - @Input() readonly: boolean = true; - - @Input() style: any; - - @Input() styleClass: string; - - @Output() activeIndexChange: EventEmitter = new EventEmitter(); - - itemClick(event: Event, item: MenuItem, i: number) { - if(this.readonly || item.disabled) { - event.preventDefault(); - return; - } - - this.activeIndexChange.emit(i); - - if(!item.url) { - event.preventDefault(); - } - - if(item.command) { - item.command({ - originalEvent: event, - item: item, - index: i - }); - } - } - -} - -@NgModule({ - imports: [CommonModule,RouterModule], - exports: [Steps,RouterModule], - declarations: [Steps] -}) -export class StepsModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/table/table.css b/dashboard/src/app/components/table/table.css deleted file mode 100644 index 4b6e0713d..000000000 --- a/dashboard/src/app/components/table/table.css +++ /dev/null @@ -1,224 +0,0 @@ -.ui-table { - position: relative; -} - -.ui-table table { - border-collapse: collapse; - width: 100%; - table-layout: fixed; -} - -.ui-table .ui-table-thead>tr>th, -.ui-table .ui-table-tbody>tr>td, -.ui-table .ui-table-tfoot>tr>td { - padding: .25em .5em; -} - -.ui-table .ui-sortable-column { - cursor: pointer; -} - -.ui-table-auto-layout>.ui-table-wrapper { - overflow-x: auto; -} - -.ui-table-auto-layout>.ui-table-wrapper>table { - table-layout: auto; -} - - -/* Sections */ - -.ui-table-caption, -.ui-table-summary { - padding: .25em .5em; - text-align: center; - font-weight: bold; -} - -.ui-table-caption { - border-bottom: 0 none; -} - -.ui-table-summary { - border-top: 0 none; -} - - -/* Paginator */ - -.ui-table .ui-paginator-top { - border-bottom: 0 none; -} - -.ui-table .ui-paginator-bottom { - border-top: 0 none; -} - - -/* Scrollable */ - -.ui-table-scrollable-header, -.ui-table-scrollable-footer { - overflow: hidden; - border: 0 none; -} - -.ui-table-scrollable-body { - overflow: auto; - position: relative; -} - -.ui-table-scrollable-body>table>.ui-table-tbody>tr:first-child>td { - border-top: 0 none; -} - -.ui-table-virtual-table { - position: absolute; -} - - -/* Frozen Columns */ - -.ui-table-frozen-view .ui-table-scrollable-body { - overflow: hidden; -} - -.ui-table-frozen-view>.ui-table-scrollable-body>table>.ui-table-tbody>tr>td:last-child { - border-right: 0 none; -} - -.ui-table-unfrozen-view { - position: absolute; - top: 0px; -} - - -/* Resizable */ - -.ui-table-resizable>.ui-table-wrapper { - overflow-x: auto; -} - -.ui-table-resizable .ui-table-thead>tr>th, -.ui-table-resizable .ui-table-tfoot>tr>td, -.ui-table-resizable .ui-table-data>tr>td { - overflow: hidden; -} - -.ui-resizable-column { - background-clip: padding-box; - position: relative; -} - -.ui-table-resizable-fit .ui-resizable-column:last-child .ui-column-resizer { - display: none; -} - -.ui-table .ui-column-resizer { - display: block; - position: absolute !important; - top: 0; - right: 0; - margin: 0; - width: .5em; - height: 100%; - padding: 0px; - cursor: col-resize; - border: 1px solid transparent; -} - -.ui-table .ui-column-resizer-helper { - width: 1px; - position: absolute; - z-index: 10; - display: none; -} - - -/* Edit */ - -.ui-table .ui-table-tbody>tr>td.ui-editing-cell { - padding: 0; -} - -.ui-table .ui-table-tbody>tr>td.ui-editing-cell p-celleditor>* { - width: 100%; -} - - -/* Reorder */ - -.ui-table-reorder-indicator-up, -.ui-table-reorder-indicator-down { - position: absolute; - display: none; -} - - -/* Responsive */ - -.ui-table-responsive .ui-table-tbody>tr>td .ui-column-title { - display: none; -} - -@media screen and (max-width: 40em) { - .ui-table-responsive .ui-table-thead>tr>th, - .ui-table-responsive .ui-table-tfoot>tr>td { - display: none !important; - } - .ui-table-responsive .ui-table-tbody>tr>td { - text-align: left; - display: block; - border: 0 none; - width: 100% !important; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - float: left; - clear: left; - } - .ui-table-responsive .ui-table-tbody>tr>td .ui-column-title { - padding: .4em; - min-width: 30%; - display: inline-block; - margin: -.4em 1em -.4em -.4em; - font-weight: bold; - } -} - - -/* Loader */ - -.ui-table-loading { - position: absolute; - width: 100%; - height: 100%; - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=10)"; - opacity: 0.1; - z-index: 1; -} - -.ui-table-loading-content { - position: absolute; - left: 50%; - top: 50%; - z-index: 2; - margin-top: -1em; - margin-left: -1em; -} - - -/* 自定义table modifyProfile start */ - -.custom-table-class tr td, -.custom-table-class th { - color: #657D95 !important; - font-weight: normal; - text-align: left; - line-height: 2em; - border: none !important; -} - - -/* 自定义table modifyProfile end */ \ No newline at end of file diff --git a/dashboard/src/app/components/table/table.ts b/dashboard/src/app/components/table/table.ts deleted file mode 100644 index 985237856..000000000 --- a/dashboard/src/app/components/table/table.ts +++ /dev/null @@ -1,2889 +0,0 @@ -import { NgModule, Component, HostListener, OnInit, AfterViewInit, Directive, AfterContentInit, Input, Output, EventEmitter, ElementRef, ContentChildren, TemplateRef, QueryList, ViewChild, NgZone, EmbeddedViewRef, ViewContainerRef} from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { Column, PrimeTemplate, SharedModule } from '../common/shared'; -import { PaginatorModule } from '../paginator/paginator'; -import { DomHandler } from '../dom/domhandler'; -import { ObjectUtils } from '../utils/objectutils'; -import { SortMeta } from '../common/sortmeta'; -import { FilterMetadata } from '../common/filtermetadata'; -import { OnDestroy } from '@angular/core/src/metadata/lifecycle_hooks'; -import { Injectable } from '@angular/core'; -import { Subject } from 'rxjs/Subject'; -import { Subscription } from 'rxjs/Subscription'; -import { Observable } from 'rxjs/Observable'; - -@Injectable() -export class TableService { - - private sortSource = new Subject(); - private selectionSource = new Subject(); - private contextMenuSource = new Subject(); - private valueSource = new Subject(); - - sortSource$ = this.sortSource.asObservable(); - selectionSource$ = this.selectionSource.asObservable(); - contextMenuSource$ = this.contextMenuSource.asObservable(); - valueSource$ = this.valueSource.asObservable(); - - onSort(sortMeta: SortMeta|SortMeta[]) { - this.sortSource.next(sortMeta); - } - - onSelectionChange() { - this.selectionSource.next(); - } - - onContextMenu(data: any) { - this.contextMenuSource.next(data); - } - - onValueChange(value: any) { - this.valueSource.next(value); - } -} - -@Component({ - selector: 'p-table', - template: ` -
-
-
- -
-
- -
- - -
- - - - - - - - - -
-
- -
-
-
-
- - -
- -
- - - - - -
- `, - providers: [DomHandler, ObjectUtils, TableService] -}) -export class Table implements OnInit, AfterContentInit { - - @Input() columns: any[]; - - @Input() frozenColumns: any[]; - - @Input() frozenValue: any[]; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() paginator: boolean; - - @Input() rows: number; - - @Input() first: number = 0; - - @Input() totalRecords: number = 0; - - @Input() pageLinks: number = 5; - - @Input() rowsPerPageOptions: number[]; - - @Input() alwaysShowPaginator: boolean = true; - - @Input() paginatorPosition: string = 'bottom'; - - @Input() paginatorDropdownAppendTo: any; - - @Input() defaultSortOrder: number = 1; - - @Input() sortMode: string = 'single'; - - @Input() selectionMode: string; - - @Output() selectionChange: EventEmitter = new EventEmitter(); - - @Input() contextMenuSelection: any; - - @Output() contextMenuSelectionChange: EventEmitter = new EventEmitter(); - - @Input() dataKey: string; - - @Input() metaKeySelection: boolean; - - @Input() rowTrackBy: Function = (index: number, item: any) => item; - - @Input() lazy: boolean = false; - - @Input() compareSelectionBy: string = 'deepEquals'; - - @Input() csvSeparator: string = ','; - - @Input() exportFilename: string = 'download'; - - @Input() filters: { [s: string]: FilterMetadata; } = {}; - - @Input() globalFilterFields: string[]; - - @Input() filterDelay: number = 300; - - @Input() expandedRowKeys: { [s: string]: number; } = {}; - - @Input() rowExpandMode: string = 'multiple'; - - @Input() scrollable: boolean; - - @Input() scrollHeight: string; - - @Input() virtualScroll: boolean; - - @Input() virtualScrollDelay: number = 500; - - @Input() virtualRowHeight: number = 27; - - @Input() frozenWidth: string; - - @Input() responsive: boolean; - - @Input() contextMenu: any; - - @Input() resizableColumns: boolean; - - @Input() columnResizeMode: string = 'fit'; - - @Input() reorderableColumns: boolean; - - @Input() loading: boolean; - - @Input() loadingIcon: string = 'fa fa-spin fa-2x fa-circle-o-notch'; - - @Input() rowHover: boolean; - - @Input() customSort: boolean; - - @Input() autoLayout: boolean; - - @Output() onRowSelect: EventEmitter = new EventEmitter(); - - @Output() onRowUnselect: EventEmitter = new EventEmitter(); - - @Output() onPage: EventEmitter = new EventEmitter(); - - @Output() onSort: EventEmitter = new EventEmitter(); - - @Output() onFilter: EventEmitter = new EventEmitter(); - - @Output() onLazyLoad: EventEmitter = new EventEmitter(); - - @Output() onRowExpand: EventEmitter = new EventEmitter(); - - @Output() onRowCollapse: EventEmitter = new EventEmitter(); - - @Output() onContextMenuSelect: EventEmitter = new EventEmitter(); - - @Output() onColResize: EventEmitter = new EventEmitter(); - - @Output() onColReorder: EventEmitter = new EventEmitter(); - - @Output() onRowReorder: EventEmitter = new EventEmitter(); - - @Output() onEditInit: EventEmitter = new EventEmitter(); - - @Output() onEditComplete: EventEmitter = new EventEmitter(); - - @Output() onEditCancel: EventEmitter = new EventEmitter(); - - @Output() onHeaderCheckboxToggle: EventEmitter = new EventEmitter(); - - @Output() sortFunction: EventEmitter = new EventEmitter(); - - @ViewChild('container') containerViewChild: ElementRef; - - @ViewChild('resizeHelper') resizeHelperViewChild: ElementRef; - - @ViewChild('reorderIndicatorUp') reorderIndicatorUpViewChild: ElementRef; - - @ViewChild('reorderIndicatorDown') reorderIndicatorDownViewChild: ElementRef; - - @ViewChild('table') tableViewChild: ElementRef; - - @ContentChildren(PrimeTemplate) templates: QueryList; - - _value: any[] = []; - - filteredValue: any[]; - - headerTemplate: TemplateRef; - - bodyTemplate: TemplateRef; - - captionTemplate: TemplateRef; - - frozenRowsTemplate: TemplateRef; - - footerTemplate: TemplateRef; - - summaryTemplate: TemplateRef; - - colGroupTemplate: TemplateRef; - - expandedRowTemplate: TemplateRef; - - frozenHeaderTemplate: TemplateRef; - - frozenBodyTemplate: TemplateRef; - - frozenFooterTemplate: TemplateRef; - - frozenColGroupTemplate: TemplateRef; - - emptyMessageTemplate: TemplateRef; - - paginatorLeftTemplate: TemplateRef; - - paginatorRightTemplate: TemplateRef; - - selectionKeys: any = {}; - - lastResizerHelperX: number; - - reorderIconWidth: number; - - reorderIconHeight: number; - - draggedColumn: any; - - draggedRowIndex: number; - - droppedRowIndex: number; - - rowDragging: boolean; - - dropPosition: number; - - editingCell: Element; - - _multiSortMeta: SortMeta[]; - - _sortField: string; - - _sortOrder: number = 1; - - virtualScrollTimer: any; - - virtualScrollCallback: Function; - - preventSelectionSetterPropagation: boolean; - - _selection: any; - - anchorRowIndex: number; - - rangeRowIndex: number; - - filterTimeout: any; - - initialized: boolean; - - rowTouched: boolean; - - constructor(public el: ElementRef, public domHandler: DomHandler, public objectUtils: ObjectUtils, public zone: NgZone, public tableService: TableService) {} - - ngOnInit() { - if (this.lazy) { - this.onLazyLoad.emit(this.createLazyLoadMetadata()); - } - this.initialized = true; - } - - ngAfterContentInit() { - this.templates.forEach((item) => { - switch (item.getType()) { - case 'caption': - this.captionTemplate = item.template; - break; - - case 'header': - this.headerTemplate = item.template; - break; - - case 'body': - this.bodyTemplate = item.template; - break; - - case 'footer': - this.footerTemplate = item.template; - break; - - case 'summary': - this.summaryTemplate = item.template; - break; - - case 'colgroup': - this.colGroupTemplate = item.template; - break; - - case 'rowexpansion': - this.expandedRowTemplate = item.template; - break; - - case 'frozenrows': - this.frozenRowsTemplate = item.template; - break; - - case 'frozenheader': - this.frozenHeaderTemplate = item.template; - break; - - case 'frozenbody': - this.frozenBodyTemplate = item.template; - break; - - case 'frozenfooter': - this.frozenFooterTemplate = item.template; - break; - - case 'frozencolgroup': - this.frozenColGroupTemplate = item.template; - break; - - case 'emptymessage': - this.emptyMessageTemplate = item.template; - break; - - case 'paginatorleft': - this.paginatorLeftTemplate = item.template; - break; - - case 'paginatorright': - this.paginatorRightTemplate = item.template; - break; - } - }); - } - - @Input() get value(): any[] { - return this._value; - } - set value(val: any[]) { - this._value = val; - this.updateTotalRecords(); - - if (!this.lazy) { - if (this.sortMode == 'single') - this.sortSingle(); - else if (this.sortMode == 'multiple') - this.sortMultiple(); - } - - if(this.virtualScroll && this.virtualScrollCallback) { - this.virtualScrollCallback(); - } - - this.tableService.onValueChange(val); - } - - @Input() get sortField(): string { - return this._sortField; - } - - set sortField(val: string) { - this._sortField = val; - - //avoid triggering lazy load prior to lazy initialization at onInit - if ( !this.lazy || this.initialized ) { - if (this.sortMode === 'single') { - this.sortSingle(); - } - } - } - - @Input() get sortOrder(): number { - return this._sortOrder; - } - set sortOrder(val: number) { - this._sortOrder = val; - - //avoid triggering lazy load prior to lazy initialization at onInit - if ( !this.lazy || this.initialized ) { - if (this.sortMode === 'single') { - this.sortSingle(); - } - } - } - - @Input() get multiSortMeta(): SortMeta[] { - return this._multiSortMeta; - } - - set multiSortMeta(val: SortMeta[]) { - this._multiSortMeta = val; - if (this.sortMode === 'multiple') { - this.sortMultiple(); - } - } - - @Input() get selection(): any { - return this._selection; - } - - set selection(val: any) { - this._selection = val; - - if(!this.preventSelectionSetterPropagation) { - this.updateSelectionKeys(); - this.tableService.onSelectionChange(); - } - this.preventSelectionSetterPropagation = false; - } - - updateSelectionKeys() { - if(this.dataKey && this._selection) { - this.selectionKeys = {}; - if(Array.isArray(this._selection)) { - for(let data of this._selection) { - this.selectionKeys[String(this.objectUtils.resolveFieldData(data, this.dataKey))] = 1; - } - } - else { - this.selectionKeys[String(this.objectUtils.resolveFieldData(this._selection, this.dataKey))] = 1; - } - } - } - - updateTotalRecords() { - this.totalRecords = this.lazy ? this.totalRecords : (this._value ? this._value.length : 0); - } - - onPageChange(event) { - this.first = event.first; - this.rows = event.rows; - - if (this.lazy) { - this.onLazyLoad.emit(this.createLazyLoadMetadata()); - } - - this.onPage.emit({ - first: this.first, - rows: this.rows - }); - - this.tableService.onValueChange(this.value); - } - - sort(event) { - let originalEvent = event.originalEvent; - - if(this.sortMode === 'single') { - this._sortOrder = (this.sortField === event.field) ? this.sortOrder * -1 : this.defaultSortOrder; - this._sortField = event.field; - this.sortSingle(); - } - if (this.sortMode === 'multiple') { - let metaKey = originalEvent.metaKey || originalEvent.ctrlKey; - let sortMeta = this.getSortMeta(event.field); - - if (sortMeta) { - if (!metaKey) { - this._multiSortMeta = [{ field: event.field, order: sortMeta.order * -1 }] - } - else { - sortMeta.order = sortMeta.order * -1; - } - } - else { - if (!metaKey || !this.multiSortMeta) { - this._multiSortMeta = []; - } - this.multiSortMeta.push({ field: event.field, order: this.defaultSortOrder }); - } - - this.sortMultiple(); - } - } - - sortSingle() { - if(this.sortField && this.sortOrder) { - this.first = 0; - - if(this.lazy) { - this.onLazyLoad.emit(this.createLazyLoadMetadata()); - } - else if (this.value) { - if(this.customSort) { - this.sortFunction.emit({ - data: this.value, - mode: this.sortMode, - field: this.sortField, - order: this.sortOrder - }); - } - else { - this.value.sort((data1, data2) => { - let value1 = this.objectUtils.resolveFieldData(data1, this.sortField); - let value2 = this.objectUtils.resolveFieldData(data2, this.sortField); - let result = null; - - if (value1 == null && value2 != null) - result = -1; - else if (value1 != null && value2 == null) - result = 1; - else if (value1 == null && value2 == null) - result = 0; - else if (typeof value1 === 'string' && typeof value2 === 'string') - result = value1.localeCompare(value2); - else - result = (value1 < value2) ? -1 : (value1 > value2) ? 1 : 0; - - return (this.sortOrder * result); - }); - } - - if(this.hasFilter()) { - this._filter(); - } - } - - let sortMeta: SortMeta = { - field: this.sortField, - order: this.sortOrder - }; - - this.onSort.emit(sortMeta); - this.tableService.onSort(sortMeta); - } - } - - sortMultiple() { - if(this.multiSortMeta) { - if (this.lazy) { - this.onLazyLoad.emit(this.createLazyLoadMetadata()); - } - else if (this.value) { - if(this.customSort) { - this.sortFunction.emit({ - data: this.value, - mode: this.sortMode, - multiSortMeta: this.multiSortMeta - }); - } - else { - this.value.sort((data1, data2) => { - return this.multisortField(data1, data2, this.multiSortMeta, 0); - }); - } - - if(this.hasFilter()) { - this._filter(); - } - } - - this.onSort.emit({ - multisortmeta: this.multiSortMeta - }); - this.tableService.onSort(this.multiSortMeta); - } - } - - multisortField(data1, data2, multiSortMeta, index) { - let value1 = this.objectUtils.resolveFieldData(data1, multiSortMeta[index].field); - let value2 = this.objectUtils.resolveFieldData(data2, multiSortMeta[index].field); - let result = null; - - if (typeof value1 == 'string' || value1 instanceof String) { - if (value1.localeCompare && (value1 != value2)) { - return (multiSortMeta[index].order * value1.localeCompare(value2)); - } - } - else { - result = (value1 < value2) ? -1 : 1; - } - - if (value1 == value2) { - return (multiSortMeta.length - 1) > (index) ? (this.multisortField(data1, data2, multiSortMeta, index + 1)) : 0; - } - - return (multiSortMeta[index].order * result); - } - - getSortMeta(field: string) { - if (this.multiSortMeta && this.multiSortMeta.length) { - for (let i = 0; i < this.multiSortMeta.length; i++) { - if (this.multiSortMeta[i].field === field) { - return this.multiSortMeta[i]; - } - } - } - - return null; - } - - isSorted(field: string) { - if(this.sortMode === 'single') { - return (this.sortField && this.sortField === field); - } - else if(this.sortMode === 'multiple') { - let sorted = false; - if(this.multiSortMeta) { - for(let i = 0; i < this.multiSortMeta.length; i++) { - if(this.multiSortMeta[i].field == field) { - sorted = true; - break; - } - } - } - return sorted; - } - } - - handleRowClick(event) { - let targetNode = ( event.originalEvent.target).nodeName; - if (targetNode == 'INPUT' || targetNode == 'BUTTON' || targetNode == 'A' || (this.domHandler.hasClass(event.originalEvent.target, 'ui-clickable'))) { - return; - } - - if(this.selectionMode) { - this.preventSelectionSetterPropagation = true; - if(this.isMultipleSelectionMode() && event.originalEvent.shiftKey && this.anchorRowIndex != null) { - this.domHandler.clearSelection(); - if(this.rangeRowIndex != null) { - this.clearSelectionRange(event.originalEvent); - } - - this.rangeRowIndex = event.rowIndex; - this.selectRange(event.originalEvent, event.rowIndex); - } - else { - let rowData = event.rowData; - let selected = this.isSelected(rowData); - let metaSelection = this.rowTouched ? false : this.metaKeySelection; - let dataKeyValue = this.dataKey ? String(this.objectUtils.resolveFieldData(rowData, this.dataKey)) : null; - this.anchorRowIndex = event.rowIndex; - this.rangeRowIndex = event.rowIndex; - - if(metaSelection) { - let metaKey = event.originalEvent.metaKey||event.originalEvent.ctrlKey; - - if(selected && metaKey) { - if(this.isSingleSelectionMode()) { - this._selection = null; - this.selectionKeys = {}; - this.selectionChange.emit(null); - } - else { - let selectionIndex = this.findIndexInSelection(rowData); - this._selection = this.selection.filter((val,i) => i!=selectionIndex); - this.selectionChange.emit(this.selection); - if(dataKeyValue) { - delete this.selectionKeys[dataKeyValue]; - } - } - - this.onRowUnselect.emit({originalEvent: event.originalEvent, data: rowData, type: 'row'}); - } - else { - if(this.isSingleSelectionMode()) { - this._selection = rowData; - this.selectionChange.emit(rowData); - if(dataKeyValue) { - this.selectionKeys = {}; - this.selectionKeys[dataKeyValue] = 1; - } - } - else if(this.isMultipleSelectionMode()) { - if(metaKey) { - this._selection = this.selection||[]; - } - else { - this._selection = []; - this.selectionKeys = {}; - } - - this._selection = [...this.selection,rowData]; - this.selectionChange.emit(this.selection); - if(dataKeyValue) { - this.selectionKeys[dataKeyValue] = 1; - } - } - - this.onRowSelect.emit({originalEvent: event.originalEvent, data: rowData, type: 'row'}); - } - } - else { - if (this.selectionMode === 'single') { - if (selected) { - this._selection = null; - this.selectionKeys = {}; - this.selectionChange.emit(this.selection); - this.onRowUnselect.emit({ originalEvent: event.originalEvent, data: rowData, type: 'row' }); - } - else { - this._selection = rowData; - this.selectionChange.emit(this.selection); - this.onRowSelect.emit({ originalEvent: event.originalEvent, data: rowData, type: 'row' }); - if (dataKeyValue) { - this.selectionKeys = {}; - this.selectionKeys[dataKeyValue] = 1; - } - } - } - else if (this.selectionMode === 'multiple') { - if (selected) { - let selectionIndex = this.findIndexInSelection(rowData); - this._selection = this.selection.filter((val, i) => i != selectionIndex); - this.selectionChange.emit(this.selection); - this.onRowUnselect.emit({ originalEvent: event.originalEvent, data: rowData, type: 'row' }); - if (dataKeyValue) { - delete this.selectionKeys[dataKeyValue]; - } - } - else { - this._selection = this.selection ? [...this.selection, rowData] : [rowData]; - this.selectionChange.emit(this.selection); - this.onRowSelect.emit({ originalEvent: event.originalEvent, data: rowData, type: 'row' }); - if (dataKeyValue) { - this.selectionKeys[dataKeyValue] = 1; - } - } - } - } - } - - this.tableService.onSelectionChange(); - } - - this.rowTouched = false; - } - - handleRowTouchEnd(event) { - this.rowTouched = true; - } - - handleRowRightClick(event) { - if (this.contextMenu) { - this.contextMenuSelection = event.rowData; - this.contextMenuSelectionChange.emit(event.rowData); - this.onContextMenuSelect.emit({ originalEvent: event.originalEvent, data: event.rowData }); - this.contextMenu.show(event.originalEvent); - this.tableService.onContextMenu(event.rowData); - } - } - - selectRange(event: MouseEvent, rowIndex: number) { - let rangeStart, rangeEnd; - - if(this.anchorRowIndex > rowIndex) { - rangeStart = rowIndex; - rangeEnd = this.anchorRowIndex; - } - else if(this.anchorRowIndex < rowIndex) { - rangeStart = this.anchorRowIndex; - rangeEnd = rowIndex; - } - else { - rangeStart = rowIndex; - rangeEnd = rowIndex; - } - - for(let i = rangeStart; i <= rangeEnd; i++) { - let rangeRowData = this.value[i]; - if(!this.isSelected(rangeRowData)) { - this._selection = [...this.selection, rangeRowData]; - let dataKeyValue: string = this.dataKey ? String(this.objectUtils.resolveFieldData(rangeRowData, this.dataKey)) : null; - if(dataKeyValue) { - this.selectionKeys[dataKeyValue] = 1; - } - this.onRowSelect.emit({originalEvent: event, data: rangeRowData, type: 'row'}); - } - } - - this.selectionChange.emit(this.selection); - } - - clearSelectionRange(event: MouseEvent) { - let rangeStart, rangeEnd; - - if(this.rangeRowIndex > this.anchorRowIndex) { - rangeStart = this.anchorRowIndex; - rangeEnd = this.rangeRowIndex; - } - else if(this.rangeRowIndex < this.anchorRowIndex) { - rangeStart = this.rangeRowIndex; - rangeEnd = this.anchorRowIndex; - } - else { - rangeStart = this.rangeRowIndex; - rangeEnd = this.rangeRowIndex; - } - - for(let i = rangeStart; i <= rangeEnd; i++) { - let rangeRowData = this.value[i]; - let selectionIndex = this.findIndexInSelection(rangeRowData); - this._selection = this.selection.filter((val,i) => i!=selectionIndex); - let dataKeyValue: string = this.dataKey ? String(this.objectUtils.resolveFieldData(rangeRowData, this.dataKey)) : null; - if(dataKeyValue) { - delete this.selectionKeys[dataKeyValue]; - } - this.onRowUnselect.emit({originalEvent: event, data: rangeRowData, type: 'row'}); - } - } - - isSelected(rowData) { - if (rowData && this.selection) { - if (this.dataKey) { - return this.selectionKeys[this.objectUtils.resolveFieldData(rowData, this.dataKey)] !== undefined; - } - else { - if (this.selection instanceof Array) - return this.findIndexInSelection(rowData) > -1; - else - return this.equals(rowData, this.selection); - } - } - - return false; - } - - findIndexInSelection(rowData: any) { - let index: number = -1; - if (this.selection && this.selection.length) { - for (let i = 0; i < this.selection.length; i++) { - if (this.equals(rowData, this.selection[i])) { - index = i; - break; - } - } - } - - return index; - } - - toggleRowWithRadio(event: Event, rowData:any) { - this.preventSelectionSetterPropagation = true; - - if(this.selection != rowData) { - this._selection = rowData; - this.selectionChange.emit(this.selection); - this.onRowSelect.emit({originalEvent: event, data: rowData, type: 'radiobutton'}); - - if(this.dataKey) { - this.selectionKeys = {}; - this.selectionKeys[String(this.objectUtils.resolveFieldData(rowData, this.dataKey))] = 1; - } - } - else { - this._selection = null; - this.selectionChange.emit(this.selection); - this.onRowUnselect.emit({originalEvent: event, data: rowData, type: 'radiobutton'}); - } - - this.tableService.onSelectionChange(); - } - - toggleRowWithCheckbox(event, rowData: any) { - this.selection = this.selection||[]; - let selected = this.isSelected(rowData); - let dataKeyValue = this.dataKey ? String(this.objectUtils.resolveFieldData(rowData, this.dataKey)) : null; - this.preventSelectionSetterPropagation = true; - - if (selected) { - let selectionIndex = this.findIndexInSelection(rowData); - this._selection = this.selection.filter((val, i) => i != selectionIndex); - this.selectionChange.emit(this.selection); - this.onRowUnselect.emit({ originalEvent: event.originalEvent, data: rowData, type: 'checkbox' }); - if (dataKeyValue) { - delete this.selectionKeys[dataKeyValue]; - } - } - else { - this._selection = this.selection ? [...this.selection, rowData] : [rowData]; - this.selectionChange.emit(this.selection); - this.onRowSelect.emit({ originalEvent: event.originalEvent, data: rowData, type: 'checkbox' }); - if (dataKeyValue) { - this.selectionKeys[dataKeyValue] = 1; - } - } - - this.tableService.onSelectionChange(); - } - - toggleRowsWithCheckbox(event: Event, check: boolean) { - this._selection = check ? this.value.slice() : []; - this.preventSelectionSetterPropagation = true; - this.updateSelectionKeys(); - this.selectionChange.emit(this._selection); - this.tableService.onSelectionChange(); - this.onHeaderCheckboxToggle.emit({originalEvent: event, checked: check}); - } - - equals(data1, data2) { - return this.compareSelectionBy === 'equals' ? (data1 === data2) : this.objectUtils.equals(data1, data2, this.dataKey); - } - - filter(value, field, matchMode) { - if(this.filterTimeout) { - clearTimeout(this.filterTimeout); - } - - this.filterTimeout = setTimeout(() => { - if (!this.isFilterBlank(value)) - this.filters[field] = { value: value, matchMode: matchMode }; - else if (this.filters[field]) - delete this.filters[field]; - - this._filter(); - this.filterTimeout = null; - }, this.filterDelay); - } - - filterGlobal(value, matchMode) { - this.filter(value, 'global', matchMode); - } - - isFilterBlank(filter: any): boolean { - if (filter !== null && filter !== undefined) { - if ((typeof filter === 'string' && filter.trim().length == 0) || (filter instanceof Array && filter.length == 0)) - return true; - else - return false; - } - return true; - } - - _filter() { - this.first = 0; - - if (this.lazy) { - this.onLazyLoad.emit(this.createLazyLoadMetadata()); - } - else { - if (!this.value) { - return; - } - - if(!this.hasFilter()) { - this.filteredValue = null; - if (this.paginator) { - this.totalRecords = this.value ? this.value.length : 0; - } - } - else { - let globalFilterFieldsArray; - if (this.filters['global']) { - if (!this.columns && !this.globalFilterFields) - throw new Error('Global filtering requires dynamic columns or globalFilterFields to be defined.'); - else - globalFilterFieldsArray = this.globalFilterFields||this.columns; - } - - this.filteredValue = []; - - for (let i = 0; i < this.value.length; i++) { - let localMatch = true; - let globalMatch = false; - let localFiltered = false; - - for (let prop in this.filters) { - if (this.filters.hasOwnProperty(prop) && prop !== 'global') { - localFiltered = true; - let filterMeta = this.filters[prop]; - let filterField = prop; - let filterValue = filterMeta.value; - let filterMatchMode = filterMeta.matchMode || 'startsWith'; - let dataFieldValue = this.objectUtils.resolveFieldData(this.value[i], filterField); - let filterConstraint = this.filterConstraints[filterMatchMode]; - - if (!filterConstraint(dataFieldValue, filterValue)) { - localMatch = false; - } - - if (!localMatch) { - break; - } - } - } - - if (this.filters['global'] && !globalMatch && globalFilterFieldsArray) { - for(let j = 0; j < globalFilterFieldsArray.length; j++) { - let globalFilterField = globalFilterFieldsArray[j].field||globalFilterFieldsArray[j]; - globalMatch = this.filterConstraints[this.filters['global'].matchMode](this.objectUtils.resolveFieldData(this.value[i], globalFilterField), this.filters['global'].value); - - if(globalMatch) { - break; - } - } - } - - let matches: boolean; - if(this.filters['global']) { - matches = localFiltered ? (localFiltered && localMatch && globalMatch) : globalMatch; - } - else { - matches = localFiltered && localMatch; - } - - if (matches) { - this.filteredValue.push(this.value[i]); - } - } - - if (this.filteredValue.length === this.value.length) { - this.filteredValue = null; - } - - if (this.paginator) { - this.totalRecords = this.filteredValue ? this.filteredValue.length : this.value ? this.value.length : 0; - } - } - } - - this.onFilter.emit({ - filters: this.filters, - filteredValue: this.filteredValue || this.value - }); - - this.tableService.onValueChange(this.value); - } - - hasFilter() { - let empty = true; - for (let prop in this.filters) { - if (this.filters.hasOwnProperty(prop)) { - empty = false; - break; - } - } - - return !empty; - } - - filterConstraints = { - - startsWith(value, filter): boolean { - if (filter === undefined || filter === null || filter.trim() === '') { - return true; - } - - if (value === undefined || value === null) { - return false; - } - - let filterValue = filter.toLowerCase(); - return value.toString().toLowerCase().slice(0, filterValue.length) === filterValue; - }, - - contains(value, filter): boolean { - if (filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) { - return true; - } - - if (value === undefined || value === null) { - return false; - } - - return value.toString().toLowerCase().indexOf(filter.toLowerCase()) !== -1; - }, - - endsWith(value, filter): boolean { - if (filter === undefined || filter === null || filter.trim() === '') { - return true; - } - - if (value === undefined || value === null) { - return false; - } - - let filterValue = filter.toString().toLowerCase(); - return value.toString().toLowerCase().indexOf(filterValue, value.toString().length - filterValue.length) !== -1; - }, - - equals(value, filter): boolean { - if (filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) { - return true; - } - - if (value === undefined || value === null) { - return false; - } - - return value.toString().toLowerCase() == filter.toString().toLowerCase(); - }, - - notEquals(value, filter): boolean { - if (filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) { - return false; - } - - if (value === undefined || value === null) { - return true; - } - - return value.toString().toLowerCase() != filter.toString().toLowerCase(); - }, - - in(value, filter: any[]): boolean { - if (filter === undefined || filter === null || filter.length === 0) { - return true; - } - - if (value === undefined || value === null) { - return false; - } - - for (let i = 0; i < filter.length; i++) { - if (filter[i] === value) - return true; - } - - return false; - }, - - lt(value, filter): boolean { - if (filter === undefined || filter === null) { - return true; - } - - if (value === undefined || value === null) { - return false; - } - - return value < filter; - }, - - gt(value, filter): boolean { - if (filter === undefined || filter === null) { - return true; - } - - if (value === undefined || value === null) { - return false; - } - - return value > filter; - } - } - - createLazyLoadMetadata(): any { - return { - first: this.first, - rows: this.virtualScroll ? this.rows * 2: this.rows, - sortField: this.sortField, - sortOrder: this.sortOrder, - filters: this.filters, - globalFilter: this.filters && this.filters['global'] ? this.filters['global'].value : null, - multiSortMeta: this.multiSortMeta - }; - } - - public reset() { - this._sortField = null; - this._sortOrder = 1; - this._multiSortMeta = null; - - this.filteredValue = null; - this.filters = {}; - - this.first = 0; - this.updateTotalRecords(); - - if(this.lazy) { - this.onLazyLoad.emit(this.createLazyLoadMetadata()); - } - } - - public exportCSV(options?: any) { - let data = this.filteredValue || this.value; - let csv = '\ufeff'; - - if (options && options.selectionOnly) { - data = this.selection || []; - } - - //headers - for (let i = 0; i < this.columns.length; i++) { - let column = this.columns[i]; - if (column.exportable !== false && column.field) { - csv += '"' + (column.header || column.field) + '"'; - - if (i < (this.columns.length - 1)) { - csv += this.csvSeparator; - } - } - } - - //body - data.forEach((record, i) => { - csv += '\n'; - for (let i = 0; i < this.columns.length; i++) { - let column = this.columns[i]; - if (column.exportable !== false && column.field) { - let cellData = this.objectUtils.resolveFieldData(record, column.field); - - if (cellData != null) - cellData = String(cellData).replace(/"/g, '""'); - else - cellData = ''; - - csv += '"' + cellData + '"'; - - if (i < (this.columns.length - 1)) { - csv += this.csvSeparator; - } - } - } - }); - - let blob = new Blob([csv], { - type: 'text/csv;charset=utf-8;' - }); - - if (window.navigator.msSaveOrOpenBlob) { - navigator.msSaveOrOpenBlob(blob, this.exportFilename + '.csv'); - } - else { - let link = document.createElement("a"); - link.style.display = 'none'; - document.body.appendChild(link); - if (link.download !== undefined) { - link.setAttribute('href', URL.createObjectURL(blob)); - link.setAttribute('download', this.exportFilename + '.csv'); - link.click(); - } - else { - csv = 'data:text/csv;charset=utf-8,' + csv; - window.open(encodeURI(csv)); - } - document.body.removeChild(link); - } - } - - toggleRow(rowData: any, event?: Event) { - if(!this.dataKey) { - throw new Error('dataKey must be defined to use row expansion'); - } - - let dataKeyValue = String(this.objectUtils.resolveFieldData(rowData, this.dataKey)); - - if (this.expandedRowKeys[dataKeyValue] != null) { - delete this.expandedRowKeys[dataKeyValue]; - this.onRowCollapse.emit({ - originalEvent: event, - data: rowData - }); - } - else { - if (this.rowExpandMode === 'single') { - this.expandedRowKeys = {}; - } - - this.expandedRowKeys[dataKeyValue] = 1; - this.onRowExpand.emit({ - originalEvent: event, - data: rowData - }); - } - - if (event) { - event.preventDefault(); - } - } - - isRowExpanded(rowData: any): boolean { - return this.expandedRowKeys[String(this.objectUtils.resolveFieldData(rowData, this.dataKey))] === 1; - } - - isSingleSelectionMode() { - return this.selectionMode === 'single'; - } - - isMultipleSelectionMode() { - return this.selectionMode === 'multiple'; - } - - onColumnResizeBegin(event) { - let containerLeft = this.domHandler.getOffset(this.containerViewChild.nativeElement).left; - this.lastResizerHelperX = (event.pageX - containerLeft + this.containerViewChild.nativeElement.scrollLeft); - } - - onColumnResize(event) { - let containerLeft = this.domHandler.getOffset(this.containerViewChild.nativeElement).left; - this.domHandler.addClass(this.containerViewChild.nativeElement, 'ui-unselectable-text'); - this.resizeHelperViewChild.nativeElement.style.height = this.containerViewChild.nativeElement.offsetHeight + 'px'; - this.resizeHelperViewChild.nativeElement.style.top = 0 + 'px'; - this.resizeHelperViewChild.nativeElement.style.left = (event.pageX - containerLeft + this.containerViewChild.nativeElement.scrollLeft) + 'px'; - - this.resizeHelperViewChild.nativeElement.style.display = 'block'; - } - - onColumnResizeEnd(event, column) { - let delta = this.resizeHelperViewChild.nativeElement.offsetLeft - this.lastResizerHelperX; - let columnWidth = column.offsetWidth; - let newColumnWidth = columnWidth + delta; - let minWidth = column.style.minWidth || 15; - - if (columnWidth + delta > parseInt(minWidth)) { - if (this.columnResizeMode === 'fit') { - let nextColumn = column.nextElementSibling; - while (!nextColumn.offsetParent) { - nextColumn = nextColumn.nextElementSibling; - } - - if (nextColumn) { - let nextColumnWidth = nextColumn.offsetWidth - delta; - let nextColumnMinWidth = nextColumn.style.minWidth || 15; - - if (newColumnWidth > 15 && nextColumnWidth > parseInt(nextColumnMinWidth)) { - if (this.scrollable) { - let scrollableBodyTable = this.domHandler.findSingle(this.el.nativeElement, 'table.ui-table-scrollable-body-table'); - let scrollableHeaderTable = this.domHandler.findSingle(this.el.nativeElement, 'table.ui-table-scrollable-header-table'); - let scrollableFooterTable = this.domHandler.findSingle(this.el.nativeElement, 'table.ui-table-scrollable-footer-table'); - let resizeColumnIndex = this.domHandler.index(column); - - this.resizeColGroup(scrollableHeaderTable, resizeColumnIndex, newColumnWidth, nextColumnWidth); - this.resizeColGroup(scrollableBodyTable, resizeColumnIndex, newColumnWidth, nextColumnWidth); - this.resizeColGroup(scrollableFooterTable, resizeColumnIndex, newColumnWidth, nextColumnWidth); - } - else { - column.style.width = newColumnWidth + 'px'; - if (nextColumn) { - nextColumn.style.width = nextColumnWidth + 'px'; - } - } - } - } - } - else if (this.columnResizeMode === 'expand') { - if (this.scrollable) { - let scrollableBodyTable = this.domHandler.findSingle(this.el.nativeElement, 'table.ui-table-scrollable-body-table'); - let scrollableHeaderTable = this.domHandler.findSingle(this.el.nativeElement, 'table.ui-table-scrollable-header-table'); - let scrollableFooterTable = this.domHandler.findSingle(this.el.nativeElement, 'table.ui-table-scrollable-footer-table'); - scrollableBodyTable.style.width = scrollableBodyTable.offsetWidth + delta + 'px'; - scrollableHeaderTable.style.width = scrollableHeaderTable.offsetWidth + delta + 'px'; - if(scrollableFooterTable) { - scrollableFooterTable.style.width = scrollableHeaderTable.offsetWidth + delta + 'px'; - } - let resizeColumnIndex = this.domHandler.index(column); - - this.resizeColGroup(scrollableHeaderTable, resizeColumnIndex, newColumnWidth, null); - this.resizeColGroup(scrollableBodyTable, resizeColumnIndex, newColumnWidth, null); - this.resizeColGroup(scrollableFooterTable, resizeColumnIndex, newColumnWidth, null); - } - else { - this.tableViewChild.nativeElement.style.width = this.tableViewChild.nativeElement.offsetWidth + delta + 'px'; - column.style.width = newColumnWidth + 'px'; - let containerWidth = this.tableViewChild.nativeElement.style.width; - this.containerViewChild.nativeElement.style.width = containerWidth + 'px'; - } - } - - this.onColResize.emit({ - element: column, - delta: delta - }); - } - - this.resizeHelperViewChild.nativeElement.style.display = 'none'; - this.domHandler.removeClass(this.containerViewChild.nativeElement, 'ui-unselectable-text'); - } - - resizeColGroup(table, resizeColumnIndex, newColumnWidth, nextColumnWidth) { - if(table) { - let colGroup = table.children[0].nodeName === 'COLGROUP' ? table.children[0] : null; - - if(colGroup) { - let col = colGroup.children[resizeColumnIndex]; - let nextCol = col.nextElementSibling; - col.style.width = newColumnWidth + 'px'; - - if (nextCol && nextColumnWidth) { - nextCol.style.width = nextColumnWidth + 'px'; - } - } - else { - throw "Scrollable tables require a colgroup to support resizable columns"; - } - } - } - - onColumnDragStart(event, columnElement) { - if (this.domHandler.hasClass(event.target, 'ui-column-resizer')) { - event.preventDefault(); - return; - } - - this.reorderIconWidth = this.domHandler.getHiddenElementOuterWidth(this.reorderIndicatorUpViewChild.nativeElement); - this.reorderIconHeight = this.domHandler.getHiddenElementOuterHeight(this.reorderIndicatorDownViewChild.nativeElement); - this.draggedColumn = columnElement; - event.dataTransfer.setData('text', 'b'); // For firefox - } - - onColumnDragEnter(event, dropHeader) { - if (this.reorderableColumns && this.draggedColumn && dropHeader) { - event.preventDefault(); - let containerOffset = this.domHandler.getOffset(this.containerViewChild.nativeElement); - let dropHeaderOffset = this.domHandler.getOffset(dropHeader); - - if (this.draggedColumn != dropHeader) { - let targetLeft = dropHeaderOffset.left - containerOffset.left; - let targetTop = containerOffset.top - dropHeaderOffset.top; - let columnCenter = dropHeaderOffset.left + dropHeader.offsetWidth / 2; - - this.reorderIndicatorUpViewChild.nativeElement.style.top = dropHeaderOffset.top - containerOffset.top - (this.reorderIconHeight - 1) + 'px'; - this.reorderIndicatorDownViewChild.nativeElement.style.top = dropHeaderOffset.top - containerOffset.top + dropHeader.offsetHeight + 'px'; - - if (event.pageX > columnCenter) { - this.reorderIndicatorUpViewChild.nativeElement.style.left = (targetLeft + dropHeader.offsetWidth - Math.ceil(this.reorderIconWidth / 2)) + 'px'; - this.reorderIndicatorDownViewChild.nativeElement.style.left = (targetLeft + dropHeader.offsetWidth - Math.ceil(this.reorderIconWidth / 2)) + 'px'; - this.dropPosition = 1; - } - else { - this.reorderIndicatorUpViewChild.nativeElement.style.left = (targetLeft - Math.ceil(this.reorderIconWidth / 2)) + 'px'; - this.reorderIndicatorDownViewChild.nativeElement.style.left = (targetLeft - Math.ceil(this.reorderIconWidth / 2)) + 'px'; - this.dropPosition = -1; - } - - this.reorderIndicatorUpViewChild.nativeElement.style.display = 'block'; - this.reorderIndicatorDownViewChild.nativeElement.style.display = 'block'; - } - else { - event.dataTransfer.dropEffect = 'none'; - } - } - } - - onColumnDragLeave(event) { - if (this.reorderableColumns && this.draggedColumn) { - event.preventDefault(); - this.reorderIndicatorUpViewChild.nativeElement.style.display = 'none'; - this.reorderIndicatorDownViewChild.nativeElement.style.display = 'none'; - } - } - - onColumnDrop(event, dropColumn) { - event.preventDefault(); - if (this.draggedColumn) { - let dragIndex = this.domHandler.indexWithinGroup(this.draggedColumn, 'preorderablecolumn'); - let dropIndex = this.domHandler.indexWithinGroup(dropColumn, 'preorderablecolumn'); - let allowDrop = (dragIndex != dropIndex); - if (allowDrop && ((dropIndex - dragIndex == 1 && this.dropPosition === -1) || (dragIndex - dropIndex == 1 && this.dropPosition === 1))) { - allowDrop = false; - } - - if (allowDrop) { - this.objectUtils.reorderArray(this.columns, dragIndex, dropIndex); - - this.onColReorder.emit({ - dragIndex: dragIndex, - dropIndex: dropIndex, - columns: this.columns - }); - } - - this.reorderIndicatorUpViewChild.nativeElement.style.display = 'none'; - this.reorderIndicatorDownViewChild.nativeElement.style.display = 'none'; - this.draggedColumn.draggable = false; - this.draggedColumn = null; - this.dropPosition = null; - } - } - - onRowDragStart(event, index) { - this.rowDragging = true; - this.draggedRowIndex = index; - event.dataTransfer.setData('text', 'b'); // For firefox - } - - onRowDragOver(event, index, rowElement) { - if (this.rowDragging && this.draggedRowIndex !== index) { - let rowY = this.domHandler.getOffset(rowElement).top + this.domHandler.getWindowScrollTop(); - let pageY = event.pageY; - let rowMidY = rowY + this.domHandler.getOuterHeight(rowElement) / 2; - let prevRowElement = rowElement.previousElementSibling; - - if (pageY < rowMidY) { - this.domHandler.removeClass(rowElement, 'ui-table-dragpoint-bottom'); - - this.droppedRowIndex = index; - if (prevRowElement) - this.domHandler.addClass(prevRowElement, 'ui-table-dragpoint-bottom'); - else - this.domHandler.addClass(rowElement, 'ui-table-dragpoint-top'); - } - else { - if (prevRowElement) - this.domHandler.removeClass(prevRowElement, 'ui-table-dragpoint-bottom'); - else - this.domHandler.addClass(rowElement, 'ui-table-dragpoint-top'); - - this.droppedRowIndex = index + 1; - this.domHandler.addClass(rowElement, 'ui-table-dragpoint-bottom'); - } - } - } - - onRowDragLeave(event, rowElement) { - let prevRowElement = rowElement.previousElementSibling; - if (prevRowElement) { - this.domHandler.removeClass(prevRowElement, 'ui-table-dragpoint-bottom'); - } - - this.domHandler.removeClass(rowElement, 'ui-table-dragpoint-bottom'); - this.domHandler.removeClass(rowElement, 'ui-table-dragpoint-top'); - } - - onRowDragEnd(event) { - this.rowDragging = false; - this.draggedRowIndex = null; - this.droppedRowIndex = null; - } - - onRowDrop(event, rowElement) { - if (this.droppedRowIndex != null) { - let dropIndex = (this.draggedRowIndex > this.droppedRowIndex) ? this.droppedRowIndex : (this.droppedRowIndex === 0) ? 0 : this.droppedRowIndex - 1; - this.objectUtils.reorderArray(this.value, this.draggedRowIndex, dropIndex); - - this.onRowReorder.emit({ - dragIndex: this.draggedRowIndex, - dropIndex: this.droppedRowIndex - }); - } - - //cleanup - this.onRowDragLeave(event, rowElement); - this.onRowDragEnd(event); - } - - handleVirtualScroll(event) { - this.first = (event.page - 1) * this.rows; - this.virtualScrollCallback = event.callback; - - this.zone.run(() => { - if(this.virtualScrollTimer) { - clearTimeout(this.virtualScrollTimer); - } - - this.virtualScrollTimer = setTimeout(() => { - this.onLazyLoad.emit(this.createLazyLoadMetadata()); - }, this.virtualScrollDelay); - }); - } - - isEmpty() { - let data = this.filteredValue||this.value; - return data == null || data.length == 0; - } - - ngOnDestroy() { - this.editingCell = null; - this.initialized = null; - } -} - -@Component({ - selector: '[pTableBody]', - template: ` - - - - - - - - - - - - - - - - - - - - ` -}) -export class TableBody { - - @Input("pTableBody") columns: Column[]; - - @Input("pTableBodyTemplate") template: TemplateRef; - - constructor(public dt: Table) {} -} - -@Component({ - selector: '[pScrollableView]', - template: ` -
-
- - - - - - - - - - -
-
-
-
- - - -
-
-
- - ` -}) -export class ScrollableView implements AfterViewInit,OnDestroy { - - @Input("pScrollableView") columns: Column[]; - - @Input() frozen: boolean; - - @ViewChild('scrollHeader') scrollHeaderViewChild: ElementRef; - - @ViewChild('scrollHeaderBox') scrollHeaderBoxViewChild: ElementRef; - - @ViewChild('scrollBody') scrollBodyViewChild: ElementRef; - - @ViewChild('scrollTable') scrollTableViewChild: ElementRef; - - @ViewChild('scrollFooter') scrollFooterViewChild: ElementRef; - - @ViewChild('scrollFooterBox') scrollFooterBoxViewChild: ElementRef; - - @ViewChild('virtualScroller') virtualScrollerViewChild: ElementRef; - - headerScrollListener: Function; - - bodyScrollListener: Function; - - footerScrollListener: Function; - - frozenSiblingBody: Element; - - _scrollHeight: string; - - subscription: Subscription; - - constructor(public dt: Table, public el: ElementRef, public domHandler: DomHandler, public zone: NgZone) { - this.subscription = this.dt.tableService.valueSource$.subscribe(() => { - this.zone.runOutsideAngular(() => { - setTimeout(() => { - this.alignScrollBar(); - }, 50); - }); - }); - } - - @Input() get scrollHeight(): string { - return this._scrollHeight; - } - set scrollHeight(val: string) { - this._scrollHeight = val; - this.setScrollHeight(); - } - - ngAfterViewInit() { - this.bindEvents(); - this.setScrollHeight(); - this.alignScrollBar(); - - if(!this.frozen) { - if (this.dt.frozenColumns || this.dt.frozenBodyTemplate) { - this.domHandler.addClass(this.el.nativeElement, 'ui-table-unfrozen-view'); - } - - if(this.dt.frozenWidth) { - this.el.nativeElement.style.left = this.dt.frozenWidth; - this.el.nativeElement.style.width = 'calc(100% - ' + this.dt.frozenWidth + ')'; - } - - let frozenView = this.el.nativeElement.previousElementSibling; - if (frozenView) { - this.frozenSiblingBody = this.domHandler.findSingle(frozenView, '.ui-table-scrollable-body'); - } - } - else { - this.scrollBodyViewChild.nativeElement.style.paddingBottom = this.domHandler.calculateScrollbarWidth() + 'px'; - } - - if(this.dt.virtualScroll) { - this.virtualScrollerViewChild.nativeElement.style.height = this.dt.totalRecords * this.dt.virtualRowHeight + 'px'; - } - } - - bindEvents() { - this.zone.runOutsideAngular(() => { - let scrollBarWidth = this.domHandler.calculateScrollbarWidth(); - - if (this.scrollHeaderViewChild && this.scrollHeaderViewChild.nativeElement) { - this.headerScrollListener = this.onHeaderScroll.bind(this); - this.scrollHeaderBoxViewChild.nativeElement.addEventListener('scroll', this.headerScrollListener); - } - - if (this.scrollFooterViewChild && this.scrollFooterViewChild.nativeElement) { - this.footerScrollListener = this.onFooterScroll.bind(this); - this.scrollFooterViewChild.nativeElement.addEventListener('scroll', this.footerScrollListener); - } - - if(!this.frozen) { - this.bodyScrollListener = this.onBodyScroll.bind(this); - this.scrollBodyViewChild.nativeElement.addEventListener('scroll', this.bodyScrollListener); - } - }); - } - - unbindEvents() { - if (this.scrollHeaderViewChild && this.scrollHeaderViewChild.nativeElement) { - this.scrollHeaderBoxViewChild.nativeElement.removeEventListener('scroll', this.headerScrollListener); - } - - if (this.scrollFooterViewChild && this.scrollFooterViewChild.nativeElement) { - this.scrollFooterViewChild.nativeElement.removeEventListener('scroll', this.footerScrollListener); - } - - this.scrollBodyViewChild.nativeElement.addEventListener('scroll', this.bodyScrollListener); - } - - onHeaderScroll(event) { - this.scrollHeaderViewChild.nativeElement.scrollLeft = 0; - } - - onFooterScroll(event) { - this.scrollFooterViewChild.nativeElement.scrollLeft = 0; - } - - onBodyScroll(event) { - if (this.scrollHeaderViewChild && this.scrollHeaderViewChild.nativeElement) { - this.scrollHeaderBoxViewChild.nativeElement.style.marginLeft = -1 * this.scrollBodyViewChild.nativeElement.scrollLeft + 'px'; - } - - if (this.scrollFooterViewChild && this.scrollFooterViewChild.nativeElement) { - this.scrollFooterBoxViewChild.nativeElement.style.marginLeft = -1 * this.scrollBodyViewChild.nativeElement.scrollLeft + 'px'; - } - - if (this.frozenSiblingBody) { - this.frozenSiblingBody.scrollTop = this.scrollBodyViewChild.nativeElement.scrollTop; - } - - if(this.dt.virtualScroll) { - let viewport = this.domHandler.getOuterHeight(this.scrollBodyViewChild.nativeElement); - let tableHeight = this.domHandler.getOuterHeight(this.scrollTableViewChild.nativeElement); - let pageHeight = 28 * this.dt.rows; - let virtualTableHeight = this.domHandler.getOuterHeight(this.virtualScrollerViewChild.nativeElement); - let pageCount = (virtualTableHeight / pageHeight)||1; - let scrollBodyTop = this.scrollTableViewChild.nativeElement.style.top||'0'; - - if((this.scrollBodyViewChild.nativeElement.scrollTop + viewport > parseFloat(scrollBodyTop) + tableHeight) || (this.scrollBodyViewChild.nativeElement.scrollTop < parseFloat(scrollBodyTop))) { - let page = Math.floor((this.scrollBodyViewChild.nativeElement.scrollTop * pageCount) / (this.scrollBodyViewChild.nativeElement.scrollHeight)) + 1; - this.dt.handleVirtualScroll({ - page: page, - callback: () => { - this.scrollTableViewChild.nativeElement.style.top = ((page - 1) * pageHeight) + 'px'; - - if (this.frozenSiblingBody) { - ( this.frozenSiblingBody.children[0]).style.top = this.scrollTableViewChild.nativeElement.style.top; - } - } - }); - } - } - } - - setScrollHeight() { - if(this.scrollHeight && this.scrollBodyViewChild && this.scrollBodyViewChild.nativeElement) { - if(this.scrollHeight.indexOf('%') !== -1) { - this.scrollBodyViewChild.nativeElement.style.visibility = 'hidden'; - this.scrollBodyViewChild.nativeElement.style.height = '100px'; //temporary height to calculate static height - let containerHeight = this.domHandler.getOuterHeight(this.dt.el.nativeElement.children[0]); - let relativeHeight = this.domHandler.getOuterHeight(this.dt.el.nativeElement.parentElement) * parseInt(this.scrollHeight) / 100; - let staticHeight = containerHeight - 100; //total height of headers, footers, paginators - let scrollBodyHeight = (relativeHeight - staticHeight); - - this.scrollBodyViewChild.nativeElement.style.height = 'auto'; - this.scrollBodyViewChild.nativeElement.style.maxHeight = scrollBodyHeight + 'px'; - this.scrollBodyViewChild.nativeElement.style.visibility = 'visible'; - } - else { - this.scrollBodyViewChild.nativeElement.style.maxHeight = this.scrollHeight; - } - } - } - - hasVerticalOverflow() { - return this.domHandler.getOuterHeight(this.scrollTableViewChild.nativeElement) > this.domHandler.getOuterHeight(this.scrollBodyViewChild.nativeElement); - } - - alignScrollBar() { - if(!this.frozen) { - let scrollBarWidth = this.hasVerticalOverflow() ? this.domHandler.calculateScrollbarWidth() : 0; - this.scrollHeaderBoxViewChild.nativeElement.style.marginRight = scrollBarWidth + 'px'; - if(this.scrollFooterBoxViewChild && this.scrollFooterBoxViewChild.nativeElement) { - this.scrollFooterBoxViewChild.nativeElement.style.marginRight = scrollBarWidth + 'px'; - } - } - } - - ngOnDestroy() { - this.unbindEvents(); - - this.frozenSiblingBody = null; - - if(this.subscription) { - this.subscription.unsubscribe(); - } - } -} - -@Directive({ - selector: '[pSortableColumn]', - providers: [DomHandler], - host: { - '[class.ui-sortable-column]': 'true', - '[class.ui-state-highlight]': 'sorted' - } -}) -export class SortableColumn implements OnInit, OnDestroy { - - @Input("pSortableColumn") field: string; - - @Input() pSortableColumnDisabled: boolean; - - sorted: boolean; - - subscription: Subscription; - - constructor(public dt: Table, public domHandler: DomHandler) { - if (this.isEnabled()) { - this.subscription = this.dt.tableService.sortSource$.subscribe(sortMeta => { - this.updateSortState(); - }); - } - } - - ngOnInit() { - if (this.isEnabled()) { - this.updateSortState(); - } - } - - updateSortState() { - this.sorted = this.dt.isSorted(this.field); - } - - @HostListener('click', ['$event']) - onClick(event: MouseEvent) { - if (this.isEnabled()) { - this.updateSortState(); - this.dt.sort({ - originalEvent: event, - field: this.field - }); - - this.domHandler.clearSelection(); - } - } - - isEnabled() { - return this.pSortableColumnDisabled !== true; - } - - ngOnDestroy() { - if (this.subscription) { - this.subscription.unsubscribe(); - } - } - -} - - -@Component({ - selector: 'p-sortIcon', - template: ` - - ` -}) -export class SortIcon implements OnInit, OnDestroy { - - @Input() field: string; - - subscription: Subscription; - - sortOrder: number; - - sorted: boolean; - - constructor(public dt: Table) { - this.subscription = this.dt.tableService.sortSource$.subscribe(sortMeta => { - this.updateSortState(); - }); - } - - ngOnInit() { - this.updateSortState(); - } - - updateSortState() { - if (this.dt.sortMode === 'single') { - this.sortOrder = this.dt.isSorted(this.field) ? this.dt.sortOrder : 0; - } - else if (this.dt.sortMode === 'multiple') { - let sortMeta = this.dt.getSortMeta(this.field); - this.sortOrder = sortMeta ? sortMeta.order: 0; - } - } - - ngOnDestroy() { - if (this.subscription) { - this.subscription.unsubscribe(); - } - } -} - -@Directive({ - selector: '[pSelectableRow]', - providers: [DomHandler], - host: { - '[class.ui-state-highlight]': 'selected' - } -}) -export class SelectableRow implements OnInit, OnDestroy { - - @Input("pSelectableRow") data: any; - - @Input("pSelectableRowIndex") index: number; - - @Input() pSelectableRowDisabled: boolean; - - selected: boolean; - - subscription: Subscription; - - constructor(public dt: Table, public domHandler: DomHandler, public tableService: TableService) { - if (this.isEnabled()) { - this.subscription = this.dt.tableService.selectionSource$.subscribe(() => { - this.selected = this.dt.isSelected(this.data); - }); - } - } - - ngOnInit() { - if (this.isEnabled()) { - this.selected = this.dt.isSelected(this.data); - } - } - - @HostListener('click', ['$event']) - onClick(event: Event) { - if (this.isEnabled()) { - this.dt.handleRowClick({ - originalEvent: event, - rowData: this.data, - rowIndex: this.index - }); - } - } - - @HostListener('touchend', ['$event']) - onTouchEnd(event: Event) { - if (this.isEnabled()) { - this.dt.handleRowTouchEnd(event); - } - } - - isEnabled() { - return this.pSelectableRowDisabled !== true; - } - - ngOnDestroy() { - if (this.subscription) { - this.subscription.unsubscribe(); - } - } - -} - -@Directive({ - selector: '[pSelectableRowDblClick]', - providers: [DomHandler], - host: { - '[class.ui-state-highlight]': 'selected' - } -}) -export class SelectableRowDblClick implements OnInit, OnDestroy { - - @Input("pSelectableRowDblClick") data: any; - - @Input("pSelectableRowIndex") index: number; - - @Input() pSelectableRowDisabled: boolean; - - selected: boolean; - - subscription: Subscription; - - constructor(public dt: Table, public domHandler: DomHandler, public tableService: TableService) { - if (this.isEnabled()) { - this.subscription = this.dt.tableService.selectionSource$.subscribe(() => { - this.selected = this.dt.isSelected(this.data); - }); - } - } - - ngOnInit() { - if (this.isEnabled()) { - this.selected = this.dt.isSelected(this.data); - } - } - - @HostListener('dblclick', ['$event']) - onClick(event: Event) { - if (this.isEnabled()) { - this.dt.handleRowClick({ - originalEvent: event, - rowData: this.data, - rowIndex: this.index - }); - } - } - - isEnabled() { - return this.pSelectableRowDisabled !== true; - } - - ngOnDestroy() { - if (this.subscription) { - this.subscription.unsubscribe(); - } - } - -} - -@Directive({ - selector: '[pContextMenuRow]', - host: { - '[class.ui-contextmenu-selected]': 'selected' - } -}) -export class ContextMenuRow { - - @Input("pContextMenuRow") data: any; - - @Input() pContextMenuRowDisabled: boolean; - - selected: boolean; - - subscription: Subscription; - - constructor(public dt: Table, public tableService: TableService) { - if (this.isEnabled()) { - this.subscription = this.dt.tableService.contextMenuSource$.subscribe((data) => { - this.selected = this.dt.equals(this.data, data); - }); - } - } - - @HostListener('contextmenu', ['$event']) - onContextMenu(event: Event) { - if (this.isEnabled()) { - this.dt.handleRowRightClick({ - originalEvent: event, - rowData: this.data - }); - - event.preventDefault(); - } - } - - isEnabled() { - return this.pContextMenuRowDisabled !== true; - } - - ngOnDestroy() { - if (this.subscription) { - this.subscription.unsubscribe(); - } - } - -} - -@Directive({ - selector: '[pRowToggler]' -}) -export class RowToggler { - - @Input('pRowToggler') data: any; - - @Input() pRowTogglerDisabled: boolean; - - constructor(public dt: Table) { } - - @HostListener('click', ['$event']) - onClick(event: Event) { - if (this.isEnabled()) { - this.dt.toggleRow(this.data, event); - event.preventDefault(); - } - } - - isEnabled() { - return this.pRowTogglerDisabled !== true; - } -} - -@Directive({ - selector: '[pResizableColumn]' -}) -export class ResizableColumn implements AfterViewInit, OnDestroy { - - @Input() pResizableColumnDisabled: boolean; - - resizer: HTMLSpanElement; - - resizerMouseDownListener: any; - - documentMouseMoveListener: any; - - documentMouseUpListener: any; - - constructor(public dt: Table, public el: ElementRef, public domHandler: DomHandler, public zone: NgZone) { } - - ngAfterViewInit() { - if (this.isEnabled()) { - this.domHandler.addClass(this.el.nativeElement, 'ui-resizable-column'); - this.resizer = document.createElement('span'); - this.resizer.className = 'ui-column-resizer ui-clickable'; - this.el.nativeElement.appendChild(this.resizer); - - this.zone.runOutsideAngular(() => { - this.resizerMouseDownListener = this.onMouseDown.bind(this); - this.resizer.addEventListener('mousedown', this.resizerMouseDownListener); - }); - } - } - - bindDocumentEvents() { - this.zone.runOutsideAngular(() => { - this.documentMouseMoveListener = this.onDocumentMouseMove.bind(this); - document.addEventListener('mousemove', this.documentMouseMoveListener); - - this.documentMouseUpListener = this.onDocumentMouseUp.bind(this); - document.addEventListener('mouseup', this.documentMouseUpListener); - }); - } - - unbindDocumentEvents() { - if (this.documentMouseMoveListener) { - document.removeEventListener('mousemove', this.documentMouseMoveListener); - this.documentMouseMoveListener = null; - } - - if (this.documentMouseUpListener) { - document.removeEventListener('mouseup', this.documentMouseUpListener); - this.documentMouseUpListener = null; - } - } - - onMouseDown(event: Event) { - this.dt.onColumnResizeBegin(event); - this.bindDocumentEvents(); - } - - onDocumentMouseMove(event: Event) { - this.dt.onColumnResize(event); - } - - onDocumentMouseUp(event: Event) { - this.dt.onColumnResizeEnd(event, this.el.nativeElement); - this.unbindDocumentEvents(); - } - - isEnabled() { - return this.pResizableColumnDisabled !== true; - } - - ngOnDestroy() { - if (this.resizerMouseDownListener) { - this.resizer.removeEventListener('mousedown', this.resizerMouseDownListener); - } - - this.unbindDocumentEvents(); - } -} - -@Directive({ - selector: '[pReorderableColumn]' -}) -export class ReorderableColumn implements AfterViewInit, OnDestroy { - - @Input() pReorderableColumnDisabled: boolean; - - dragStartListener: any; - - dragOverListener: any; - - dragEnterListener: any; - - dragLeaveListener: any; - - mouseDownListener: any; - - constructor(public dt: Table, public el: ElementRef, public domHandler: DomHandler, public zone: NgZone) { } - - ngAfterViewInit() { - if (this.isEnabled()) { - this.bindEvents(); - } - } - - bindEvents() { - this.zone.runOutsideAngular(() => { - this.mouseDownListener = this.onMouseDown.bind(this); - this.el.nativeElement.addEventListener('mousedown', this.mouseDownListener); - - this.dragStartListener = this.onDragStart.bind(this); - this.el.nativeElement.addEventListener('dragstart', this.dragStartListener); - - this.dragOverListener = this.onDragEnter.bind(this); - this.el.nativeElement.addEventListener('dragover', this.dragOverListener); - - this.dragEnterListener = this.onDragEnter.bind(this); - this.el.nativeElement.addEventListener('dragenter', this.dragEnterListener); - - this.dragLeaveListener = this.onDragLeave.bind(this); - this.el.nativeElement.addEventListener('dragleave', this.dragLeaveListener); - }); - } - - unbindEvents() { - if (this.mouseDownListener) { - document.removeEventListener('mousedown', this.mouseDownListener); - this.mouseDownListener = null; - } - - if (this.dragOverListener) { - document.removeEventListener('dragover', this.dragOverListener); - this.dragOverListener = null; - } - - if (this.dragEnterListener) { - document.removeEventListener('dragenter', this.dragEnterListener); - this.dragEnterListener = null; - } - - if (this.dragEnterListener) { - document.removeEventListener('dragenter', this.dragEnterListener); - this.dragEnterListener = null; - } - - if (this.dragLeaveListener) { - document.removeEventListener('dragleave', this.dragLeaveListener); - this.dragLeaveListener = null; - } - } - - onMouseDown(event) { - if (event.target.nodeName === 'INPUT') - this.el.nativeElement.draggable = false; - else - this.el.nativeElement.draggable = true; - } - - onDragStart(event) { - this.dt.onColumnDragStart(event, this.el.nativeElement); - } - - onDragOver(event) { - event.preventDefault(); - } - - onDragEnter(event) { - this.dt.onColumnDragEnter(event, this.el.nativeElement); - } - - onDragLeave(event) { - this.dt.onColumnDragLeave(event); - } - - @HostListener('drop', ['$event']) - onDrop(event) { - if (this.isEnabled()) { - this.dt.onColumnDrop(event, this.el.nativeElement); - } - } - - isEnabled() { - return this.pReorderableColumnDisabled !== true; - } - - ngOnDestroy() { - this.unbindEvents(); - } - -} - -@Directive({ - selector: '[pEditableColumn]' -}) -export class EditableColumn implements AfterViewInit { - - @Input("pEditableColumn") data: any; - - @Input("pEditableColumnField") field: any; - - @Input() pEditableColumnDisabled: boolean; - - constructor(public dt: Table, public el: ElementRef, public domHandler: DomHandler, public zone: NgZone) {} - - ngAfterViewInit() { - if (this.isEnabled()) { - this.domHandler.addClass(this.el.nativeElement, 'ui-editable-column'); - } - } - - isValid() { - return (this.dt.editingCell && this.domHandler.find(this.dt.editingCell, '.ng-invalid.ng-dirty').length === 0); - } - - @HostListener('click', ['$event']) - onClick(event: MouseEvent) { - if (this.isEnabled()) { - if (this.dt.editingCell) { - if (this.dt.editingCell !== this.el.nativeElement) { - if (!this.isValid()) { - return; - } - - this.domHandler.removeClass(this.dt.editingCell, 'ui-editing-cell'); - this.openCell(); - } - } - else { - this.openCell(); - } - } - } - - openCell() { - this.dt.editingCell = this.el.nativeElement; - this.domHandler.addClass(this.el.nativeElement, 'ui-editing-cell'); - this.dt.onEditInit.emit({ field: this.field, data: this.data}); - this.zone.runOutsideAngular(() => { - setTimeout(() => { - let focusable = this.domHandler.findSingle(this.el.nativeElement, 'input, textarea'); - if (focusable) { - focusable.focus(); - } - }, 50); - }); - } - - @HostListener('keydown', ['$event']) - onKeyDown(event: KeyboardEvent) { - if (this.isEnabled()) { - //enter - if (event.keyCode == 13) { - if (this.isValid()) { - this.domHandler.removeClass(this.dt.editingCell, 'ui-editing-cell'); - this.dt.editingCell = null; - this.dt.onEditComplete.emit({ field: this.field, data: this.data }); - } - - event.preventDefault(); - } - - //escape - else if (event.keyCode == 27) { - if (this.isValid()) { - this.domHandler.removeClass(this.dt.editingCell, 'ui-editing-cell'); - this.dt.editingCell = null; - this.dt.onEditCancel.emit({ field: this.field, data: this.data }); - } - - event.preventDefault(); - } - - //tab - else if (event.keyCode == 9) { - if (event.shiftKey) - this.moveToPreviousCell(event); - else - this.moveToNextCell(event); - } - } - } - - findCell(element) { - if (element) { - let cell = element; - while (cell && !this.domHandler.hasClass(cell, 'ui-editing-cell')) { - cell = cell.parentElement; - } - - return cell; - } - else { - return null; - } - } - - moveToPreviousCell(event: KeyboardEvent) { - let currentCell = this.findCell(event.target); - let row = currentCell.parentElement; - let targetCell = this.findPreviousEditableColumn(currentCell); - - if (targetCell) { - this.domHandler.invokeElementMethod(targetCell, 'click'); - event.preventDefault(); - } - } - - moveToNextCell(event: KeyboardEvent) { - let currentCell = this.findCell(event.target); - let row = currentCell.parentElement; - let targetCell = this.findNextEditableColumn(currentCell); - - if (targetCell) { - this.domHandler.invokeElementMethod(targetCell, 'click'); - event.preventDefault(); - } - } - - findPreviousEditableColumn(cell: Element) { - let prevCell = cell.previousElementSibling; - - if (!prevCell) { - let previousRow = cell.parentElement.previousElementSibling; - if (previousRow) { - prevCell = previousRow.lastElementChild; - } - } - - if (prevCell) { - if (this.domHandler.hasClass(prevCell, 'ui-editable-column')) - return prevCell; - else - return this.findPreviousEditableColumn(prevCell); - } - else { - return null; - } - } - - findNextEditableColumn(cell: Element) { - let nextCell = cell.nextElementSibling; - - if (!nextCell) { - let nextRow = cell.parentElement.nextElementSibling; - if (nextRow) { - nextCell = nextRow.firstElementChild; - } - } - - if (nextCell) { - if (this.domHandler.hasClass(nextCell, 'ui-editable-column')) - return nextCell; - else - return this.findNextEditableColumn(nextCell); - } - else { - return null; - } - } - - isEnabled() { - return this.pEditableColumnDisabled !== true; - } - -} - -@Component({ - selector: 'p-cellEditor', - template: ` - - - - - - - ` -}) -export class CellEditor implements AfterContentInit { - - @ContentChildren(PrimeTemplate) templates: QueryList; - - inputTemplate: TemplateRef; - - outputTemplate: TemplateRef; - - constructor(public dt: Table, public editableColumn: EditableColumn) { } - - ngAfterContentInit() { - this.templates.forEach((item) => { - switch (item.getType()) { - case 'input': - this.inputTemplate = item.template; - break; - - case 'output': - this.outputTemplate = item.template; - break; - } - }); - } - -} - -@Component({ - selector: 'p-tableRadioButton', - template: ` -
-
- -
-
- -
-
- ` -}) -export class TableRadioButton { - - @Input() disabled: boolean; - - @Input() value: any; - - @ViewChild('box') boxViewChild: ElementRef; - - checked: boolean; - - subscription: Subscription; - - constructor(public dt: Table, public domHandler: DomHandler, public tableService: TableService) { - this.subscription = this.dt.tableService.selectionSource$.subscribe(() => { - this.checked = this.dt.isSelected(this.value); - }); - } - - ngOnInit() { - this.checked = this.dt.isSelected(this.value); - } - - onClick(event: Event) { - this.dt.toggleRowWithRadio(event, this.value); - this.domHandler.clearSelection(); - } - - onFocus() { - this.domHandler.addClass(this.boxViewChild.nativeElement, 'ui-state-focus'); - } - - onBlur() { - this.domHandler.removeClass(this.boxViewChild.nativeElement, 'ui-state-focus'); - } - - ngOnDestroy() { - if (this.subscription) { - this.subscription.unsubscribe(); - } - } - -} - -@Component({ - selector: 'p-tableCheckbox', - template: ` -
-
- -
-
- -
-
- ` -}) -export class TableCheckbox { - - @Input() disabled: boolean; - - @Input() value: any; - - @ViewChild('box') boxViewChild: ElementRef; - - checked: boolean; - - subscription: Subscription; - - constructor(public dt: Table, public domHandler: DomHandler, public tableService: TableService) { - this.subscription = this.dt.tableService.selectionSource$.subscribe(() => { - this.checked = this.dt.isSelected(this.value); - }); - } - - ngOnInit() { - this.checked = this.dt.isSelected(this.value); - } - - onClick(event: Event) { - this.dt.toggleRowWithCheckbox(event, this.value); - this.domHandler.clearSelection(); - } - - onFocus() { - this.domHandler.addClass(this.boxViewChild.nativeElement, 'ui-state-focus'); - } - - onBlur() { - this.domHandler.removeClass(this.boxViewChild.nativeElement, 'ui-state-focus'); - } - - ngOnDestroy() { - if (this.subscription) { - this.subscription.unsubscribe(); - } - } - -} - -@Component({ - selector: 'p-tableHeaderCheckbox', - template: ` -
-
- -
-
- -
-
- ` -}) -export class TableHeaderCheckbox { - - @ViewChild('box') boxViewChild: ElementRef; - - checked: boolean; - - disabled: boolean; - - subscription: Subscription; - - constructor(public dt: Table, public domHandler: DomHandler, public tableService: TableService) { - this.subscription = this.dt.tableService.selectionSource$.subscribe(() => { - this.checked = this.updateCheckedState(); - }); - } - - ngOnInit() { - this.checked = this.updateCheckedState(); - } - - onClick(event: Event, checked) { - if(this.dt.value && this.dt.value.length > 0) { - this.dt.toggleRowsWithCheckbox(event, !checked); - } - - this.domHandler.clearSelection(); - } - - onFocus() { - this.domHandler.addClass(this.boxViewChild.nativeElement, 'ui-state-focus'); - } - - onBlur() { - this.domHandler.removeClass(this.boxViewChild.nativeElement, 'ui-state-focus'); - } - - ngOnDestroy() { - if (this.subscription) { - this.subscription.unsubscribe(); - } - } - - updateCheckedState() { - return (this.dt.value && this.dt.value.length > 0 && this.dt.selection && this.dt.selection.length > 0 && this.dt.selection.length === this.dt.value.length); - } - -} - -@Directive({ - selector: '[pReorderableRowHandle]' -}) -export class ReorderableRowHandle implements AfterViewInit { - - @Input("pReorderableRowHandle") index: number; - - constructor(public el: ElementRef, public domHandler: DomHandler) {} - - ngAfterViewInit() { - this.domHandler.addClass(this.el.nativeElement, 'ui-table-reorderablerow-handle'); - } -} - -@Directive({ - selector: '[pReorderableRow]' -}) -export class ReorderableRow implements AfterViewInit { - - @Input("pReorderableRow") index: number; - - @Input() pReorderableRowDisabled: boolean; - - mouseDownListener: any; - - dragStartListener: any; - - dragEndListener: any; - - dragOverListener: any; - - dragLeaveListener: any; - - dropListener: any; - - constructor(public dt: Table, public el: ElementRef, public domHandler: DomHandler, public zone: NgZone) {} - - ngAfterViewInit() { - if (this.isEnabled()) { - this.el.nativeElement.droppable = true; - this.bindEvents(); - } - } - - bindEvents() { - this.zone.runOutsideAngular(() => { - this.mouseDownListener = this.onMouseDown.bind(this); - this.el.nativeElement.addEventListener('mousedown', this.mouseDownListener); - - this.dragStartListener = this.onDragStart.bind(this); - this.el.nativeElement.addEventListener('dragstart', this.dragStartListener); - - this.dragEndListener = this.onDragEnd.bind(this); - this.el.nativeElement.addEventListener('dragend', this.dragEndListener); - - this.dragOverListener = this.onDragOver.bind(this); - this.el.nativeElement.addEventListener('dragover', this.dragOverListener); - - this.dragLeaveListener = this.onDragLeave.bind(this); - this.el.nativeElement.addEventListener('dragleave', this.dragLeaveListener); - }); - } - - unbindEvents() { - if (this.mouseDownListener) { - document.removeEventListener('mousedown', this.mouseDownListener); - this.mouseDownListener = null; - } - - if (this.dragStartListener) { - document.removeEventListener('dragstart', this.dragStartListener); - this.dragStartListener = null; - } - - if (this.dragEndListener) { - document.removeEventListener('dragend', this.dragEndListener); - this.dragEndListener = null; - } - - if (this.dragOverListener) { - document.removeEventListener('dragover', this.dragOverListener); - this.dragOverListener = null; - } - - if (this.dragLeaveListener) { - document.removeEventListener('dragleave', this.dragLeaveListener); - this.dragLeaveListener = null; - } - } - - onMouseDown(event) { - if (this.domHandler.hasClass(event.target, 'ui-table-reorderablerow-handle')) - this.el.nativeElement.draggable = true; - else - this.el.nativeElement.draggable = false; - } - - onDragStart(event) { - this.dt.onRowDragStart(event, this.index); - } - - onDragEnd(event) { - this.dt.onRowDragEnd(event); - this.el.nativeElement.draggable = false; - } - - onDragOver(event) { - this.dt.onRowDragOver(event, this.index, this.el.nativeElement); - event.preventDefault(); - } - - onDragLeave(event) { - this.dt.onRowDragLeave(event, this.el.nativeElement); - } - - isEnabled() { - return this.pReorderableRowDisabled !== true; - } - - @HostListener('drop', ['$event']) - onDrop(event) { - if (this.isEnabled() && this.dt.rowDragging) { - this.dt.onRowDrop(event, this.el.nativeElement); - } - } -} - -@NgModule({ - imports: [CommonModule,PaginatorModule], - exports: [Table,SharedModule,SortableColumn,SelectableRow,RowToggler,ContextMenuRow,ResizableColumn,ReorderableColumn,EditableColumn,CellEditor,SortIcon,TableRadioButton,TableCheckbox,TableHeaderCheckbox,ReorderableRowHandle,ReorderableRow,SelectableRowDblClick], - declarations: [Table,SortableColumn,SelectableRow,RowToggler,ContextMenuRow,ResizableColumn,ReorderableColumn,EditableColumn,CellEditor,TableBody,ScrollableView,SortIcon,TableRadioButton,TableCheckbox,TableHeaderCheckbox,ReorderableRowHandle,ReorderableRow,SelectableRowDblClick] -}) -export class TableModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/tabmenu/tabmenu.css b/dashboard/src/app/components/tabmenu/tabmenu.css deleted file mode 100644 index 506b2cf24..000000000 --- a/dashboard/src/app/components/tabmenu/tabmenu.css +++ /dev/null @@ -1,35 +0,0 @@ -/** TabMenu **/ -.ui-tabmenu .ui-tabmenu-nav { - margin: 0; - padding: .25em .5em 0 .25em; -} - -.ui-tabmenu .ui-tabmenu-nav .ui-tabmenuitem { - list-style: none; - float: left; - position: relative; - margin: 0 .2em 1px 0; - padding: 0; - white-space: nowrap; - display: block; - border-bottom: 0; - top: 1px; -} - -.ui-tabmenu .ui-tabmenu-nav .ui-tabmenuitem a { - float: left; - padding: 0.5em 1em; - text-decoration: none; -} - -.ui-tabmenu .ui-tabmenu-nav a { - padding: 0.5em 1em; -} - -.ui-tabmenu .ui-tabmenu-nav .ui-tabmenuitem .ui-icon { - float: left; -} - -.ui-tabmenu .ui-tabmenu-nav .ui-tabmenuitem.ui-state-disabled a { - cursor: default; -} \ No newline at end of file diff --git a/dashboard/src/app/components/tabmenu/tabmenu.spec.ts b/dashboard/src/app/components/tabmenu/tabmenu.spec.ts deleted file mode 100644 index 7c15af923..000000000 --- a/dashboard/src/app/components/tabmenu/tabmenu.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { TabMenu } from './tabmenu'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('TabMenu', () => { - - let tabmenu: TabMenu; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - TabMenu - ] - }); - - fixture = TestBed.createComponent(TabMenu); - tabmenu = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/tabmenu/tabmenu.ts b/dashboard/src/app/components/tabmenu/tabmenu.ts deleted file mode 100644 index 7e3ffea6b..000000000 --- a/dashboard/src/app/components/tabmenu/tabmenu.ts +++ /dev/null @@ -1,71 +0,0 @@ -import {NgModule,Component,ElementRef,Input,Output} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; -import {MenuItem} from '../common/menuitem'; -import {Location} from '@angular/common'; -import {RouterModule} from '@angular/router'; - -@Component({ - selector: 'p-tabMenu', - template: ` - - `, - providers: [DomHandler] -}) -export class TabMenu { - - @Input() model: MenuItem[]; - - @Input() activeItem: MenuItem; - - @Input() popup: boolean; - - @Input() style: any; - - @Input() styleClass: string; - - itemClick(event: Event, item: MenuItem) { - if(item.disabled) { - event.preventDefault(); - return; - } - - if(!item.url) { - event.preventDefault(); - } - - if(item.command) { - item.command({ - originalEvent: event, - item: item - }); - } - - this.activeItem = item; - } -} - -@NgModule({ - imports: [CommonModule,RouterModule], - exports: [TabMenu,RouterModule], - declarations: [TabMenu] -}) -export class TabMenuModule { } diff --git a/dashboard/src/app/components/tabview/tabview.scss b/dashboard/src/app/components/tabview/tabview.scss deleted file mode 100644 index 15fff9f80..000000000 --- a/dashboard/src/app/components/tabview/tabview.scss +++ /dev/null @@ -1,143 +0,0 @@ -.ui-tabview { - padding: 0; -} - -.ui-tabview .ui-tabview-nav { - margin: 0; -} - -.ui-tabview .ui-tabview-nav li { - list-style: none; - float: left; - top: 0.01rem; - position: relative; - margin-right: 0.30rem; - padding: 0; - white-space: nowrap; -} - -.ui-tabview .ui-tabview-nav li a { - float: left; - padding: 0 0.05rem; - font-size: 0.16rem; - line-height: 0.20rem; - height: 0.32rem; - text-decoration: none; -} - -.ui-tabview.ui-tabview-large .ui-tabview-nav li a { - padding: 0 0.05rem; - font-size: 0.20rem; - line-height: 0.24rem; - height: 0.40rem; -} - -.ui-tabview .ui-tabview-nav li.ui-tabview-selected a, -.ui-tabview .ui-tabview-nav li.ui-state-disabled a, -.ui-tabview .ui-tabview-nav li.ui-state-processing a { - cursor: text; -} - -.ui-tabview .ui-tabview-nav li a, -.ui-tabview.ui-tabview-collapsible .ui-tabview-nav li.ui-tabview-selected a { - cursor: pointer; -} - -.ui-tabview .ui-tabview-panel { - border-width: 0; - padding: 0.3rem 0; - background: none; -} - -.ui-tabview .ui-tabview-nav li { - display: block; -} - -.ui-tabview .ui-tabview-nav li .ui-tabview-left-icon, -.ui-tabview .ui-tabview-nav li .ui-tabview-right-icon, -.ui-tabview .ui-tabview-nav li .ui-tabview-title { - vertical-align: middle; -} - -.ui-tabview .ui-tabview-nav li .ui-tabview-close { - margin: 0.5em 0.3em 0 0; - cursor: pointer; -} - -/* per orientation settings */ -/* top and bottom */ -.ui-tabview.ui-tabview-top > .ui-tabview-nav li { - border-bottom: 0; -} - -.ui-tabview.ui-tabview-top > .ui-tabview-nav { - padding: 0; - border-bottom: 1px solid $color-splitline; -} - -.ui-tabview.ui-tabview-bottom > .ui-tabview-nav { - padding: 0 .2em .2em; -} - -.ui-tabview.ui-tabview-bottom > .ui-tabview-nav li { - border-top: 0; -} - -/* left and right*/ -.ui-tabview-left::after, -.ui-tabview-right::after { - clear:both; - content: "."; - display: block; - height: 0; - visibility: hidden; -} - -.ui-tabview-left > .ui-tabview-nav { - float:left; - width: 25%; - height: 300px; - background-image: none; - padding-top: 1px; -} - -.ui-tabview-left > .ui-tabview-panels { - float:right; - width: 75%; -} - -.ui-tabview.ui-tabview-left > .ui-tabview-nav li, -.ui-tabview.ui-tabview-right > .ui-tabview-nav li{ - display: block; - float: right; - white-space: normal; - width: 99%; -} - -.ui-tabview.ui-tabview-left > .ui-tabview-nav li { - margin: 0 0 1px 0; - border-right:0 none; -} - -.ui-tabview.ui-tabview-right > .ui-tabview-nav { - float:right; - width: 25%; - height: 300px; - background-image: none; - padding-top: 1px; -} - -.ui-tabview.ui-tabview-right > .ui-tabview-panels { - float:left; - width: 75%; -} - -.ui-tabview.ui-tabview-right > .ui-tabview-nav li { - margin: 0 0 1px 0; - border-left:0 none; -} - -/* RTL */ -.ui-rtl .ui-tabview .ui-tabview-nav li { - float: right; -} diff --git a/dashboard/src/app/components/tabview/tabview.spec.ts b/dashboard/src/app/components/tabview/tabview.spec.ts deleted file mode 100644 index bd6abcfaf..000000000 --- a/dashboard/src/app/components/tabview/tabview.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { TabView } from './tabview'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('TabView', () => { - - let tabview: TabView; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - TabView - ] - }); - - fixture = TestBed.createComponent(TabView); - tabview = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/tabview/tabview.ts b/dashboard/src/app/components/tabview/tabview.ts deleted file mode 100644 index f57ddb1a6..000000000 --- a/dashboard/src/app/components/tabview/tabview.ts +++ /dev/null @@ -1,310 +0,0 @@ -import {NgModule,Component,ElementRef,OnDestroy,Input,Output,EventEmitter,HostListener,AfterContentInit, - ContentChildren,ContentChild,QueryList,TemplateRef,EmbeddedViewRef,ViewContainerRef} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {SharedModule,PrimeTemplate} from '../common/shared'; -import {BlockableUI} from '../common/blockableui'; - -let idx: number = 0; - -@Component({ - selector: '[p-tabViewNav]', - host:{ - '[class.ui-tabview-nav]': 'true', - '[class.ui-helper-reset]': 'true', - '[class.ui-helper-clearfix]': 'true', - '[class.ui-widget-header]': 'true', - '[class.ui-corner-all]': 'true' - }, - template: ` - -
  • - - - {{tab.header}} - - - -
  • -
    - `, -}) -export class TabViewNav { - - @Input() tabs: TabPanel[]; - - @Input() orientation: string = 'top'; - - @Output() onTabClick: EventEmitter = new EventEmitter(); - - @Output() onTabCloseClick: EventEmitter = new EventEmitter(); - - getDefaultHeaderClass(tab:TabPanel) { - let styleClass = 'ui-state-default ui-corner-' + this.orientation; - if(tab.headerStyleClass) { - styleClass = styleClass + " " + tab.headerStyleClass; - } - return styleClass; - } - - clickTab(event, tab: TabPanel) { - this.onTabClick.emit({ - originalEvent: event, - tab: tab - }) - } - - clickClose(event, tab: TabPanel) { - this.onTabCloseClick.emit({ - originalEvent: event, - tab: tab - }) - } -} - -@Component({ - selector: 'p-tabPanel', - template: ` -
    - - - - -
    - ` -}) -export class TabPanel implements AfterContentInit,OnDestroy { - - @Input() header: string; - - @Input() disabled: boolean; - - @Input() closable: boolean; - - @Input() headerStyle: any; - - @Input() headerStyleClass: string; - - @Input() leftIcon: string; - - @Input() rightIcon: string; - - @Input() cache: boolean = true; - - @ContentChildren(PrimeTemplate) templates: QueryList; - - constructor(public viewContainer: ViewContainerRef) {} - - closed: boolean; - - view: EmbeddedViewRef; - - _selected: boolean; - - loaded: boolean; - - id: string = `ui-tabpanel-${idx++}`; - - contentTemplate: TemplateRef; - - ngAfterContentInit() { - this.templates.forEach((item) => { - switch(item.getType()) { - case 'content': - this.contentTemplate = item.template; - break; - - default: - this.contentTemplate = item.template; - break; - } - }); - } - - @Input() get selected(): boolean { - return this._selected; - } - - set selected(val: boolean) { - this._selected = val; - this.loaded = true; - } - - ngOnDestroy() { - this.view = null; - } -} - -@Component({ - selector: 'p-tabView', - template: ` -
    -
      -
      - -
      -
        -
        - `, -}) -export class TabView implements AfterContentInit,BlockableUI { - - @Input() orientation: string = 'top'; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() controlClose: boolean; - - @ContentChildren(TabPanel) tabPanels: QueryList; - - @Output() onChange: EventEmitter = new EventEmitter(); - - @Output() onClose: EventEmitter = new EventEmitter(); - - initialized: boolean; - - tabs: TabPanel[]; - - _activeIndex: number; - - _lazy: boolean; - - constructor(public el: ElementRef) {} - - @Input() get lazy(): boolean { - return this._lazy; - } - - set lazy(val: boolean) { - this._lazy = val; - console.log('Lazy property of TabView is deprecated, use an ngTemplate inside a TabPanel instead for Lazy Loading'); - } - - ngAfterContentInit() { - this.initTabs(); - - this.tabPanels.changes.subscribe(_ => { - this.initTabs(); - }); - } - - initTabs(): void { - this.tabs = this.tabPanels.toArray(); - let selectedTab: TabPanel = this.findSelectedTab(); - if(!selectedTab && this.tabs.length) { - if(this.activeIndex != null && this.tabs.length > this.activeIndex) - this.tabs[this.activeIndex].selected = true; - else - this.tabs[0].selected = true; - } - } - - open(event: Event, tab: TabPanel) { - if(tab.disabled) { - if(event) { - event.preventDefault(); - } - return; - } - - if(!tab.selected) { - let selectedTab: TabPanel = this.findSelectedTab(); - if(selectedTab) { - selectedTab.selected = false - } - tab.selected = true; - this.onChange.emit({originalEvent: event, index: this.findTabIndex(tab)}); - } - - if(event) { - event.preventDefault(); - } - } - - close(event: Event, tab: TabPanel) { - if(this.controlClose) { - this.onClose.emit({ - originalEvent: event, - index: this.findTabIndex(tab), - close: () => { - this.closeTab(tab); - }} - ); - } - else { - this.closeTab(tab); - this.onClose.emit({ - originalEvent: event, - index: this.findTabIndex(tab) - }); - } - - event.stopPropagation(); - } - - closeTab(tab: TabPanel) { - if(tab.selected) { - tab.selected = false; - for(let i = 0; i < this.tabs.length; i++) { - let tabPanel = this.tabs[i]; - if(!tabPanel.closed&&!tab.disabled) { - tabPanel.selected = true; - break; - } - } - } - - tab.closed = true; - } - - findSelectedTab() { - for(let i = 0; i < this.tabs.length; i++) { - if(this.tabs[i].selected) { - return this.tabs[i]; - } - } - return null; - } - - findTabIndex(tab: TabPanel) { - let index = -1; - for(let i = 0; i < this.tabs.length; i++) { - if(this.tabs[i] == tab) { - index = i; - break; - } - } - return index; - } - - getBlockableElement(): HTMLElement { - return this.el.nativeElement.children[0]; - } - - @Input() get activeIndex(): number { - return this._activeIndex; - } - - set activeIndex(val:number) { - this._activeIndex = val; - - if(this.tabs && this.tabs.length && this._activeIndex != null && this.tabs.length > this._activeIndex) { - this.findSelectedTab().selected = false; - this.tabs[this._activeIndex].selected = true; - } - } -} - - -@NgModule({ - imports: [CommonModule,SharedModule], - exports: [TabView,TabPanel,TabViewNav,SharedModule], - declarations: [TabView,TabPanel,TabViewNav] -}) -export class TabViewModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/terminal/terminal.css b/dashboard/src/app/components/terminal/terminal.css deleted file mode 100644 index 86fe6028e..000000000 --- a/dashboard/src/app/components/terminal/terminal.css +++ /dev/null @@ -1,25 +0,0 @@ -.ui-terminal { - height: 18em; - overflow: auto; - padding: .25em; -} - -.ui-terminal-input { - border: 0 none; - background-color: transparent; - color: inherit; - padding: 0; - margin: 0 0 0 .125em; - width: 75%; - outline: none; - vertical-align: baseline; -} - -.ui-terminal-command { - margin-left: .125em; - -moz-margin-start: .125em; -} - -.ui-terminal-input::-ms-clear { - display: none; -} \ No newline at end of file diff --git a/dashboard/src/app/components/terminal/terminal.spec.ts b/dashboard/src/app/components/terminal/terminal.spec.ts deleted file mode 100644 index 0d12d090b..000000000 --- a/dashboard/src/app/components/terminal/terminal.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Terminal } from './terminal'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Terminal', () => { - - let terminal: Terminal; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Terminal - ] - }); - - fixture = TestBed.createComponent(Terminal); - terminal = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/terminal/terminal.ts b/dashboard/src/app/components/terminal/terminal.ts deleted file mode 100644 index 7257379e5..000000000 --- a/dashboard/src/app/components/terminal/terminal.ts +++ /dev/null @@ -1,99 +0,0 @@ -import {NgModule,Component,AfterViewInit,AfterViewChecked,OnDestroy,Input,Output,EventEmitter,ElementRef} from '@angular/core'; -import {FormsModule} from '@angular/forms'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; -import {TerminalService} from './terminalservice'; -import {Subscription} from 'rxjs/Subscription'; - -@Component({ - selector: 'p-terminal', - template: ` -
        -
        {{welcomeMessage}}
        -
        -
        - {{prompt}} - {{command.text}} -
        {{command.response}}
        -
        -
        -
        - {{prompt}} - -
        -
        - `, - providers: [DomHandler] -}) -export class Terminal implements AfterViewInit,AfterViewChecked,OnDestroy { - - @Input() welcomeMessage: string; - - @Input() prompt: string; - - @Input() style: any; - - @Input() styleClass: string; - - commands: any[] = []; - - command: string; - - container: Element; - - commandProcessed: boolean; - - subscription: Subscription; - - constructor(public el: ElementRef, public domHandler: DomHandler, public terminalService: TerminalService) { - this.subscription = terminalService.responseHandler.subscribe(response => { - this.commands[this.commands.length - 1].response = response; - this.commandProcessed = true; - }); - } - - ngAfterViewInit() { - this.container = this.domHandler.find(this.el.nativeElement, '.ui-terminal')[0]; - } - - ngAfterViewChecked() { - if(this.commandProcessed) { - this.container.scrollTop = this.container.scrollHeight; - this.commandProcessed = false; - } - } - - @Input() - set response(value: string) { - if(value) { - this.commands[this.commands.length - 1].response = value; - this.commandProcessed = true; - } - } - - handleCommand(event: KeyboardEvent) { - if(event.keyCode == 13) { - this.commands.push({text: this.command}); - this.terminalService.sendCommand(this.command); - this.command = ''; - } - } - - focus(element: HTMLElement) { - element.focus(); - } - - ngOnDestroy() { - if(this.subscription) { - this.subscription.unsubscribe(); - } - } - -} - -@NgModule({ - imports: [CommonModule,FormsModule], - exports: [Terminal], - declarations: [Terminal] -}) -export class TerminalModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/terminal/terminalservice.ts b/dashboard/src/app/components/terminal/terminalservice.ts deleted file mode 100644 index 3bebf10b3..000000000 --- a/dashboard/src/app/components/terminal/terminalservice.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Subject } from 'rxjs/Subject'; -import { Observable } from 'rxjs/Observable'; - -@Injectable() -export class TerminalService { - - private commandSource = new Subject(); - private responseSource = new Subject(); - - commandHandler = this.commandSource.asObservable(); - responseHandler = this.responseSource.asObservable(); - - sendCommand(command: string) { - if(command) { - this.commandSource.next(command); - } - } - - sendResponse(response: string) { - if(response) { - this.responseSource.next(response); - } - } -} \ No newline at end of file diff --git a/dashboard/src/app/components/tieredmenu/tieredmenu.css b/dashboard/src/app/components/tieredmenu/tieredmenu.css deleted file mode 100644 index 072178ed6..000000000 --- a/dashboard/src/app/components/tieredmenu/tieredmenu.css +++ /dev/null @@ -1,49 +0,0 @@ -.ui-tieredmenu { - width: 12.5em; - padding: .25em; -} - -.ui-tieredmenu.ui-tieredmenu-dynamic { - position: absolute; - display: none; -} - -.ui-tieredmenu .ui-menu-separator { - border-width: 1px 0 0 0; -} - -.ui-tieredmenu ul { - list-style: none; - margin: 0; - padding: 0; -} - -.ui-tieredmenu .ui-submenu-list { - display: none; - position: absolute; - width: 12.5em; - padding: .25em; -} - -.ui-tieredmenu .ui-menuitem-link { - padding: .25em; - display: block; - position: relative; - text-decoration: none; -} - -.ui-tieredmenu .ui-menuitem { - position: relative; - margin: .125em 0; -} - -.ui-tieredmenu .ui-menuitem-link .ui-submenu-icon { - position: absolute; - margin-top: -.5em; - right: 0; - top: 50%; -} - -.ui-tieredmenu .ui-menuitem-active > .ui-submenu > .ui-submenu-list { - display: block; -} \ No newline at end of file diff --git a/dashboard/src/app/components/tieredmenu/tieredmenu.spec.ts b/dashboard/src/app/components/tieredmenu/tieredmenu.spec.ts deleted file mode 100644 index bfe3428b5..000000000 --- a/dashboard/src/app/components/tieredmenu/tieredmenu.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { TieredMenu } from './tieredmenu'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('TieredMenu', () => { - - let tieredmenu: TieredMenu; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - TieredMenu - ] - }); - - fixture = TestBed.createComponent(TieredMenu); - tieredmenu = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/tieredmenu/tieredmenu.ts b/dashboard/src/app/components/tieredmenu/tieredmenu.ts deleted file mode 100644 index 8c33d396a..000000000 --- a/dashboard/src/app/components/tieredmenu/tieredmenu.ts +++ /dev/null @@ -1,217 +0,0 @@ -import {NgModule,Component,ElementRef,AfterViewInit,OnDestroy,Input,Output,Renderer2} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {DomHandler} from '../dom/domhandler'; -import {MenuItem} from '../common/menuitem'; -import {RouterModule} from '@angular/router'; - -@Component({ - selector: 'p-tieredMenuSub', - template: ` - - `, - providers: [DomHandler] -}) -export class TieredMenuSub { - - @Input() item: MenuItem; - - @Input() root: boolean; - - @Input() autoZIndex: boolean = true; - - @Input() baseZIndex: number = 0; - - constructor(public domHandler: DomHandler) {} - - activeItem: HTMLLIElement; - - hideTimeout: any; - - onItemMouseEnter(event: Event, item: HTMLLIElement, menuitem: MenuItem) { - if(menuitem.disabled) { - return; - } - - if(this.hideTimeout) { - clearTimeout(this.hideTimeout); - this.hideTimeout = null; - } - - this.activeItem = item; - let nextElement: HTMLElement = item.children[0].nextElementSibling; - if(nextElement) { - let sublist: HTMLElement = nextElement.children[0]; - if(this.autoZIndex) { - sublist.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex)); - } - sublist.style.zIndex = String(++DomHandler.zindex); - - sublist.style.top = '0px'; - sublist.style.left = this.domHandler.getOuterWidth(item.children[0]) + 'px'; - } - } - - onItemMouseLeave(event: Event) { - this.hideTimeout = setTimeout(() => { - this.activeItem = null; - }, 1000); - } - - itemClick(event: Event, item: MenuItem) { - if(item.disabled) { - event.preventDefault(); - return true; - } - - if(!item.url) { - event.preventDefault(); - } - - if(item.command) { - item.command({ - originalEvent: event, - item: item - }); - } - } - - listClick(event: Event) { - this.activeItem = null; - } -} - -@Component({ - selector: 'p-tieredMenu', - template: ` -
        - -
        - `, - providers: [DomHandler] -}) -export class TieredMenu implements AfterViewInit,OnDestroy { - - @Input() model: MenuItem[]; - - @Input() popup: boolean; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() appendTo: any; - - @Input() autoZIndex: boolean = true; - - @Input() baseZIndex: number = 0; - - container: any; - - documentClickListener: any; - - preventDocumentDefault: any; - - constructor(public el: ElementRef, public domHandler: DomHandler, public renderer: Renderer2) {} - - ngAfterViewInit() { - this.container = this.el.nativeElement.children[0]; - - if(this.popup) { - if(this.appendTo) { - if(this.appendTo === 'body') - document.body.appendChild(this.container); - else - this.domHandler.appendChild(this.container, this.appendTo); - } - } - } - - toggle(event: Event) { - if(this.container.offsetParent) - this.hide(); - else - this.show(event); - } - - show(event: Event) { - this.preventDocumentDefault = true; - this.moveOnTop(); - this.container.style.display = 'block'; - this.domHandler.absolutePosition(this.container, event.currentTarget); - this.domHandler.fadeIn(this.container, 250); - this.bindDocumentClickListener(); - } - - hide() { - this.container.style.display = 'none'; - this.unbindDocumentClickListener(); - } - - moveOnTop() { - if(this.autoZIndex) { - this.container.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex)); - } - } - - unbindDocumentClickListener() { - if(this.documentClickListener) { - this.documentClickListener(); - this.documentClickListener = null; - } - } - - bindDocumentClickListener() { - if(!this.documentClickListener) { - this.documentClickListener = this.renderer.listen('document', 'click', () => { - if(!this.preventDocumentDefault) { - this.hide(); - } - this.preventDocumentDefault = false; - }); - } - } - - ngOnDestroy() { - if(this.popup) { - if(this.documentClickListener) { - this.unbindDocumentClickListener(); - } - if(this.appendTo) { - this.el.nativeElement.appendChild(this.container); - } - } - } - -} - -@NgModule({ - imports: [CommonModule,RouterModule], - exports: [TieredMenu,RouterModule], - declarations: [TieredMenu,TieredMenuSub] -}) -export class TieredMenuModule { } diff --git a/dashboard/src/app/components/togglebutton/togglebutton.spec.ts b/dashboard/src/app/components/togglebutton/togglebutton.spec.ts deleted file mode 100644 index 2824d1407..000000000 --- a/dashboard/src/app/components/togglebutton/togglebutton.spec.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { ToggleButton } from './togglebutton'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('ToggleButton', () => { - let toggleButton: ToggleButton; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - ToggleButton - ] - }); - - fixture = TestBed.createComponent(ToggleButton); - toggleButton = fixture.componentInstance; - }); - - it('should display the OFF label when value is undefined', () => { - toggleButton.offLabel = 'NO'; - fixture.detectChanges(); - const labelEl = fixture.debugElement.query(By.css('.ui-button-text')); - expect(labelEl.nativeElement.textContent).toBe('NO'); - }); - - it('should display the ON label when clicked', () => { - toggleButton.onLabel = 'YES'; - fixture.detectChanges(); - const clickEl = fixture.nativeElement.querySelector('.ui-togglebutton') - clickEl.click(); - fixture.detectChanges(); - - const labelEl = fixture.debugElement.query(By.css('.ui-button-text')); - expect(labelEl.nativeElement.textContent).toBe('YES') - }); - - it('Should display as checked when value is true by default', () => { - toggleButton.checked = true; - fixture.detectChanges(); - expect(toggleButton.checked).toBe(true); - }); -}); diff --git a/dashboard/src/app/components/togglebutton/togglebutton.ts b/dashboard/src/app/components/togglebutton/togglebutton.ts deleted file mode 100644 index 0909cf7d1..000000000 --- a/dashboard/src/app/components/togglebutton/togglebutton.ts +++ /dev/null @@ -1,122 +0,0 @@ -import {NgModule,Component,Input,Output,EventEmitter,forwardRef,AfterViewInit,ViewChild,ElementRef} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; - -export const TOGGLEBUTTON_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => ToggleButton), - multi: true -}; - -@Component({ - selector: 'p-toggleButton', - template: ` -
        -
        - -
        - - {{checked ? hasOnLabel ? onLabel : 'ui-btn' : hasOffLabel ? offLabel : 'ui-btn'}} -
        - `, - providers: [TOGGLEBUTTON_VALUE_ACCESSOR] -}) -export class ToggleButton implements ControlValueAccessor,AfterViewInit { - - @Input() onLabel: string = 'Yes'; - - @Input() offLabel: string = 'No'; - - @Input() onIcon: string; - - @Input() offIcon: string; - - @Input() disabled: boolean; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() inputId: string; - - @Input() tabindex: number; - - @Output() onChange: EventEmitter = new EventEmitter(); - - @ViewChild('checkbox') checkboxViewChild: ElementRef; - - checkbox: HTMLInputElement; - - checked: boolean = false; - - focus: boolean = false; - - onModelChange: Function = () => {}; - - onModelTouched: Function = () => {}; - - ngAfterViewInit() { - this.checkbox = this.checkboxViewChild.nativeElement; - } - - getIconClass() { - let baseClass = 'ui-button-icon-left fa fa-fw'; - return baseClass + ' ' + (this.checked ? this.onIcon : this.offIcon); - } - - toggle(event: Event) { - if(!this.disabled) { - this.checked = !this.checked; - this.onModelChange(this.checked); - this.onModelTouched(); - this.onChange.emit({ - originalEvent: event, - checked: this.checked - }); - this.checkbox.focus(); - } - } - - onFocus() { - this.focus = true; - } - - onBlur() { - this.focus = false; - this.onModelTouched(); - } - - writeValue(value: any) : void { - this.checked = value; - } - - registerOnChange(fn: Function): void { - this.onModelChange = fn; - } - - registerOnTouched(fn: Function): void { - this.onModelTouched = fn; - } - - setDisabledState(val: boolean): void { - this.disabled = val; - } - - get hasOnLabel():boolean { - return this.onLabel && this.onLabel.length > 0; - } - - get hasOffLabel():boolean { - return this.onLabel && this.onLabel.length > 0; - } -} - -@NgModule({ - imports: [CommonModule], - exports: [ToggleButton], - declarations: [ToggleButton] -}) -export class ToggleButtonModule { } diff --git a/dashboard/src/app/components/toolbar/toolbar.css b/dashboard/src/app/components/toolbar/toolbar.css deleted file mode 100644 index 0c48db8f5..000000000 --- a/dashboard/src/app/components/toolbar/toolbar.css +++ /dev/null @@ -1,11 +0,0 @@ -.ui-toolbar { - padding: .25em .5em; -} - -.ui-toolbar-group-left { - float:left -} - -.ui-toolbar-group-right { - float:right -} \ No newline at end of file diff --git a/dashboard/src/app/components/toolbar/toolbar.spec.ts b/dashboard/src/app/components/toolbar/toolbar.spec.ts deleted file mode 100644 index b0cffecfd..000000000 --- a/dashboard/src/app/components/toolbar/toolbar.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Toolbar } from './toolbar'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Toolbar', () => { - - let toolbar: Toolbar; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Toolbar - ] - }); - - fixture = TestBed.createComponent(Toolbar); - toolbar = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/toolbar/toolbar.ts b/dashboard/src/app/components/toolbar/toolbar.ts deleted file mode 100644 index 3e1c2d737..000000000 --- a/dashboard/src/app/components/toolbar/toolbar.ts +++ /dev/null @@ -1,32 +0,0 @@ -import {NgModule,Component,Input,Output,EventEmitter,ElementRef} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {BlockableUI} from '../common/blockableui'; - -@Component({ - selector: 'p-toolbar', - template: ` -
        - -
        - ` -}) -export class Toolbar implements BlockableUI { - - @Input() style: any; - - @Input() styleClass: string; - - constructor(private el: ElementRef) {} - - getBlockableElement(): HTMLElement { - return this.el.nativeElement.children[0]; - } - -} - -@NgModule({ - imports: [CommonModule], - exports: [Toolbar], - declarations: [Toolbar] -}) -export class ToolbarModule { } diff --git a/dashboard/src/app/components/tooltip/tooltip.css b/dashboard/src/app/components/tooltip/tooltip.css deleted file mode 100644 index 71329bd2d..000000000 --- a/dashboard/src/app/components/tooltip/tooltip.css +++ /dev/null @@ -1,67 +0,0 @@ -.ui-tooltip { - position:absolute; - display:none; - padding: .25em .5em; - max-width: 12.5em; -} - -.ui-tooltip.ui-tooltip-right, -.ui-tooltip.ui-tooltip-left { - padding: 0 .25em; -} - -.ui-tooltip.ui-tooltip-top, -.ui-tooltip.ui-tooltip-bottom { - padding:.25em 0; -} - -.ui-tooltip .ui-tooltip-text { - padding: .125em .5em; - background-color: rgb(76, 76, 76); - color: #ffffff; - white-space: pre-line; -} - -.ui-tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} - -.ui-tooltip-right .ui-tooltip-arrow { - top: 50%; - left: 0; - margin-top: -.25em; - border-width: .25em .25em .25em 0; - border-right-color: rgb(76, 76, 76); -} - -.ui-tooltip-left .ui-tooltip-arrow { - top: 50%; - right: 0; - margin-top: -.25em; - border-width: .25em 0 .25em .25em; - border-left-color: rgb(76, 76, 76); -} - -.ui-tooltip.ui-tooltip-top { - padding: .25em 0; -} - -.ui-tooltip-top .ui-tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -.25em; - border-width: .25em .25em 0; - border-top-color: rgb(76, 76, 76); -} - -.ui-tooltip-bottom .ui-tooltip-arrow { - top: 0; - left: 50%; - margin-left: -.25em; - border-width: 0 .25em .25em; - border-bottom-color: rgb(76, 76, 76); -} \ No newline at end of file diff --git a/dashboard/src/app/components/tooltip/tooltip.spec.ts b/dashboard/src/app/components/tooltip/tooltip.spec.ts deleted file mode 100644 index 05da7c78a..000000000 --- a/dashboard/src/app/components/tooltip/tooltip.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Tooltip } from './tooltip'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Tooltip', () => { - - let tooltip: Tooltip; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Tooltip - ] - }); - - fixture = TestBed.createComponent(Tooltip); - tooltip = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/tooltip/tooltip.ts b/dashboard/src/app/components/tooltip/tooltip.ts deleted file mode 100644 index c43c4a983..000000000 --- a/dashboard/src/app/components/tooltip/tooltip.ts +++ /dev/null @@ -1,388 +0,0 @@ -import { NgModule, Directive, ElementRef, AfterViewInit, OnDestroy, HostBinding, HostListener, Input, NgZone } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { DomHandler } from '../dom/domhandler'; - -@Directive({ - selector: '[pTooltip]', - providers: [DomHandler] -}) -export class Tooltip implements AfterViewInit, OnDestroy { - - @Input() tooltipPosition: string = 'right'; - - @Input() tooltipEvent: string = 'hover'; - - @Input() appendTo: any = 'body'; - - @Input() positionStyle: string; - - @Input() tooltipStyleClass: string; - - @Input() tooltipZIndex: string = 'auto'; - - @Input("tooltipDisabled") disabled: boolean; - - @Input() escape: boolean = true; - - @Input() showDelay: number; - - @Input() hideDelay: number; - - @Input() life: number; - - container: any; - - styleClass: string; - - tooltipText: any; - - showTimeout: any; - - hideTimeout: any; - - lifeTimeout: any; - - active: boolean; - - _text: string; - - mouseEnterListener: Function; - - mouseLeaveListener: Function; - - clickListener: Function; - - focusListener: Function; - - blurListener: Function; - - resizeListener: any; - - constructor(public el: ElementRef, public domHandler: DomHandler, public zone: NgZone) { } - - ngAfterViewInit() { - this.zone.runOutsideAngular(() => { - if (this.tooltipEvent === 'hover') { - this.mouseEnterListener = this.onMouseEnter.bind(this); - this.mouseLeaveListener = this.onMouseLeave.bind(this); - this.clickListener = this.onClick.bind(this); - this.el.nativeElement.addEventListener('mouseenter', this.mouseEnterListener); - this.el.nativeElement.addEventListener('mouseleave', this.mouseLeaveListener); - this.el.nativeElement.addEventListener('click', this.clickListener); - } - else if (this.tooltipEvent === 'focus') { - this.focusListener = this.onFocus.bind(this); - this.blurListener = this.onBlur.bind(this); - this.el.nativeElement.addEventListener('focus', this.focusListener); - this.el.nativeElement.addEventListener('blur', this.blurListener); - } - }); - } - - onMouseEnter(e: Event) { - if (!this.container) { - if (this.hideTimeout) { - clearTimeout(this.hideTimeout); - this.remove(); - } - - this.activate(); - } - } - - onMouseLeave(e: Event) { - this.deactivate(true); - } - - onFocus(e: Event) { - this.activate(); - } - - onBlur(e: Event) { - this.deactivate(true); - } - - onClick(e: Event) { - this.deactivate(true); - } - - activate() { - this.active = true; - if (this.hideTimeout) { - clearTimeout(this.hideTimeout); - } - - if (this.showDelay) - this.showTimeout = setTimeout(() => { this.show() }, this.showDelay); - else - this.show(); - - if (this.life) { - this.lifeTimeout = setTimeout(() => { this.deactivate(false) }, this.life); - } - } - - deactivate(useDelay) { - this.active = false; - if (this.showTimeout) { - clearTimeout(this.showTimeout); - } - - if (this.lifeTimeout) { - clearTimeout(this.lifeTimeout); - } - - if (this.hideDelay && useDelay) - this.hideTimeout = setTimeout(() => { this.hide() }, this.hideDelay); - else - this.hide(); - } - - get text(): string { - return this._text; - } - - @Input('pTooltip') set text(text: string) { - this._text = text; - if (this.active) { - if (this._text) { - if (this.container && this.container.offsetParent) - this.updateText(); - else - this.show(); - } - else { - this.hide(); - } - } - } - - create() { - this.container = document.createElement('div'); - - let tooltipArrow = document.createElement('div'); - tooltipArrow.className = 'ui-tooltip-arrow'; - this.container.appendChild(tooltipArrow); - - this.tooltipText = document.createElement('div'); - this.tooltipText.className = 'ui-tooltip-text ui-shadow ui-corner-all'; - - this.updateText(); - - if (this.positionStyle) { - this.container.style.position = this.positionStyle; - } - - this.container.appendChild(this.tooltipText); - - if (this.appendTo === 'body') - document.body.appendChild(this.container); - else if (this.appendTo === 'target') - this.domHandler.appendChild(this.container, this.el.nativeElement); - else - this.domHandler.appendChild(this.container, this.appendTo); - - this.container.style.display = 'inline-block'; - } - - show() { - if (!this.text || this.disabled) { - return; - } - - this.create(); - this.align(); - this.domHandler.fadeIn(this.container, 250); - - if (this.tooltipZIndex === 'auto') - this.container.style.zIndex = ++DomHandler.zindex; - else - this.container.style.zIndex = this.tooltipZIndex; - - this.bindDocumentResizeListener(); - } - - hide() { - this.remove(); - } - - updateText() { - if (this.escape) { - this.tooltipText.innerHTML = ''; - this.tooltipText.appendChild(document.createTextNode(this._text)); - } - else { - this.tooltipText.innerHTML = this._text; - } - } - - align() { - let position = this.tooltipPosition; - - switch (position) { - case 'top': - this.alignTop(); - if (this.isOutOfBounds()) { - this.alignBottom(); - } - break; - - case 'bottom': - this.alignBottom(); - if (this.isOutOfBounds()) { - this.alignTop(); - } - break; - - case 'left': - this.alignLeft(); - if (this.isOutOfBounds()) { - this.alignRight(); - - if (this.isOutOfBounds()) { - this.alignTop(); - - if (this.isOutOfBounds()) { - this.alignBottom(); - } - } - } - break; - - case 'right': - this.alignRight(); - if (this.isOutOfBounds()) { - this.alignLeft(); - - if (this.isOutOfBounds()) { - this.alignTop(); - - if (this.isOutOfBounds()) { - this.alignBottom(); - } - } - } - break; - } - } - - getHostOffset() { - let offset = this.el.nativeElement.getBoundingClientRect(); - let targetLeft = offset.left + this.domHandler.getWindowScrollLeft(); - let targetTop = offset.top + this.domHandler.getWindowScrollTop(); - - return { left: targetLeft, top: targetTop }; - } - - alignRight() { - this.preAlign('right'); - let hostOffset = this.getHostOffset(); - let left = hostOffset.left + this.domHandler.getOuterWidth(this.el.nativeElement); - let top = hostOffset.top + (this.domHandler.getOuterHeight(this.el.nativeElement) - this.domHandler.getOuterHeight(this.container)) / 2; - this.container.style.left = left + 'px'; - this.container.style.top = top + 'px'; - } - - alignLeft() { - this.preAlign('left'); - let hostOffset = this.getHostOffset(); - let left = hostOffset.left - this.domHandler.getOuterWidth(this.container); - let top = hostOffset.top + (this.domHandler.getOuterHeight(this.el.nativeElement) - this.domHandler.getOuterHeight(this.container)) / 2; - this.container.style.left = left + 'px'; - this.container.style.top = top + 'px'; - } - - alignTop() { - this.preAlign('top'); - let hostOffset = this.getHostOffset(); - let left = hostOffset.left + (this.domHandler.getOuterWidth(this.el.nativeElement) - this.domHandler.getOuterWidth(this.container)) / 2; - let top = hostOffset.top - this.domHandler.getOuterHeight(this.container); - this.container.style.left = left + 'px'; - this.container.style.top = top + 'px'; - } - - alignBottom() { - this.preAlign('bottom'); - let hostOffset = this.getHostOffset(); - let left = hostOffset.left + (this.domHandler.getOuterWidth(this.el.nativeElement) - this.domHandler.getOuterWidth(this.container)) / 2; - let top = hostOffset.top + this.domHandler.getOuterHeight(this.el.nativeElement); - this.container.style.left = left + 'px'; - this.container.style.top = top + 'px'; - } - - preAlign(position: string) { - this.container.style.left = -999 + 'px'; - this.container.style.top = -999 + 'px'; - - let defaultClassName = 'ui-tooltip ui-widget ui-tooltip-' + position; - this.container.className = this.tooltipStyleClass ? defaultClassName + ' ' + this.tooltipStyleClass : defaultClassName; - } - - isOutOfBounds(): boolean { - let offset = this.container.getBoundingClientRect(); - let targetTop = offset.top; - let targetLeft = offset.left; - let width = this.domHandler.getOuterWidth(this.container); - let height = this.domHandler.getOuterHeight(this.container); - let viewport = this.domHandler.getViewport(); - - return (targetLeft + width > viewport.width) || (targetLeft < 0) || (targetTop < 0) || (targetTop + height > viewport.height); - } - - onWindowResize(e: Event) { - this.hide(); - } - - bindDocumentResizeListener() { - this.zone.runOutsideAngular(() => { - this.resizeListener = this.onWindowResize.bind(this); - window.addEventListener('resize', this.resizeListener); - }); - } - - unbindDocumentResizeListener() { - if (this.resizeListener) { - window.removeEventListener('resize', this.resizeListener); - this.resizeListener = null; - } - } - - unbindEvents() { - if (this.tooltipEvent === 'hover') { - this.el.nativeElement.removeEventListener('mouseenter', this.mouseEnterListener); - this.el.nativeElement.removeEventListener('mouseleave', this.mouseLeaveListener); - this.el.nativeElement.removeEventListener('click', this.clickListener); - } - else if (this.tooltipEvent === 'focus') { - this.el.nativeElement.removeEventListener('focus', this.focusListener); - this.el.nativeElement.removeEventListener('blur', this.blurListener); - } - - this.unbindDocumentResizeListener(); - } - - remove() { - if (this.container && this.container.parentElement) { - if (this.appendTo === 'body') - document.body.removeChild(this.container); - else if (this.appendTo === 'target') - this.el.nativeElement.removeChild(this.container); - else - this.domHandler.removeChild(this.container, this.appendTo); - } - - this.container = null; - } - - ngOnDestroy() { - this.unbindEvents(); - this.remove(); - } -} - -@NgModule({ - imports: [CommonModule], - exports: [Tooltip], - declarations: [Tooltip] -}) -export class TooltipModule { } diff --git a/dashboard/src/app/components/tree/images/line.gif b/dashboard/src/app/components/tree/images/line.gif deleted file mode 100644 index 64e2280ec55b5af431513c21695c69bb0ff67240..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13112 zcmeI3XOt6F7=|Y+h%6Qq#DZmZzyfYEC1FFxBr7H?MT5Yu($U$Oo9vimW}M8D?Aow5 z6tH0LB8mkT0a2>G_d>A%HY^moVv94IkSur(p6>_$zBxI`&7J4F<+<8NB$_HVE@XGn6ASac&vs9K2Gwsa*!t4fF&Ga$yrj0kB` zhqjuezI8-{+?tdF3R4@d4CcgK+DH>iqI2n#mJxFyMpE=fBHC@In`P*B#7c&kLCy=> znKPoBg!XxOx6FBcw6De^_=SMKrkbvoEPA-4(Sn~AIL`hOM6cie(8Y%dSK6(hsl>(6 z(YoTC_P-F*WLbvDve|6bll6LZGr{tKK!D{0RuJ4a;m)*ZmXvdAnLdRuEM887%MN*wV;$VbJarBPNk7-E7eH zRJgGHI@Kgu-ArcaNWC}cRPF?oXD!zg`-n(b;CRl>dEGqUz;hyBBl`I99qJ3vF6A*@ zQR6NDDHlYaPvir|@(xh3JjgmCI*4hv?(Auo{{IuE$R%G!vzcl?7DZ-Bilm8VWo&2s z&dwBBjO%7vvchUwN)R@o#)E9RbGPd&tlEx+9ZR;9%NH--6!I&=81u_7FF$Xx=7}JHi zKn6fCrVDj}41i!v7wQ5T0Ku3p)CDpCf-zmF3uFKUW4cfm$N&h&bfGSg0T7JoLR}yO zAQ;nyx>V+4af8M#R zExGKJW-DW!W9V8sl{{N*O2mmGH%e!nIeF5=3FF6&9dpL%4fUf(jXZ5c?9@|+4;wn9 zZg4bm@}QGy!=WH01_t_T2Kc-J&#@kN^$Gp^9e>=h$Mo&PRMAHtb>tDf4?pbCLwX(D xv&TUPc0XYM{r2rv*>#^Tdw1@%SA~nBs .ui-treenode-content > .ui-tree-toggler { - visibility: hidden; -} - -.ui-tree .ui-chkbox-box { - cursor: pointer; -} - -.ui-tree .ui-chkbox { - display: inline-block; - vertical-align: middle; -} - -.ui-tree .ui-chkbox .ui-chkbox-icon { - margin-left: 1px; -} - -/** Fluid **/ -.ui-fluid .ui-tree { - width: 100%; -} - -/** Horizontal Tree **/ -.ui-tree-horizontal { - width:auto; - padding: .5em 0; - overflow:auto; -} - -.ui-tree.ui-tree-horizontal table, -.ui-tree.ui-tree-horizontal tr, -.ui-tree.ui-tree-horizontal td { - border-collapse: collapse; - margin: 0; - padding: 0; - vertical-align: middle; -} - -.ui-tree.ui-tree-horizontal .ui-tree-toggler { - vertical-align: middle; - margin: 0; -} - -.ui-tree-horizontal .ui-treenode-content { - font-weight: normal; - padding: 0.4em 1em 0.4em 0.2em; -} - -.ui-tree.ui-tree-horizontal .ui-tree-node-label { - margin: 0; -} - -.ui-tree-horizontal .ui-treenode-parent .ui-treenode-content { - font-weight: normal; - white-space: nowrap; -} - -.ui-tree.ui-tree-horizontal .ui-treenode { - background: url("./images/line.gif") repeat-x scroll center center transparent; - padding: .25em 2.5em; -} - -.ui-tree.ui-tree-horizontal .ui-treenode.ui-treenode-leaf, -.ui-tree.ui-tree-horizontal .ui-treenode.ui-treenode-collapsed { - padding-right: 0; -} - -.ui-tree.ui-tree-horizontal .ui-treenode-children { - padding: 0; - margin: 0; -} - -.ui-tree.ui-tree-horizontal .ui-treenode-connector { - width: 1px; -} - -.ui-tree.ui-tree-horizontal .ui-treenode-connector-table { - height: 100%; - width: 1px; -} - -.ui-tree.ui-tree-horizontal .ui-treenode-connector-line { - background: url("./images/line.gif") repeat-y scroll 0 0 transparent; - width: 1px; -} - -.ui-tree.ui-tree-horizontal table { - height: 0; -} - -.ui-tree.ui-tree-horizontal .ui-chkbox { - vertical-align: bottom; - margin-right: .25em; -} - -/** Loading **/ -.ui-tree.ui-tree-loading { - position: relative; - min-height: 4em; -} - -.ui-tree .ui-tree-loading-mask { - position: absolute; - width: 100%; - height: 100%; - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=10)"; - opacity: 0.1; - z-index: 1; -} - -.ui-tree .ui-tree-loading-content { - position: absolute; - left: 50%; - top: 50%; - z-index: 2; - margin-top: -1em; - margin-left: -1em; -} diff --git a/dashboard/src/app/components/tree/tree.spec.ts b/dashboard/src/app/components/tree/tree.spec.ts deleted file mode 100644 index 21b398771..000000000 --- a/dashboard/src/app/components/tree/tree.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Tree } from './tree'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('Tree', () => { - - let tree: Tree; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - Tree - ] - }); - - fixture = TestBed.createComponent(Tree); - tree = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/tree/tree.ts b/dashboard/src/app/components/tree/tree.ts deleted file mode 100644 index ba3a62c79..000000000 --- a/dashboard/src/app/components/tree/tree.ts +++ /dev/null @@ -1,779 +0,0 @@ -import {NgModule,Component,Input,AfterContentInit,OnDestroy,Output,EventEmitter,OnInit,EmbeddedViewRef,ViewContainerRef, - ContentChildren,QueryList,TemplateRef,Inject,ElementRef,forwardRef,Host} from '@angular/core'; -import {Optional} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {TreeNode} from '../common/treenode'; -import {SharedModule} from '../common/shared'; -import {PrimeTemplate} from '../common/shared'; -import {TreeDragDropService} from '../common/treedragdropservice'; -import {Subscription} from 'rxjs/Subscription'; -import {BlockableUI} from '../common/blockableui'; - -@Component({ - selector: 'p-treeNode', - template: ` - -
      • -
      • -
        -
        -
        - {{node.label}} - - - - -
        - -
      • -
      • - - - - - - - - -
        - - - - - - - - - -
        -
        -
        - - {{node.label}} - - - - -
        -
        -
        - -
        -
        -
        - ` -}) -export class UITreeNode implements OnInit { - - static ICON_CLASS: string = 'ui-treenode-icon fa fa-fw'; - - @Input() node: TreeNode; - - @Input() parentNode: TreeNode; - - @Input() root: boolean; - - @Input() index: number; - - @Input() firstChild: boolean; - - @Input() lastChild: boolean; - - constructor(@Inject(forwardRef(() => Tree)) public tree:Tree) {} - - draghoverPrev: boolean; - - draghoverNext: boolean; - - draghoverNode: boolean - - ngOnInit() { - this.node.parent = this.parentNode; - } - - getIcon() { - let icon: string; - - if(this.node.icon) - icon = this.node.icon; - else - icon = this.node.expanded && this.node.children && this.node.children.length ? this.node.expandedIcon : this.node.collapsedIcon; - - return UITreeNode.ICON_CLASS + ' ' + icon; - } - - isLeaf() { - return this.node.leaf == false ? false : !(this.node.children&&this.node.children.length); - } - - toggle(event: Event) { - if(this.node.expanded) - this.tree.onNodeCollapse.emit({originalEvent: event, node: this.node}); - else - this.tree.onNodeExpand.emit({originalEvent: event, node: this.node}); - - this.node.expanded = !this.node.expanded - } - - onNodeClick(event: MouseEvent) { - this.tree.onNodeClick(event, this.node); - } - - onNodeTouchEnd() { - this.tree.onNodeTouchEnd(); - } - - onNodeRightClick(event: MouseEvent) { - this.tree.onNodeRightClick(event, this.node); - } - - isSelected() { - return this.tree.isSelected(this.node); - } - - onDropPoint(event: Event, position: number) { - event.preventDefault(); - let dragNode = this.tree.dragNode; - let dragNodeIndex = this.tree.dragNodeIndex; - let dragNodeScope = this.tree.dragNodeScope; - let isValidDropPointIndex = this.tree.dragNodeTree === this.tree ? (position === 1 || dragNodeIndex !== this.index - 1) : true; - - if(this.tree.allowDrop(dragNode, this.node, dragNodeScope) && isValidDropPointIndex) { - let newNodeList = this.node.parent ? this.node.parent.children : this.tree.value; - this.tree.dragNodeSubNodes.splice(dragNodeIndex, 1); - let dropIndex = this.index; - - if(position < 0) { - dropIndex = (this.tree.dragNodeSubNodes === newNodeList) ? ((this.tree.dragNodeIndex > this.index) ? this.index : this.index - 1) : this.index; - newNodeList.splice(dropIndex, 0, dragNode); - } - else { - dropIndex = newNodeList.length; - newNodeList.push(dragNode); - } - - this.tree.dragDropService.stopDrag({ - node: dragNode, - subNodes: this.node.parent ? this.node.parent.children : this.tree.value, - index: dragNodeIndex - }); - - this.tree.onNodeDrop.emit({ - originalEvent: event, - dragNode: dragNode, - dropNode: this.node, - dropIndex: dropIndex - }); - } - - this.draghoverPrev = false; - this.draghoverNext = false; - } - - onDropPointDragOver(event) { - event.dataTransfer.dropEffect = 'move'; - event.preventDefault(); - } - - onDropPointDragEnter(event: Event, position: number) { - if(this.tree.allowDrop(this.tree.dragNode, this.node, this.tree.dragNodeScope)) { - if(position < 0) - this.draghoverPrev = true; - else - this.draghoverNext = true; - } - } - - onDropPointDragLeave(event: Event) { - this.draghoverPrev = false; - this.draghoverNext = false; - } - - onDragStart(event) { - if(this.tree.draggableNodes && this.node.draggable !== false) { - event.dataTransfer.setData("text", "data"); - - this.tree.dragDropService.startDrag({ - tree: this, - node: this.node, - subNodes: this.node.parent ? this.node.parent.children : this.tree.value, - index: this.index, - scope: this.tree.draggableScope - }); - } - else { - event.preventDefault(); - } - } - - onDragStop(event) { - this.tree.dragDropService.stopDrag({ - node: this.node, - subNodes: this.node.parent ? this.node.parent.children : this.tree.value, - index: this.index - }); - } - - onDropNodeDragOver(event) { - event.dataTransfer.dropEffect = 'move'; - if(this.tree.droppableNodes) { - event.preventDefault(); - event.stopPropagation(); - } - } - - onDropNode(event) { - if(this.tree.droppableNodes && this.node.droppable !== false) { - event.preventDefault(); - event.stopPropagation(); - let dragNode = this.tree.dragNode; - if(this.tree.allowDrop(dragNode, this.node, this.tree.dragNodeScope)) { - let dragNodeIndex = this.tree.dragNodeIndex; - this.tree.dragNodeSubNodes.splice(dragNodeIndex, 1); - - if(this.node.children) - this.node.children.push(dragNode); - else - this.node.children = [dragNode]; - - this.tree.dragDropService.stopDrag({ - node: dragNode, - subNodes: this.node.parent ? this.node.parent.children : this.tree.value, - index: this.tree.dragNodeIndex - }); - - this.tree.onNodeDrop.emit({ - originalEvent: event, - dragNode: dragNode, - dropNode: this.node, - index: this.index - }); - } - } - - this.draghoverNode = false; - } - - onDropNodeDragEnter(event) { - if(this.tree.droppableNodes && this.node.droppable !== false && this.tree.allowDrop(this.tree.dragNode, this.node, this.tree.dragNodeScope)) { - this.draghoverNode = true; - } - } - - onDropNodeDragLeave(event) { - if(this.tree.droppableNodes) { - let rect = event.currentTarget.getBoundingClientRect(); - if(event.x > rect.left + rect.width || event.x < rect.left || event.y >= Math.floor(rect.top + rect.height) || event.y < rect.top) { - this.draghoverNode = false; - } - } - } -} - -@Component({ - selector: 'p-tree', - template: ` -
        -
        -
        - -
        -
          - -
        -
        {{emptyMessage}}
        -
        -
        -
        -
        - -
        - - -
        -
        {{emptyMessage}}
        -
        - ` -}) -export class Tree implements OnInit,AfterContentInit,OnDestroy,BlockableUI { - - @Input() value: TreeNode[]; - - @Input() selectionMode: string; - - @Input() selection: any; - - @Output() selectionChange: EventEmitter = new EventEmitter(); - - @Output() onNodeSelect: EventEmitter = new EventEmitter(); - - @Output() onNodeUnselect: EventEmitter = new EventEmitter(); - - @Output() onNodeExpand: EventEmitter = new EventEmitter(); - - @Output() onNodeCollapse: EventEmitter = new EventEmitter(); - - @Output() onNodeContextMenuSelect: EventEmitter = new EventEmitter(); - - @Output() onNodeDrop: EventEmitter = new EventEmitter(); - - @Input() style: any; - - @Input() styleClass: string; - - @Input() contextMenu: any; - - @Input() layout: string = 'vertical'; - - @Input() draggableScope: any; - - @Input() droppableScope: any; - - @Input() draggableNodes: boolean; - - @Input() droppableNodes: boolean; - - @Input() metaKeySelection: boolean = true; - - @Input() propagateSelectionUp: boolean = true; - - @Input() propagateSelectionDown: boolean = true; - - @Input() loading: boolean; - - @Input() loadingIcon: string = 'fa-circle-o-notch'; - - @Input() emptyMessage: string = 'No records found'; - - @ContentChildren(PrimeTemplate) templates: QueryList; - - public templateMap: any; - - public nodeTouched: boolean; - - public dragNodeTree: Tree; - - public dragNode: TreeNode; - - public dragNodeSubNodes: TreeNode[]; - - public dragNodeIndex: number; - - public dragNodeScope: any; - - public dragHover: boolean; - - public dragStartSubscription: Subscription; - - public dragStopSubscription: Subscription; - - constructor(public el: ElementRef, @Optional() public dragDropService: TreeDragDropService) {} - - ngOnInit() { - if(this.droppableNodes) { - this.dragStartSubscription = this.dragDropService.dragStart$.subscribe( - event => { - this.dragNodeTree = event.tree; - this.dragNode = event.node; - this.dragNodeSubNodes = event.subNodes; - this.dragNodeIndex = event.index; - this.dragNodeScope = event.scope; - }); - - this.dragStopSubscription = this.dragDropService.dragStop$.subscribe( - event => { - this.dragNodeTree = null; - this.dragNode = null; - this.dragNodeSubNodes = null; - this.dragNodeIndex = null; - this.dragNodeScope = null; - this.dragHover = false; - }); - } - } - - get horizontal(): boolean { - return this.layout == 'horizontal'; - } - - ngAfterContentInit() { - if(this.templates.length) { - this.templateMap = {}; - } - - this.templates.forEach((item) => { - this.templateMap[item.name] = item.template; - }); - } - - onNodeClick(event: MouseEvent, node: TreeNode) { - let eventTarget = ( event.target); - - if(eventTarget.className && eventTarget.className.indexOf('ui-tree-toggler') === 0) { - return; - } - else if(this.selectionMode) { - if(node.selectable === false) { - return; - } - - let index = this.findIndexInSelection(node); - let selected = (index >= 0); - - if(this.isCheckboxSelectionMode()) { - if(selected) { - if(this.propagateSelectionDown) - this.propagateDown(node, false); - else - this.selection = this.selection.filter((val,i) => i!=index); - - if(this.propagateSelectionUp && node.parent) { - this.propagateUp(node.parent, false); - } - - this.selectionChange.emit(this.selection); - this.onNodeUnselect.emit({originalEvent: event, node: node}); - } - else { - if(this.propagateSelectionDown) - this.propagateDown(node, true); - else - this.selection = [...this.selection||[],node]; - - if(this.propagateSelectionUp && node.parent) { - this.propagateUp(node.parent, true); - } - - this.selectionChange.emit(this.selection); - this.onNodeSelect.emit({originalEvent: event, node: node}); - } - } - else { - let metaSelection = this.nodeTouched ? false : this.metaKeySelection; - - if(metaSelection) { - let metaKey = (event.metaKey||event.ctrlKey); - - if(selected && metaKey) { - if(this.isSingleSelectionMode()) { - this.selectionChange.emit(null); - } - else { - this.selection = this.selection.filter((val,i) => i!=index); - this.selectionChange.emit(this.selection); - } - - this.onNodeUnselect.emit({originalEvent: event, node: node}); - } - else { - if(this.isSingleSelectionMode()) { - this.selectionChange.emit(node); - } - else if(this.isMultipleSelectionMode()) { - this.selection = (!metaKey) ? [] : this.selection||[]; - this.selection = [...this.selection,node]; - this.selectionChange.emit(this.selection); - } - - this.onNodeSelect.emit({originalEvent: event, node: node}); - } - } - else { - if(this.isSingleSelectionMode()) { - if(selected) { - this.selection = null; - this.onNodeUnselect.emit({originalEvent: event, node: node}); - } - else { - this.selection = node; - this.onNodeSelect.emit({originalEvent: event, node: node}); - } - } - else { - if(selected) { - this.selection = this.selection.filter((val,i) => i!=index); - this.onNodeUnselect.emit({originalEvent: event, node: node}); - } - else { - this.selection = [...this.selection||[],node]; - this.onNodeSelect.emit({originalEvent: event, node: node}); - } - } - - this.selectionChange.emit(this.selection); - } - } - } - - this.nodeTouched = false; - } - - onNodeTouchEnd() { - this.nodeTouched = true; - } - - onNodeRightClick(event: MouseEvent, node: TreeNode) { - if(this.contextMenu) { - let eventTarget = ( event.target); - - if(eventTarget.className && eventTarget.className.indexOf('ui-tree-toggler') === 0) { - return; - } - else { - let index = this.findIndexInSelection(node); - let selected = (index >= 0); - - if(!selected) { - if(this.isSingleSelectionMode()) - this.selectionChange.emit(node); - else - this.selectionChange.emit([node]); - } - - this.contextMenu.show(event); - this.onNodeContextMenuSelect.emit({originalEvent: event, node: node}); - } - } - } - - findIndexInSelection(node: TreeNode) { - let index: number = -1; - - if(this.selectionMode && this.selection) { - if(this.isSingleSelectionMode()) { - index = (this.selection == node) ? 0 : - 1; - } - else { - for(let i = 0; i < this.selection.length; i++) { - if(this.selection[i] == node) { - index = i; - break; - } - } - } - } - - return index; - } - - propagateUp(node: TreeNode, select: boolean) { - if(node.children && node.children.length) { - let selectedCount: number = 0; - let childPartialSelected: boolean = false; - for(let child of node.children) { - if(this.isSelected(child)) { - selectedCount++; - } - else if(child.partialSelected) { - childPartialSelected = true; - } - } - - if(select && selectedCount == node.children.length) { - this.selection = [...this.selection||[],node]; - node.partialSelected = false; - } - else { - if(!select) { - let index = this.findIndexInSelection(node); - if(index >= 0) { - this.selection = this.selection.filter((val,i) => i!=index); - } - } - - if(childPartialSelected || selectedCount > 0 && selectedCount != node.children.length) - node.partialSelected = true; - else - node.partialSelected = false; - } - } - - let parent = node.parent; - if(parent) { - this.propagateUp(parent, select); - } - } - - propagateDown(node: TreeNode, select: boolean) { - let index = this.findIndexInSelection(node); - - if(select && index == -1) { - this.selection = [...this.selection||[],node]; - } - else if(!select && index > -1) { - this.selection = this.selection.filter((val,i) => i!=index); - } - - node.partialSelected = false; - - if(node.children && node.children.length) { - for(let child of node.children) { - this.propagateDown(child, select); - } - } - } - - isSelected(node: TreeNode) { - return this.findIndexInSelection(node) != -1; - } - - isSingleSelectionMode() { - return this.selectionMode && this.selectionMode == 'single'; - } - - isMultipleSelectionMode() { - return this.selectionMode && this.selectionMode == 'multiple'; - } - - isCheckboxSelectionMode() { - return this.selectionMode && this.selectionMode == 'checkbox'; - } - - getTemplateForNode(node: TreeNode): TemplateRef { - if(this.templateMap) - return node.type ? this.templateMap[node.type] : this.templateMap['default']; - else - return null; - } - - onDragOver(event) { - if(this.droppableNodes && (!this.value || this.value.length === 0)) { - event.dataTransfer.dropEffect = 'move'; - event.preventDefault(); - } - } - - onDrop(event) { - if(this.droppableNodes && (!this.value || this.value.length === 0)) { - event.preventDefault(); - let dragNode = this.dragNode; - if(this.allowDrop(dragNode, null, this.dragNodeScope)) { - let dragNodeIndex = this.dragNodeIndex; - this.dragNodeSubNodes.splice(dragNodeIndex, 1); - this.value = this.value||[]; - this.value.push(dragNode); - - this.dragDropService.stopDrag({ - node: dragNode - }); - } - } - } - - onDragEnter(event) { - if(this.droppableNodes && this.allowDrop(this.dragNode, null, this.dragNodeScope)) { - this.dragHover = true; - } - } - - onDragLeave(event) { - if(this.droppableNodes) { - let rect = event.currentTarget.getBoundingClientRect(); - if(event.x > rect.left + rect.width || event.x < rect.left || event.y > rect.top + rect.height || event.y < rect.top) { - this.dragHover = false; - } - } - } - - allowDrop(dragNode: TreeNode, dropNode: TreeNode, dragNodeScope: any): boolean { - if(!dragNode) { - //prevent random html elements to be dragged - return false; - } - else if(this.isValidDragScope(dragNodeScope)) { - let allow: boolean = true; - if(dropNode) { - if(dragNode === dropNode) { - allow = false; - } - else { - let parent = dropNode.parent; - while(parent != null) { - if(parent === dragNode) { - allow = false; - break; - } - parent = parent.parent; - } - } - } - - return allow; - } - else { - return false; - } - } - - isValidDragScope(dragScope: any): boolean { - let dropScope = this.droppableScope; - - if(dropScope) { - if(typeof dropScope === 'string') { - if(typeof dragScope === 'string') - return dropScope === dragScope; - else if(dragScope instanceof Array) - return (>dragScope).indexOf(dropScope) != -1; - } - else if(dropScope instanceof Array) { - if(typeof dragScope === 'string') { - return (>dropScope).indexOf(dragScope) != -1; - } - else if(dragScope instanceof Array) { - for(let s of dropScope) { - for(let ds of dragScope) { - if(s === ds) { - return true; - } - } - } - } - } - return false; - } - else { - return true; - } - } - - getBlockableElement(): HTMLElement { - return this.el.nativeElement.children[0]; - } - - ngOnDestroy() { - if(this.dragStartSubscription) { - this.dragStartSubscription.unsubscribe(); - } - - if(this.dragStopSubscription) { - this.dragStopSubscription.unsubscribe(); - } - } -} -@NgModule({ - imports: [CommonModule], - exports: [Tree,SharedModule], - declarations: [Tree,UITreeNode] -}) -export class TreeModule { } diff --git a/dashboard/src/app/components/treetable/treetable.css b/dashboard/src/app/components/treetable/treetable.css deleted file mode 100644 index 1c7ae8b3a..000000000 --- a/dashboard/src/app/components/treetable/treetable.css +++ /dev/null @@ -1,134 +0,0 @@ -.ui-treetable { - position: relative; -} - -.ui-treetable table { - border-collapse:collapse; - width: 100%; - table-layout: fixed; -} - -.ui-treetable .ui-treetable-header, -.ui-treetable .ui-treetable-footer { - text-align:center; - padding: .5em .75em; -} - -.ui-treetable .ui-treetable-header { - border-bottom: 0 none; -} - -.ui-treetable .ui-treetable-footer { - border-top: 0 none; -} - -.ui-treetable th, .ui-treetable tfoot td { - text-align: center; -} - -.ui-treetable thead th, -.ui-treetable tbody td, -.ui-treetable tfoot td { - padding: .25em .5em; - overflow: hidden; - white-space: nowrap; - border-width: 1px; - border-style: solid; -} - -.ui-treetable tbody td { - border-color: inherit; -} - -.ui-treetable tbody td:first-child span { - vertical-align: middle; -} - -.ui-treetable .ui-treetable-toggler { - vertical-align: middle; - cursor: pointer; - text-decoration: none; -} - -.ui-treetable .ui-treetable-checkbox { - margin-right: .5em; -} - -.ui-treetable .ui-treetable-checkbox .ui-chkbox-icon { - margin-left: 1px; -} - -.ui-treetable .ui-treetable-row.ui-treetable-row-selectable { - cursor: pointer; -} - -.ui-treetable .ui-treetable-row.ui-state-highlight { - border: 0 none; -} - -.ui-treetable tr.ui-state-hover { - border-color: inherit; - font-weight: inherit; -} - -.ui-treetable .ui-treetable-indent { - width: 1em; - height: 1em; - float: left; -} - -/* Resizable */ -.ui-treetable .ui-column-resizer { - display: block; - position: absolute !important; - top: 0; - right: 0; - margin: 0; - width: .5em; - height: 100%; - padding: 0px; - cursor:col-resize; - border: 1px solid transparent; -} - -.ui-treetable .ui-column-resizer-helper { - width: 1px; - position: absolute; - z-index: 10; - display: none; -} - -.ui-treetable-resizable { - padding-bottom: 1px; /*fix for webkit overlow*/ - overflow:auto; -} - -.ui-treetable-resizable thead th, -.ui-treetable-resizable tbody td, -.ui-treetable-resizable tfoot td { - white-space: nowrap; -} - -.ui-treetable-resizable th.ui-resizable-column { - background-clip: padding-box; - position: relative; -} - -/* PrimeNG */ -.ui-treetable td.ui-treetable-child-table-container { - padding: 0; - border: 0 none; -} - -.ui-treetable .ui-treetable-row { - display: table-row; - border-bottom: 0 transparent -} - -.ui-treetable tbody .ui-treetable-row td { - border: 0 none; -} - -.ui-treetable tbody .ui-treetable-row td input { - outline: 0 none; -} \ No newline at end of file diff --git a/dashboard/src/app/components/treetable/treetable.spec.ts b/dashboard/src/app/components/treetable/treetable.spec.ts deleted file mode 100644 index 6c854af0e..000000000 --- a/dashboard/src/app/components/treetable/treetable.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { TreeTable } from './treetable'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('TreeTable', () => { - - let treetable: TreeTable; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - TreeTable - ] - }); - - fixture = TestBed.createComponent(TreeTable); - treetable = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/treetable/treetable.ts b/dashboard/src/app/components/treetable/treetable.ts deleted file mode 100644 index a897b0be8..000000000 --- a/dashboard/src/app/components/treetable/treetable.ts +++ /dev/null @@ -1,449 +0,0 @@ -import {NgModule,Component,Input,Output,EventEmitter,AfterContentInit,ElementRef,ContentChild,IterableDiffers,ChangeDetectorRef,ContentChildren,QueryList,Inject,forwardRef,OnInit,Renderer2,ViewChild} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {TreeNode} from '../common/treenode'; -import {Header,Footer,Column} from '../common/shared'; -import {SharedModule} from '../common/shared'; -import {Subscription} from 'rxjs/Subscription'; -import {DomHandler} from '../dom/domhandler'; - -@Component({ - selector: '[pTreeRow]', - template: ` -
        - - - -
        -
        {{resolveFieldData(node.data,col.field)}} - - -
        -
        - - - -
        - -
        - ` -}) -export class UITreeRow implements OnInit { - - @Input() node: TreeNode; - - @Input() parentNode: TreeNode; - - @Input() level: number = 0; - - @Input() labelExpand: string = "Expand"; - - @Input() labelCollapse: string = "Collapse"; - - constructor(@Inject(forwardRef(() => TreeTable)) public treeTable:TreeTable) {} - - ngOnInit() { - this.node.parent = this.parentNode; - } - - toggle(event: Event) { - if(this.node.expanded) - this.treeTable.onNodeCollapse.emit({originalEvent: event, node: this.node}); - else - this.treeTable.onNodeExpand.emit({originalEvent: event, node: this.node}); - - this.node.expanded = !this.node.expanded; - - event.preventDefault(); - } - - isLeaf() { - return this.node.leaf == false ? false : !(this.node.children&&this.node.children.length); - } - - isSelected() { - return this.treeTable.isSelected(this.node); - } - - onRowClick(event: MouseEvent) { - this.treeTable.onRowClick(event, this.node); - } - - onRowRightClick(event: MouseEvent) { - this.treeTable.onRowRightClick(event, this.node); - } - - rowDblClick(event: MouseEvent) { - this.treeTable.onRowDblclick.emit({originalEvent: event, node: this.node}); - } - - onRowTouchEnd() { - this.treeTable.onRowTouchEnd(); - } - - resolveFieldData(data: any, field: string): any { - if(data && field) { - if(field.indexOf('.') == -1) { - return data[field]; - } - else { - let fields: string[] = field.split('.'); - let value = data; - for(var i = 0, len = fields.length; i < len; ++i) { - value = value[fields[i]]; - } - return value; - } - } - else { - return null; - } - } -} - -@Component({ - selector: 'p-treeTable', - template: ` -
        -
        - -
        -
        - - - - - - - - - - - - -
        - {{col.header}} - - - -
        - {{col.footer}} - - - -
        -
        - - -
        - `, - providers: [DomHandler] -}) -export class TreeTable implements AfterContentInit { - - @Input() value: TreeNode[]; - - @Input() selectionMode: string; - - @Input() selection: any; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() labelExpand: string = "Expand"; - - @Input() labelCollapse: string = "Collapse"; - - @Input() metaKeySelection: boolean = true; - - @Input() contextMenu: any; - - @Input() toggleColumnIndex: number = 0; - - @Input() tableStyle: any; - - @Input() tableStyleClass: string; - - @Input() collapsedIcon: string = "fa-caret-right"; - - @Input() expandedIcon: string = "fa-caret-down"; - - @Output() onRowDblclick: EventEmitter = new EventEmitter(); - - @Output() selectionChange: EventEmitter = new EventEmitter(); - - @Output() onNodeSelect: EventEmitter = new EventEmitter(); - - @Output() onNodeUnselect: EventEmitter = new EventEmitter(); - - @Output() onNodeExpand: EventEmitter = new EventEmitter(); - - @Output() onNodeCollapse: EventEmitter = new EventEmitter(); - - @Output() onContextMenuSelect: EventEmitter = new EventEmitter(); - - @ContentChild(Header) header: Header; - - @ContentChild(Footer) footer: Footer; - - @ContentChildren(Column) cols: QueryList; - - @ViewChild('tbl') tableViewChild: ElementRef; - - public rowTouched: boolean; - - public columns: Column[]; - - columnsSubscription: Subscription; - - constructor (public el: ElementRef, public domHandler: DomHandler,public changeDetector: ChangeDetectorRef,public renderer: Renderer2) {} - - ngAfterContentInit() { - this.initColumns(); - - this.columnsSubscription = this.cols.changes.subscribe(_ => { - this.initColumns(); - this.changeDetector.markForCheck(); - }); - } - - initColumns(): void { - this.columns = this.cols.toArray(); - } - - onRowClick(event: MouseEvent, node: TreeNode) { - let eventTarget = ( event.target); - if(eventTarget.className && eventTarget.className.indexOf('ui-treetable-toggler') === 0) { - return; - } - else if(this.selectionMode) { - if(node.selectable === false) { - return; - } - - let metaSelection = this.rowTouched ? false : this.metaKeySelection; - let index = this.findIndexInSelection(node); - let selected = (index >= 0); - - if(this.isCheckboxSelectionMode()) { - if(selected) { - this.propagateSelectionDown(node, false); - if(node.parent) { - this.propagateSelectionUp(node.parent, false); - } - this.selectionChange.emit(this.selection); - this.onNodeUnselect.emit({originalEvent: event, node: node}); - } - else { - this.propagateSelectionDown(node, true); - if(node.parent) { - this.propagateSelectionUp(node.parent, true); - } - this.selectionChange.emit(this.selection); - this.onNodeSelect.emit({originalEvent: event, node: node}); - } - } - else { - if(metaSelection) { - let metaKey = (event.metaKey||event.ctrlKey); - - if(selected && metaKey) { - if(this.isSingleSelectionMode()) { - this.selectionChange.emit(null); - } - else { - this.selection = this.selection.filter((val,i) => i!=index); - this.selectionChange.emit(this.selection); - } - - this.onNodeUnselect.emit({originalEvent: event, node: node}); - } - else { - if(this.isSingleSelectionMode()) { - this.selectionChange.emit(node); - } - else if(this.isMultipleSelectionMode()) { - this.selection = (!metaKey) ? [] : this.selection||[]; - this.selection = [...this.selection,node]; - this.selectionChange.emit(this.selection); - } - - this.onNodeSelect.emit({originalEvent: event, node: node}); - } - } - else { - if(this.isSingleSelectionMode()) { - if(selected) { - this.selection = null; - this.onNodeUnselect.emit({originalEvent: event, node: node}); - } - else { - this.selection = node; - this.onNodeSelect.emit({originalEvent: event, node: node}); - } - } - else { - if(selected) { - this.selection = this.selection.filter((val,i) => i!=index); - this.onNodeUnselect.emit({originalEvent: event, node: node}); - } - else { - this.selection = [...this.selection||[],node]; - this.onNodeSelect.emit({originalEvent: event, node: node}); - } - } - - this.selectionChange.emit(this.selection); - } - } - } - - this.rowTouched = false; - } - - onRowTouchEnd() { - this.rowTouched = true; - } - - onRowRightClick(event: MouseEvent, node: TreeNode) { - if(this.contextMenu) { - let index = this.findIndexInSelection(node); - let selected = (index >= 0); - - if(!selected) { - if(this.isSingleSelectionMode()) { - this.selection = node; - } - else if(this.isMultipleSelectionMode()) { - this.selection = [node]; - this.selectionChange.emit(this.selection); - } - - this.selectionChange.emit(this.selection); - } - - this.contextMenu.show(event); - this.onContextMenuSelect.emit({originalEvent: event, node: node}); - } - } - - findIndexInSelection(node: TreeNode) { - let index: number = -1; - - if(this.selectionMode && this.selection) { - if(this.isSingleSelectionMode()) { - index = (this.selection == node) ? 0 : - 1; - } - else { - for(let i = 0; i < this.selection.length; i++) { - if(this.selection[i] == node) { - index = i; - break; - } - } - } - } - - return index; - } - - propagateSelectionUp(node: TreeNode, select: boolean) { - if(node.children && node.children.length) { - let selectedCount: number = 0; - let childPartialSelected: boolean = false; - for(let child of node.children) { - if(this.isSelected(child)) { - selectedCount++; - } - else if(child.partialSelected) { - childPartialSelected = true; - } - } - - if(select && selectedCount == node.children.length) { - this.selection = [...this.selection||[],node]; - node.partialSelected = false; - } - else { - if(!select) { - let index = this.findIndexInSelection(node); - if(index >= 0) { - this.selection = this.selection.filter((val,i) => i!=index); - } - } - - if(childPartialSelected || selectedCount > 0 && selectedCount != node.children.length) - node.partialSelected = true; - else - node.partialSelected = false; - } - } - - let parent = node.parent; - if(parent) { - this.propagateSelectionUp(parent, select); - } - } - - propagateSelectionDown(node: TreeNode, select: boolean) { - let index = this.findIndexInSelection(node); - - if(select && index == -1) { - this.selection = [...this.selection||[],node]; - } - else if(!select && index > -1) { - this.selection = this.selection.filter((val,i) => i!=index); - } - - node.partialSelected = false; - - if(node.children && node.children.length) { - for(let child of node.children) { - this.propagateSelectionDown(child, select); - } - } - } - - isSelected(node: TreeNode) { - return this.findIndexInSelection(node) != -1; - } - - isSingleSelectionMode() { - return this.selectionMode && this.selectionMode == 'single'; - } - - isMultipleSelectionMode() { - return this.selectionMode && this.selectionMode == 'multiple'; - } - - isCheckboxSelectionMode() { - return this.selectionMode && this.selectionMode == 'checkbox'; - } - - hasFooter() { - if(this.columns) { - let columnsArr = this.cols.toArray(); - for(let i = 0; i < columnsArr.length; i++) { - if(columnsArr[i].footer) { - return true; - } - } - } - return false; - } -} - -@NgModule({ - imports: [CommonModule], - exports: [TreeTable,SharedModule], - declarations: [TreeTable,UITreeRow] -}) -export class TreeTableModule { } \ No newline at end of file diff --git a/dashboard/src/app/components/tristatecheckbox/tristatecheckbox.spec.ts b/dashboard/src/app/components/tristatecheckbox/tristatecheckbox.spec.ts deleted file mode 100644 index 48562f49c..000000000 --- a/dashboard/src/app/components/tristatecheckbox/tristatecheckbox.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { TriStateCheckbox } from './tristatecheckbox'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; - -describe('TriStateCheckbox', () => { - - let tristate: TriStateCheckbox; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule - ], - declarations: [ - TriStateCheckbox - ] - }); - - fixture = TestBed.createComponent(TriStateCheckbox); - tristate = fixture.componentInstance; - }); -}); diff --git a/dashboard/src/app/components/tristatecheckbox/tristatecheckbox.ts b/dashboard/src/app/components/tristatecheckbox/tristatecheckbox.ts deleted file mode 100644 index a767d4fa6..000000000 --- a/dashboard/src/app/components/tristatecheckbox/tristatecheckbox.ts +++ /dev/null @@ -1,125 +0,0 @@ -import {NgModule,Component,Input,Output,EventEmitter,forwardRef,ChangeDetectorRef} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms'; - -export const TRISTATECHECKBOX_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TriStateCheckbox), - multi: true -}; - -@Component({ - selector: 'p-triStateCheckbox', - template: ` -
        -
        - -
        -
        - -
        -
        - - `, - providers: [TRISTATECHECKBOX_VALUE_ACCESSOR] -}) -export class TriStateCheckbox implements ControlValueAccessor { - - constructor(private cd: ChangeDetectorRef) {} - - @Input() disabled: boolean; - - @Input() name: string; - - @Input() tabindex: number; - - @Input() inputId: string; - - @Input() style: any; - - @Input() styleClass: string; - - @Input() label: string; - - @Output() onChange: EventEmitter = new EventEmitter(); - - focus: boolean; - - value: any; - - onModelChange: Function = () => {}; - - onModelTouched: Function = () => {}; - - onClick(event: Event, input: HTMLInputElement) { - if(!this.disabled) { - this.toggle(event); - this.focus = true; - input.focus(); - } - } - - onKeydown(event: KeyboardEvent) { - if(event.keyCode == 32) { - event.preventDefault(); - } - } - - onKeyup(event: KeyboardEvent) { - if(event.keyCode == 32) { - this.toggle(event); - event.preventDefault(); - } - } - - toggle(event: Event) { - if(this.value == null || this.value == undefined) - this.value = true; - else if(this.value == true) - this.value = false; - else if(this.value == false) - this.value = null; - - this.onModelChange(this.value); - this.onChange.emit({ - originalEvent: event, - value: this.value - }) - } - - onFocus() { - this.focus = true; - } - - onBlur() { - this.focus = false; - this.onModelTouched(); - } - - registerOnChange(fn: Function): void { - this.onModelChange = fn; - } - - registerOnTouched(fn: Function): void { - this.onModelTouched = fn; - } - - writeValue(value: any) : void { - this.value = value; - this.cd.markForCheck(); - } - - setDisabledState(disabled: boolean): void { - this.disabled = disabled; - } -} - -@NgModule({ - imports: [CommonModule], - exports: [TriStateCheckbox], - declarations: [TriStateCheckbox] -}) -export class TriStateCheckboxModule { } diff --git a/dashboard/src/app/components/utils/objectutils.spec.ts b/dashboard/src/app/components/utils/objectutils.spec.ts deleted file mode 100644 index efb2aacfa..000000000 --- a/dashboard/src/app/components/utils/objectutils.spec.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { ObjectUtils } from './objectutils'; -import { inject, TestBed } from '@angular/core/testing'; - -describe('ObjectUtils Suite', () => { - - let objectUtils: ObjectUtils = null; - - beforeEach(() => TestBed.configureTestingModule({ - providers: [ ObjectUtils ] - })); - - beforeEach(inject([ObjectUtils], s => { - objectUtils = s; - })); - - let data: any = [ - {brand: "VW", year: 2012, color: {name:"Orange"}, vin: "dsad231ff"}, - {brand: "Audi", year: 2011, color: {name:"Black"}, vin: "gwregre345"}, - {brand: "Renault", year: 2005, color: {name:"Black"}, vin: "h354htr"}, - {brand: "BMW", year: 2003, color: {name:"Blue"}, vin: "j6w54qgh"}, - {brand: "Mercedes", year: 1995, color: {name:"Red"}, vin: "hrtwy34"}, - {brand: "Volvo", year: 2005, color: {name:"Orange"}, vin: "jejtyj"}, - {brand: "Honda", year: 2012, color: {name:"Blue"}, vin: "g43gr"}, - {brand: "Jaguar", year: 2013,color: {name:"Black"}, vin: "greg34"}, - {brand: "Ford", year: 2000, color: {name:"White"}, vin: "h54hw5"}, - {brand: "Fiat", year: 2013, color: {name:"Yellow"}, vin: "245t2s"} - ]; - - it('Should resolve field data', () => { - let obj = { - firstname: 'Silvio', - lastname: 'Andolini', - address: { - country: { - name: 'Italy' - }, - city: 'Corleone' - } - } - - expect(objectUtils.resolveFieldData(obj, 'firstname')).toBe('Silvio'); - expect(objectUtils.resolveFieldData(obj, 'lastname')).toBe('Andolini'); - expect(objectUtils.resolveFieldData(obj, 'address.city')).toBe('Corleone'); - expect(objectUtils.resolveFieldData(obj, 'address.country.name')).toBe('Italy'); - expect(objectUtils.resolveFieldData(obj, 'age')).toBeUndefined(); - }); - - it('Should run single field correctly', () => { - let result = objectUtils.filter(data, ['brand'], 'b'); - expect(result[0].brand).toBe('BMW'); - }); - - it('Should run multiple filter correctly', () => { - let result = objectUtils.filter(data, ['brand','color.name'], 'w'); - expect(result[0].brand).toBe('VW'); - expect(result[1].brand).toBe('BMW'); - expect(result[2].brand).toBe('Ford'); - }); - - it('Should relocate an item in array', () => { - let arr: string[] = ['New York', 'Istanbul', 'Paris', 'Barcelona', 'London']; - objectUtils.reorderArray(arr, 3, 1); - expect(arr).toEqual(['New York', 'Barcelona', 'Istanbul', 'Paris', 'London']); - }); - - it('Should inject an item as indexed', () => { - let sourceArr: string[] = ['New York', 'Istanbul', 'Paris', 'Barcelona', 'London']; - let arr: string[] = []; - - objectUtils.insertIntoOrderedArray('Istanbul', 1, arr, sourceArr); - expect(arr).toEqual(['Istanbul']); - - objectUtils.insertIntoOrderedArray('Paris', 2, arr, sourceArr); - objectUtils.insertIntoOrderedArray('New York', 0, arr, sourceArr); - objectUtils.insertIntoOrderedArray('London', 4, arr, sourceArr); - objectUtils.insertIntoOrderedArray('Barcelona', 3, arr, sourceArr); - expect(arr).toEqual(['New York', 'Istanbul', 'Paris', 'Barcelona', 'London']); - }); - - it('Should check if simple objects are equal', () => { - const [data0, data1] = data.slice(0, 2); - expect(objectUtils.equals(data0, data0)).toBe(true); - expect(objectUtils.equals(data0, Object.assign({}, data0))).toBe(true); - expect(objectUtils.equals(data0, data1)).toBe(false); - }); - - it('Should check if nested objects are equal', () => { - const arr = [1, 2, [3, 4]]; - expect(objectUtils.equals(arr, Object.assign({}, arr))).toBe(true); - const arr2 = [1, 2, [3, 4, 5]]; - expect(objectUtils.equals(arr, arr2)).toBe(false); - const obj = {a: 1, b: {c: 3, d: 4}}; - expect(objectUtils.equals(obj, Object.assign({}, obj))).toBe(true); - const obj2 = {a: 1, b: {c: 3, d: 5}}; - expect(objectUtils.equals(obj, obj2)).toBe(false); - }); - - it('Should not cause stack overflow comparing recursive objects', () => { - const obj1 = {p: null}; - const obj2 = {p: null}; - obj1['p'] = obj1; - obj2['p'] = obj2; - expect(objectUtils.equals(obj1, obj2)).toBe(false); - }); - - it('Should be able to compare frozen nested objects', () => { - const obj1 = {a: 1, b: {c: 3, d: 4}}; - const obj2 = {a: 1, b: {c: 3, d: 4}}; - Object.preventExtensions(obj1); - Object.preventExtensions(obj2); - expect(objectUtils.equals(obj1, obj2)).toBe(true); - }); - -}); diff --git a/dashboard/src/app/components/utils/objectutils.ts b/dashboard/src/app/components/utils/objectutils.ts deleted file mode 100644 index 3f08d9125..000000000 --- a/dashboard/src/app/components/utils/objectutils.ts +++ /dev/null @@ -1,164 +0,0 @@ -import {Injectable} from '@angular/core'; -import {SelectItem} from '../common/selectitem'; - -@Injectable() -export class ObjectUtils { - - public equals(obj1: any, obj2: any, field?: string): boolean { - if (field) - return (this.resolveFieldData(obj1, field) === this.resolveFieldData(obj2, field)); - else - return this.equalsByValue(obj1, obj2); - } - - public equalsByValue(obj1: any, obj2: any, visited?: any[]): boolean { - if (obj1 == null && obj2 == null) { - return true; - } - if (obj1 == null || obj2 == null) { - return false; - } - - if (obj1 == obj2) { - return true; - } - - if (typeof obj1 == 'object' && typeof obj2 == 'object') { - if (visited) { - if (visited.indexOf(obj1) !== -1) return false; - } else { - visited = []; - } - visited.push(obj1); - - for (var p in obj1) { - if (obj1.hasOwnProperty(p) !== obj2.hasOwnProperty(p)) { - return false; - } - - switch (typeof (obj1[p])) { - case 'object': - if (!this.equalsByValue(obj1[p], obj2[p], visited)) return false; - break; - - case 'function': - if (typeof (obj2[p]) == 'undefined' || (p != 'compare' && obj1[p].toString() != obj2[p].toString())) return false; - break; - - default: - if (obj1[p] != obj2[p]) return false; - break; - } - } - - for (var p in obj2) { - if (typeof (obj1[p]) == 'undefined') return false; - } - - delete obj1._$visited; - return true; - } - - return false; - } - - resolveFieldData(data: any, field: string): any { - if(data && field) { - if(field.indexOf('.') == -1) { - return data[field]; - } - else { - let fields: string[] = field.split('.'); - let value = data; - for(var i = 0, len = fields.length; i < len; ++i) { - if (value == null) { - return null; - } - value = value[fields[i]]; - } - return value; - } - } - else { - return null; - } - } - - filter(value: any[], fields: any[], filterValue: string) { - let filteredItems: any[] = []; - - if(value) { - for(let item of value) { - for(let field of fields) { - if(String(this.resolveFieldData(item, field)).toLowerCase().indexOf(filterValue.toLowerCase()) > -1) { - filteredItems.push(item); - break; - } - } - } - } - - return filteredItems; - } - - reorderArray(value: any[], from: number, to: number) { - let target: number; - if(value && (from !== to)) { - if(to >= value.length) { - target = to - value.length; - while((target--) + 1) { - value.push(undefined); - } - } - value.splice(to, 0, value.splice(from, 1)[0]); - } - } - - generateSelectItems(val: any[], field: string): SelectItem[] { - let selectItems: SelectItem[]; - if(val && val.length) { - selectItems = []; - for(let item of val) { - selectItems.push({label: this.resolveFieldData(item, field), value: item}); - } - } - - return selectItems; - } - - insertIntoOrderedArray(item: any, index: number, arr: any[], sourceArr: any[]): void { - if(arr.length > 0) { - let injected = false; - for(let i = 0; i < arr.length; i++) { - let currentItemIndex = this.findIndexInList(arr[i], sourceArr); - if(currentItemIndex > index) { - arr.splice(i, 0, item); - injected = true; - break; - } - } - - if(!injected) { - arr.push(item); - } - } - else { - arr.push(item); - } - } - - findIndexInList(item: any, list: any): number { - let index: number = -1; - - if(list) { - for(let i = 0; i < list.length; i++) { - if(list[i] == item) { - index = i; - break; - } - } - } - - return index; - } -} diff --git a/dashboard/src/app/i18n/en/exception.json b/dashboard/src/app/i18n/en/exception.json deleted file mode 100644 index 40b9cdf15..000000000 --- a/dashboard/src/app/i18n/en/exception.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "timeout":"请求超时", - "system_error":"系统内部错误" -} \ No newline at end of file diff --git a/dashboard/src/app/i18n/en/keyID.json b/dashboard/src/app/i18n/en/keyID.json deleted file mode 100644 index 6b22c18a5..000000000 --- a/dashboard/src/app/i18n/en/keyID.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "sds_required":"{0} is required.", - "sds_pattern":"Beginning with a letter with a length of 1-128, it can contain letters / numbers / underlines.", - "sds_profileNull":"profile is required", - "sds_block_volumes_descrip":"View and manage resources that have been manually created or applied for through service templates.", - "sds_block_volumesGroup_descrip":"View and manage resources that have been manually created or applied for through service templates.", - "sds_home_tenants":"Tenants", - "sds_home_users":"Users", - "sds_home_volumes":"Volumes", - "sds_home_snapshots":"Volume Snapshots", - "sds_home_replications":"Volume Replications", - "sds_home_pools":"Storage Pools", - "sds_home_storages":"Block Storages", - "sds_home_overvew":"Overview", - "sds_home_update":"Updated 5 minutes ago", - "sds_home_capacity":"Capacity", - "sds_home_block_capacity":"Block Storage Capacity", - "sds_home_top5":"Top 5 Allocated Capacity by Block Profile", - "sds_home_used_capacity":"Used Capacity", - "sds_home_free_capacity":"Free Capacity", - "sds_block_volume_name":"Name", - "sds_block_volume_status":"Status", - "sds_block_volume_profile":"Profile", - "sds_block_volume_az":"Availability Zone", - "sds_block_volume_operation":"Operation", - "sds_block_volume_title":"Volume", - "sds_block_volume_grouptitle":"Volume Group", - "sds_block_volume_createsna":"Create Snapshot", - "sds_block_volume_createrep":"Create Replication", - "sds_block_volume_more":"More", - "sds_block_volume_modify":"Modify", - "sds_block_volume_expand":"Expand", - "sds_block_volume_delete":"Delete", - "sds_block_volume_create":"Create", - "sds_block_volume_search":"search", - "sds_block_volume_createVol":"Create Volume", - "sds_block_volume_createVol_desc":"Apply for block storage resources.", - "sds_block_volume_quantity":"Quantity", - "sds_block_volume_addvolu":"Add Volumes", - "sds_block_volume_selectpro":"Select Profile", - "sds_block_volume_conf_rep":"Configuration replication now", - "sds_block_volume_detail":"Volume detail", - "sds_block_volume_id":"Volume ID", - "sds_block_volume_createat":"Created At", - "sds_block_volume_snapshot":"Snapshot", - "sds_block_volume_replication":"Replication", - "sds_block_volume_descri":"Description", - "sds_block_volume_del_sna":"Delete Snapshots", - "sds_block_volume_curr_capa":"Current Capacity", - "sds_block_volume_expandby":"Expand Capacity By", - "sds_block_volume_totalcapa":"Total Capacity After Expansion", - "sds_block_volume_deleVolu":"Delete Volume", - "sds_block_volume_source":"The volume is created by snapshot( id: {{}} ).", - "sds_resource_region_default":"default_region", - "sds_profile_create_name_require":"name is required.", - "sds_block_volume_replication_disable":"Disable", - "sds_block_volume_replication_failover":"Failover", - "sds_profile_list_descrip":"A profile is a set of configurations on service capabilities (including resource tuning, QoS) of storage resources. A profile must be specified when volume is created.", - "sds_profile_create_title":"Create Profile", - "sds_profile_create_descrip":"Create profile to suit your specific use requirements.", - "sds_profile_access_pro":"Access Protocol", - "sds_profile_pro_type":"Provisioning Type", - "sds_profile_qos_policy":"QoS Policy", - "sds_profile_replication_policy":"Replication Policy", - "sds_profile_snap_policy":"Snapshot Policy", - "sds_profile_create_customization":"Customization", - "sds_profile_avai_pool":"Available Storage Pool", - "sds_profile_extra_key":"Key", - "sds_profile_extra_value":"Value", - "sds_profile_create_maxIOPS":"MaxIOPS", - "sds_profile_create_maxBWS":"MaxBWS", - "sds_profile_rep_type":"Type", - "sds_profile_rep_rgo":"RGO", - "sds_profile_rep_mode":"Mode", - "sds_profile_rep_rto":"RTO", - "sds_profile_rep_period":"Period", - "sds_profile_rep_rpo":"RPO", - "sds_profile_rep_bandwidth":"Bandwidth", - "sds_profile_rep_consis":"Consistency", - "sds_profile_snap_sche":"Schedule", - "sds_profile_snap_exetime":"Execution Time", - "sds_profile_snap_reten":"Retention", - "sds_profile_IOPS_unit":"IOPS/TB", - "sds_profile_BWS_unit":"MBPS/TB", - "sds_profile_unit_minutes":"Minutes", - "sds_profile_enable":"Enable", - "sds_profile_nuit_days":"Days", - "sds_profile_extra_add":"Add", - "sds_profile_pool_match":"Matching", - "sds_resource_region":"Region", - "sds_resource_storage":"Storage", - "sds_resource_region_role":"Region Role", - "sds_resource_storage_ip":"IP Address", - "sds_identity_tenant":"Tenant", - "sds_identity_user":"User", - "sds_identity_tenant_descrip":"A tenant is used to group and manage resources and users.", - "sds_identity_res_usage":"Resource Usage", - "sds_identity_tenant_cap":"Storage Capacity", - "sds_identity_tenant_manage":"User Management", - "sds_identity_tenant_add":"Add User", - "sds_block_volume_group_id":"Group ID", - "sds_block_volume_group_detail":"Volume Group detail", - "sds_block_volume_group_router":"Volume Group", - "sds_validate_max_length":"The maximum length is 200.", - "sds_block_volume_group_create_group":"Create Volume Group", - "sds_block_volume_rep_pair":"Replication Pair", - "sds_block_volume_base_info":"Basic Information", - "sds_block_volume_group_remove":"Remove", - "sds_block_volume_group_modify_group":"Modify Volume Group", - "sds_identity_user_name":"Username", - "sds_login_error_msg_401":"Incorrect username or password!", - "sds_login_error_msg_503":"Service Unavailable!", - "sds_login_error_msg_default":"Internal Server Error!" - - - -} diff --git a/dashboard/src/app/i18n/en/widgetsKeyID.json b/dashboard/src/app/i18n/en/widgetsKeyID.json deleted file mode 100644 index b1a30c60e..000000000 --- a/dashboard/src/app/i18n/en/widgetsKeyID.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "ok": "OK", - "close": "Close", - "cancel": "Cancel", - "confirm": "Confirm", - "warn": "警告", - "tip": "Information", - "success": "Success", - "error": "Error", - "emptyTable": "无数据", - "emptyData": "无数据", - "totalRecords": "总条数", - "goto": "跳转" - -} diff --git a/dashboard/src/app/i18n/zh/exception.json b/dashboard/src/app/i18n/zh/exception.json deleted file mode 100644 index 40b9cdf15..000000000 --- a/dashboard/src/app/i18n/zh/exception.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "timeout":"请求超时", - "system_error":"系统内部错误" -} \ No newline at end of file diff --git a/dashboard/src/app/i18n/zh/keyID.json b/dashboard/src/app/i18n/zh/keyID.json deleted file mode 100644 index 7171a5419..000000000 --- a/dashboard/src/app/i18n/zh/keyID.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "sds_required":"{0} is required.", - "sds_pattern":"Beginning with a letter with a length of 1-128, it can contain letters / numbers / underlines.", - "sds_profileNull":"profile is required", - "sds_block_volumes_descrip":"View and manage resources that have been manually created or applied for through service templates.", - "sds_block_volumesGroup_descrip":"View and manage resources that have been manually created or applied for through service templates.", - "sds_home_tenants":"Tenants", - "sds_home_users":"Users", - "sds_home_volumes":"Volumes", - "sds_home_snapshots":"Volume Snapshots", - "sds_home_replications":"Volume Replications", - "sds_home_pools":"Storage Pools", - "sds_home_storages":"Block Storages", - "sds_home_overvew":"Overview", - "sds_home_update":"Updated 5 minutes ago", - "sds_home_capacity":"Capacity", - "sds_home_block_capacity":"Block Storage Capacity", - "sds_home_top5":"Top 5 Allocated Capacity by Block Profile", - "sds_home_used_capacity":"Used Capacity", - "sds_home_free_capacity":"Free Capacity", - "sds_block_volume_name":"Name", - "sds_block_volume_status":"Status", - "sds_block_volume_profile":"Profile", - "sds_block_volume_az":"Availability Zone", - "sds_block_volume_operation":"Operation", - "sds_block_volume_title":"Volume", - "sds_block_volume_grouptitle":"Volume Group", - "sds_block_volume_createsna":"Create Snapshot", - "sds_block_volume_createrep":"Create Replication", - "sds_block_volume_more":"More", - "sds_block_volume_modify":"Modify", - "sds_block_volume_expand":"Expand", - "sds_block_volume_delete":"Delete", - "sds_block_volume_create":"Create", - "sds_block_volume_search":"search", - "sds_block_volume_createVol":"Create Volume", - "sds_block_volume_createVol_desc":"Apply for block storage resources.", - "sds_block_volume_quantity":"Quantity", - "sds_block_volume_addvolu":"Add Volumes", - "sds_block_volume_selectpro":"Select Profile", - "sds_block_volume_conf_rep":"Configuration replication now", - "sds_block_volume_detail":"Volume detail", - "sds_block_volume_id":"Volume ID", - "sds_block_volume_createat":"Created At", - "sds_block_volume_snapshot":"Snapshot", - "sds_block_volume_replication":"Replication", - "sds_block_volume_descri":"Description", - "sds_block_volume_del_sna":"Delete Snapshots", - "sds_block_volume_curr_capa":"Current Capacity", - "sds_block_volume_expandby":"Expand Capacity By", - "sds_block_volume_totalcapa":"Total Capacity After Expansion", - "sds_block_volume_deleVolu":"Delete Volume", - "sds_block_volume_source":"The volume is created by snapshot( id: {{}} ).", - "sds_resource_region_default":"default_region", - "sds_profile_create_name_require":"name is required.", - "sds_block_volume_replication_disable":"Disable", - "sds_block_volume_replication_failover":"Failover", - "sds_profile_list_descrip":"A profile is a set of configurations on service capabilities (including resource tuning, QoS) of storage resources. A profile must be specified when volume is created.", - "sds_profile_create_title":"Create Profile", - "sds_profile_create_descrip":"Create profile to suit your specific use requirements.", - "sds_profile_access_pro":"Access Protocol", - "sds_profile_pro_type":"Provisioning Type", - "sds_profile_qos_policy":"QoS Policy", - "sds_profile_replication_policy":"Replication Policy", - "sds_profile_snap_policy":"Snapshot Policy", - "sds_profile_create_customization":"Customization", - "sds_profile_avai_pool":"Available Storage Pool", - "sds_profile_extra_key":"Key", - "sds_profile_extra_value":"Value", - "sds_profile_create_maxIOPS":"MaxIOPS", - "sds_profile_create_maxBWS":"MaxBWS", - "sds_profile_rep_type":"Type", - "sds_profile_rep_rgo":"RGO", - "sds_profile_rep_mode":"Mode", - "sds_profile_rep_rto":"RTO", - "sds_profile_rep_period":"Period", - "sds_profile_rep_rpo":"RPO", - "sds_profile_rep_bandwidth":"Bandwidth", - "sds_profile_rep_consis":"Consistency", - "sds_profile_snap_sche":"Schedule", - "sds_profile_snap_exetime":"Execution Time", - "sds_profile_snap_reten":"Retention", - "sds_profile_IOPS_unit":"IOPS/TB", - "sds_profile_BWS_unit":"MBPS/TB", - "sds_profile_unit_minutes":"Minutes", - "sds_profile_enable":"Enable", - "sds_profile_nuit_days":"Days", - "sds_profile_extra_add":"Add", - "sds_profile_pool_match":"Matching", - "sds_resource_region":"Region", - "sds_resource_storage":"Storage", - "sds_resource_region_role":"Region Role", - "sds_resource_storage_ip":"IP Address", - "sds_identity_tenant":"Tenant", - "sds_identity_user":"User", - "sds_identity_tenant_descrip":"A tenant is used to group and manage resources and users.", - "sds_identity_res_usage":"Resource Usage", - "sds_identity_tenant_cap":"Storage Capacity", - "sds_identity_tenant_manage":"User Management", - "sds_identity_tenant_add":"Add User", - "sds_block_volume_group_id":"Group ID", - "sds_block_volume_group_detail":"Volume Group detail", - "sds_block_volume_group_router":"Volume Group", - "sds_validate_max_length":"The maximum length is 200.", - "sds_block_volume_group_create_group":"Create Volume Group", - "sds_block_volume_rep_pair":"Replication Pair", - "sds_block_volume_base_info":"Basic Information", - "sds_block_volume_group_remove":"Remove", - "sds_block_volume_group_modify_group":"Modify Volume Group", - "sds_identity_user_name":"Username", - "sds_login_error_msg_401":"Incorrect username or password!", - "sds_login_error_msg_503":"Service Unavailable!", - "sds_login_error_msg_default":"Internal Server Error!" - - - -} diff --git a/dashboard/src/app/i18n/zh/widgetsKeyID.json b/dashboard/src/app/i18n/zh/widgetsKeyID.json deleted file mode 100644 index a28f02914..000000000 --- a/dashboard/src/app/i18n/zh/widgetsKeyID.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "ok": "OK", - "close": "关闭", - "cancel": "Cancel", - "confirm": "确认", - "warn": "警告", - "tip": "提示", - "success": "成功", - "error": "錯誤", - "emptyTable": "无数据", - "emptyData": "无数据", - "totalRecords": "总条数", - "goto": "跳转" - -} diff --git a/dashboard/src/app/shared/api.ts b/dashboard/src/app/shared/api.ts deleted file mode 100644 index 3589a5eb2..000000000 --- a/dashboard/src/app/shared/api.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from './utils/consts'; -export * from './utils/utils'; -export * from './service/Exception.service'; -export * from './service/Http.service'; -export * from './service/I18N.service'; -export * from './service/MsgBox.service'; -export * from './service/ParamStor.service'; diff --git a/dashboard/src/app/shared/service/Exception.service.ts b/dashboard/src/app/shared/service/Exception.service.ts deleted file mode 100644 index 15b59a784..000000000 --- a/dashboard/src/app/shared/service/Exception.service.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Injectable } from '@angular/core'; -import { I18NService } from './I18N.service'; -import { MsgBoxService } from './MsgBox.service'; - - -@Injectable() -export class ExceptionService { - constructor(private I18N: I18NService, private msgBox: MsgBoxService) {} - - //异常判断 - isException(res){ - return false; - // let isRest = res.url.indexOf('v1') || res.url.indexOf('v3'); - // if (isRest > 0){ - // if(res.text() === "sessionout"){ - // return true; - // } - // let data = res.json(); - // if(data && data.code != 0) { - // return true; - // } - // else{ - // return false; - // } - // } - } - - doException(res){ - // if(res.text() === "sessionout" ) { - // let url = window.location.href; - // let isresource = url.indexOf('siteDistribution'); - // if(isresource > 0 ){ - // parent.postMessage({reload: "reload" }, '*'); - // } - // else{ - // window.location.reload(); - // } - // return; - // } - - // let data = res.json(); - // let code = data.code; - - // if(data && data.code) { - // code = data.code; - // } - // this.msgBox.error(this.I18N.get(code) + ""); - } -} \ No newline at end of file diff --git a/dashboard/src/app/shared/service/Http.service.ts b/dashboard/src/app/shared/service/Http.service.ts deleted file mode 100644 index d15dfd431..000000000 --- a/dashboard/src/app/shared/service/Http.service.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { Http, XHRBackend, RequestOptions, Request, RequestOptionsArgs, Response, Headers, BaseRequestOptions } from '@angular/http'; -import { Injectable, Injector } from '@angular/core'; -import { Observable } from 'rxjs/Observable'; -import { Mask } from '../utils/mask'; -import { BaseRequestOptionsArgs } from './api'; -import { ExceptionService } from './Exception.service'; - -import 'rxjs/add/operator/map'; -import 'rxjs/add/operator/catch'; -import 'rxjs/add/operator/do'; -import 'rxjs/add/operator/finally'; -import 'rxjs/add/operator/timeout'; -import 'rxjs/add/observable/throw'; - -@Injectable() -export class HttpService extends Http { - TIMEOUT = 18000; - - constructor(backend: XHRBackend, defaultOptions: RequestOptions, private injector: Injector) { - super(backend, defaultOptions); - } - - get(url: string, options?: BaseRequestOptionsArgs): Observable{ - [url, options]= this.presetURL(url, options); - return this.intercept(super.get(url, options), options); - } - - post(url: string, body: any, options?: BaseRequestOptionsArgs): Observable{ - [url, options]= this.presetURL(url, options); - return this.intercept(super.post(url, body, options), options); - } - - put(url: string, body: any, options?: BaseRequestOptionsArgs): Observable{ - [url, options]= this.presetURL(url, options); - return this.intercept(super.put(url, body, options), options); - } - - delete(url: string, options?: BaseRequestOptionsArgs): Observable{ - [url, options]= this.presetURL(url, options); - return this.intercept(super.delete(url, options), options); - } - - patch(url: string, body: any, options?: BaseRequestOptionsArgs): Observable{ - [url, options]= this.presetURL(url, options); - return this.intercept(super.patch(url, body, options), options); - } - - head(url: string, options?: BaseRequestOptionsArgs): Observable{ - [url, options]= this.presetURL(url, options); - return this.intercept(super.head(url, options), options); - } - - options(url: string, options?: BaseRequestOptionsArgs): Observable{ - [url, options]= this.presetURL(url, options); - return this.intercept(super.options(url, options), options); - } - - presetURL(url, options){ - // Configure token option - if( localStorage['auth-token'] ){ - !options && (options = {}) - !options.headers && (options['headers'] = new Headers()); - options.headers.set('X-Auth-Token', localStorage['auth-token']); - - } - - // Configure "project_id" for url - if(url.includes('{project_id}')){ - let project_id = localStorage['current-tenant'].split("|")[1]; - url = url.replace('{project_id}',project_id); - - } - - return [url, options]; - } - - intercept(observable: Observable, options = {}): Observable { - let exception = this.injector.get(ExceptionService); - - if(options.mask != false) { - Mask.show(); - } - - return observable.timeout(options.timeout || this.TIMEOUT).do((res: Response) => { - //success - - //fail: Public exception handling - if(exception.isException(res)){ - options.doException !== false && exception.doException(res); - - throw Observable.throw(res); - } - }, (err:any) => { - //fail: Public exception handling - options.doException !== false && exception.doException(err); - }) - .finally(() => { - if( options.mask !==false ){ - Mask.hide(); - } - }) - } -} \ No newline at end of file diff --git a/dashboard/src/app/shared/service/I18N.service.ts b/dashboard/src/app/shared/service/I18N.service.ts deleted file mode 100644 index b083d5aae..000000000 --- a/dashboard/src/app/shared/service/I18N.service.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Injectable } from '@angular/core'; -import { templateJitUrl } from '@angular/compiler'; - -@Injectable() - -export class I18NService { - language = 'en'; - keyID = {}; - - constructor(){ - this.language = this.getCookieLanguage(); - } - - get(key, params = []){ - let str = this.keyID[key] || key; - params.forEach((param, index) => { - str = str.replace('{' + index + '}', param); - }); - return str; - } - - //zh: Chinese en: English - getCookieLanguage() { - this.urlLanguage(); - let cookieStr = document.cookie.split("; "); - let arrLength = cookieStr.length; - for (let i = 0; i 0){ - let tempLanguage = hasUrlLan[1]; - if(tempLanguage == "zh" || tempLanguage == "en"){ - document.cookie = "language=" + tempLanguage + ";domain=.huawei.com;path=/"; - } - } - } -} \ No newline at end of file diff --git a/dashboard/src/app/shared/service/MsgBox.service.ts b/dashboard/src/app/shared/service/MsgBox.service.ts deleted file mode 100644 index 2c34eb5d1..000000000 --- a/dashboard/src/app/shared/service/MsgBox.service.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Injectable, Injector, ApplicationRef, ViewContainerRef, ComponentFactoryResolver } from '@angular/core'; -import { MsgBox } from '../../components/msgbox/msgbox'; -import { I18NService } from './I18N.service'; - -@Injectable() -export class MsgBoxService { - private defaultConfig = { - header: this.I18N.get("tip"), - visible: true, - width: 418, - height: "auto" - } - - constructor( - private componentFactoryResolver: ComponentFactoryResolver, - private applicationRef: ApplicationRef, - private I18N: I18NService, - private injector: Injector - ){} - - open(config){ - this.applicationRef = this.applicationRef || this.injector.get(ApplicationRef); - - if( !this.applicationRef || !this.applicationRef.components[0]){ - alert("System error"); - return; - } - - let viewContainerRef = this.applicationRef.components[0].instance.viewContainerRef; - let componentFactory = this.componentFactoryResolver.resolveComponentFactory(MsgBox); - viewContainerRef.clear(); - let componentRef = viewContainerRef.createComponent(componentFactory); - - if( !config.ok ){ - config.ok = () => config.visible = false; - } - - (componentRef.instance).config = config; - - return config; - } - - info(config = {}){ - if( typeof config == "string"){ - config = { - content: config - } - } - - let _config = { - type: "info", - content: "", - header: this.I18N.get("tip"), - } - - return this.open(Object.assign({}, this.defaultConfig, _config, config)); - } - - success(config = {}){ - if( typeof config == "string"){ - config = { - content: config - } - } - - let _config = { - type: "success", - content: "", - header: this.I18N.get("success") - } - - return this.open(Object.assign({}, this.defaultConfig, _config, config)); - } - - error(config = {}){ - if( typeof config == "string"){ - config = { - content: config - } - } - - let _config = { - type: "error", - content: "", - header: this.I18N.get("error") - } - - return this.open(Object.assign({}, this.defaultConfig, _config, config)); - } - -} \ No newline at end of file diff --git a/dashboard/src/app/shared/service/ParamStor.service.ts b/dashboard/src/app/shared/service/ParamStor.service.ts deleted file mode 100644 index d8c21f7b0..000000000 --- a/dashboard/src/app/shared/service/ParamStor.service.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Injectable } from '@angular/core'; - -@Injectable() -export class ParamStorService { - // Set local storage - setParam(key, value){ - localStorage[key] = value; - } - - // Get local storage - getParam(key){ - return localStorage[key]; - } - - // Current login user - CURRENT_USER(param?){ - if(param === undefined){ - return this.getParam('current-user'); - } else { - this.setParam('current-user', param); - } - } - - // User auth token - AUTH_TOKEN(param?){ - if(param === undefined){ - return this.getParam('auth-token'); - } else { - this.setParam('auth-token', param); - } - } - - // Current login user - CURRENT_TENANT(param?){ - if(param === undefined){ - return this.getParam('current-tenant'); - } else { - this.setParam('current-tenant', param); - } - } - // user password - PASSWORD(param?){ - if(param === undefined){ - return this.getParam('password'); - } else { - this.setParam('password', param); - } - } - // token period - TOKEN_PERIOD(param?){ - if(param === undefined){ - return this.getParam('token_period'); - } else { - this.setParam('token_period', param); - } - } - - -} \ No newline at end of file diff --git a/dashboard/src/app/shared/service/api.ts b/dashboard/src/app/shared/service/api.ts deleted file mode 100644 index 1f1de7792..000000000 --- a/dashboard/src/app/shared/service/api.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { EventEmitter, Injectable } from '@angular/core'; -import { Subject } from 'rxjs/Subject'; -import { Observable } from 'rxjs/Observable'; - -// export{ DomHandler } from '../dom/domhandler'; - -import{ RequestOptionsArgs } from '@angular/http'; - -export interface SortMeta { - -} - -export interface Confirmation { - message: string; - icon?: string; - header?: string; - accept?: Function; - reject?: Function; - acceptVisible?: boolean; - rejectVisible?: boolean; - acceptEvent?: EventEmitter; - rejectEvent?: EventEmitter; -} - -export interface BaseRequestOptionsArgs extends RequestOptionsArgs { - mask?: boolean; - timeout?: number; - doException?: boolean; -} - -@Injectable() -export class ConfirmationService{ - private requireConfirmationSource = new Subject(); - private acceptConfirmationSource = new Subject(); - - requireConfirmation$ = this.requireConfirmationSource.asObservable(); - accept = this.acceptConfirmationSource.asObservable(); - - confirm(confirmation: Confirmation) { - this.requireConfirmationSource.next(confirmation); - return this; - } - - onAccept() { - this.acceptConfirmationSource.next(); - } -} \ No newline at end of file diff --git a/dashboard/src/app/shared/shared.config.ts b/dashboard/src/app/shared/shared.config.ts deleted file mode 100644 index aef9e4e37..000000000 --- a/dashboard/src/app/shared/shared.config.ts +++ /dev/null @@ -1,93 +0,0 @@ -import{ Consts } from 'app/shared/api'; -import{ Http } from '@angular/http'; -import{ I18N } from 'app/components/common/api'; - -var _ = require('underscore'); -export class SharedConfig{ - - //配置入口 - static config( I18NService, injector) { - let httpService = injector.get(Http); - return () => new Promise((resolve, reject) => { - Promise.all([ - SharedConfig.I18NConfig(I18NService, httpService), - // SharedConfig.AutoDeploy(httpService), - ]).then(() => resolve()).catch(reason => console.log(reason)); - }) - } - - //I18N服务配置 - static I18NConfig(I18NService, httpService) { - let p1 = new Promise((resolve, reject) => { - //应用I18N配置 - httpService.get("src/app/i18n/"+ I18NService.language + "/keyID.json").subscribe((r) => { - Object.assign(I18NService.keyID, r.json()); - resolve(); - }) - }) - - let p2 = new Promise((resolve, reject) => { - //异常I18N配置 - httpService.get("src/app/i18n/"+ I18NService.language + "/exception.json").subscribe((r) => { - Object.assign(I18NService.keyID, r.json()); - resolve(); - }) - }) - - let p3 = new Promise((resolve, reject) => { - //控件I18N配置 - httpService.get("src/app/i18n/"+ I18NService.language + "/widgetsKeyID.json").subscribe((r) => { - Object.assign(I18NService.keyID, r.json()); - I18N.language = I18NService.language; - I18N.keyID = I18NService.keyID; - resolve(); - }) - }) - return Promise.all([p1, p2, p3]); - } - - static AutoDeploy(httpService) { - return new Promise((resolve, reject) => { - //读取环境配置url - httpService.get("src/prodconfig/deployConfig.json").subscribe((r) => { - let responseData = r.json; - - Promise.all([ - // SharedConfig.initBaseUser(httpService), - // SharedConfig.initUserRoles(httpService) - ]).then(() => resolve()).catch(reason => console.log(reason)); - }) - }) - } - - //获取用户基本权限 - static initBaseUser(httpService){ - return new Promise((resolve, reject) => { - let request: any = { params: {}}; - request.params.type = "base"; - httpService.get("/v1/...", request).subscribe(response => { - let responseData = response.json().data; - // Consts.CURRENT_USERNAME = responseData.userName; - // Consts.BASE_TENANT = responseData.tenant; - - resolve(); - }) - }) - } - - //获取用户角色信息 - static initUserRoles(httpService){ - return new Promise((resolve, reject) => { - let request: any = { params: {}}; - httpService.get("/v1/...", request).subscribe(response => { - let roles = response.json().data; - // _.each(roles, function(item, i){ - // roles[i] = item.toLowerCase(); - // }) - // Consts.USER_ROLES = roles; - - resolve(); - }) - }) - } -} \ No newline at end of file diff --git a/dashboard/src/app/shared/shared.module.ts b/dashboard/src/app/shared/shared.module.ts deleted file mode 100644 index 1c59f1d2f..000000000 --- a/dashboard/src/app/shared/shared.module.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { NgModule, ModuleWithProviders, APP_INITIALIZER, Injector } from '@angular/core'; -import { FormsModule } from '@angular/forms'; -import { ExceptionService, MsgBoxService, I18NService, HttpService, ParamStorService } from './api'; -import { SharedConfig } from './shared.config'; -import { I18N, MsgBoxModule } from '../components/common/api'; -import { XHRBackend, RequestOptions, Http } from '@angular/http'; - -export function httpFactory(backend: XHRBackend, options: RequestOptions, injector: Injector){ - options.headers.set("contentType", "application/json; charset=UTF-8"); - options.headers.set('Cache-control', 'no-cache'); - options.headers.set('cache-control', 'no-store'); - options.headers.set('expires', '0'); - options.headers.set('Pragma', 'no-cache'); - - return new HttpService(backend, options, injector); -} - -@NgModule({ - imports:[MsgBoxModule], - exports:[FormsModule, MsgBoxModule] -}) - -export class SharedModule { - static forRoot(): ModuleWithProviders { - return { - ngModule: SharedModule, - providers: [ - MsgBoxService, - I18NService, - ParamStorService, - ExceptionService, - { - provide: Http, - useFactory: httpFactory, - deps: [XHRBackend, RequestOptions, Injector] - }, - { - provide: APP_INITIALIZER, - useFactory: SharedConfig.config, - deps: [I18NService, Injector], - multi: true - } - ] - }; - } -} \ No newline at end of file diff --git a/dashboard/src/app/shared/utils/consts.ts b/dashboard/src/app/shared/utils/consts.ts deleted file mode 100644 index 3bea6428c..000000000 --- a/dashboard/src/app/shared/utils/consts.ts +++ /dev/null @@ -1,29 +0,0 @@ -export const Consts = { - /** 不显示的语言 **/ - UNKNOW_PLACEHOLDER: "--", - - /** 百分比显示小数位数 **/ - PRECISION_PERCENT: 2, - - /** 常用日期时间格式 **/ - DATE_FORMAT: "yyyy-MM-dd", - TIME_FORMAT: "hh:mm:ss", - DATETIME_FORMAT: "yyyy-MM-dd hh:mm:ss", - - /** 窗口输入框长度,按照栅格定义控件宽度,数字x标识占x个格子 **/ - W1: 72, - W2: 152, - W3: 232, - W4: 312, - W5: 250, - WSearch: 180, - - - /** 百分比显示小数位数 **/ - - /** 百分比显示小数位数 **/ - - /** 百分比显示小数位数 **/ - - /** 百分比显示小数位数 **/ -} \ No newline at end of file diff --git a/dashboard/src/app/shared/utils/mask.ts b/dashboard/src/app/shared/utils/mask.ts deleted file mode 100644 index df03d4aca..000000000 --- a/dashboard/src/app/shared/utils/mask.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { DOCUMENT } from "@angular/common"; - -export class Mask { - static createBackground = () =>{ - let div = document.createElement('div'); - div.className = 'mask-background'; - return div; - } - - static createLoading= () => { - let div = document.createElement('div'); - div.innerHTML = '

        Loading...

        '; - div.className = "M-loading-content"; - return div; - } - - static background = Mask.createBackground(); - - static loading = Mask.createLoading(); - - static show() { - document.body.appendChild(Mask.loading); - document.body.appendChild(Mask.background); - } - - static hide() { - if( document.body.querySelector('body > .M-loading-content') ){ - document.body.removeChild(Mask.loading); - } - - if( document.body.querySelector('body > .mask-background') ){ - document.body.removeChild(Mask.background); - } - } -} \ No newline at end of file diff --git a/dashboard/src/app/shared/utils/utils.ts b/dashboard/src/app/shared/utils/utils.ts deleted file mode 100644 index 833765eb9..000000000 --- a/dashboard/src/app/shared/utils/utils.ts +++ /dev/null @@ -1,146 +0,0 @@ -export class Utils { - - static capacityUnit = { - KB: "KB", - MB: "MB", - GB: "GB", - TB: "TB", - PB: "PB", - EB: "EB", - BYTE: "BYTE", - BIT: "BIT" - } - - /** - * Formatting data, preserving three decimal (interception) - * ex. 123456.78901 -> 123,456.789 - * - * @param number (input) - * @param decimals (number) - * @param dec_point (Decimal separator) - * @param thousands_sep (Thousandth separators) - * @returns number - */ - static numberFormat(number, decimals=3, dec_point=".", thousands_sep=",", isCeil=false) { - number = (String(number)).replace(/[^0-9+-Ee.]/g, ''); - let n = !isFinite(+number) ? 0 : +number, - prec = !isFinite(+decimals) ? 0 : Math.abs(decimals), - sep = thousands_sep, - dec = dec_point, - s = [], - toFixedFix = function(n, prec, isCeil) { - var k = Math.pow(10, prec); - if (isCeil) { - return String(Math.ceil(n * k) / k); - } else { - return String(Math.floor(n * k) / k); - } - }; - - // Fix for IE parseFloat(0.55).toFixed(0) = 0; - s = (prec ? toFixedFix(n, prec, isCeil) : String(Math.floor(n))).split('.'); - if (s[0].length > 3) { - s[0] = s[0].replace(/\B(?=(?:d{3})+(?!d))/g, sep); - } - if ((s[1] || '').length > prec) { - s[1] = s[1] || ''; - s[1] += new Array(prec - s[1].length + 1).join('0'); - } - if (!(s[1])) { - s[1] = '0'; - } - while ((s[1] || '').length < prec) { - s[1] += '0'; - } - return s.join(dec); - } - - /** - * Returns the capacity value of the adaptive unit for display (with units). - * @param capacity (byte) - * @param decimals (number) - * @param minUnit (string) Minimum unit of capacity after conversion - * @return {[type]} [description] - */ - static getDisplayCapacity(capacity, decimals = 3, minUnit = "GB") { - let ret; - let unit = this.capacityUnit.BYTE; - - if (minUnit == "BYTE" && capacity / 1024 < 1) { - ret = capacity; - } else if ("KB".includes(minUnit) && capacity / (1024 * 1024) < 1) { - ret = capacity / 1024; - unit = this.capacityUnit.KB; - } else if ("KB,MB".includes(minUnit) && capacity / (1024 * 1024 * 1024) < 1) { - ret = capacity / (1024 * 1024); - unit = this.capacityUnit.MB; - } else if ("KB,MB,GB".includes(minUnit) && capacity / (1024 * 1024 * 1024 * 1024) < 1) { - ret = capacity / (1024 * 1024 * 1024); - unit = this.capacityUnit.GB; - } else if ("KB,MB,GB,TB".includes(minUnit) && capacity / (1024 * 1024 * 1024 * 1024 * 1024) < 1) { - ret = capacity / (1024 * 1024 * 1024 * 1024); - unit = this.capacityUnit.TB; - } else if ("KB,MB,GB,TB,PB".includes(minUnit) && capacity / (1024 * 1024 * 1024 * 1024 * 1024 * 1024) < 1) { - ret = capacity / (1024 * 1024 * 1024 * 1024 * 1024); - unit = this.capacityUnit.PB; - } else if ("KB,MB,GB,TB,PB,EB".includes(minUnit) && capacity / (1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024) < 1) { - ret = capacity / (1024 * 1024 * 1024 * 1024 * 1024 * 1024); - unit = this.capacityUnit.EB; - } - - ret = this.numberFormat(ret, decimals); - return ret == 0 ? ret + " " + minUnit : ret + " " + unit; - } - - /** - * Returns the capacity value of the adaptive unit for display (with units). - * @param capacity (GB) - * @param decimals (number) - * @return {[type]} [description] - */ - static getDisplayGBCapacity(capacity, decimals = 3) { - let ret; - let unit = this.capacityUnit.GB; - - if (capacity / 1024 < 1) { - ret = capacity; - } else if (capacity / (1024 * 1024) < 1) { - ret = capacity / 1024; - unit = this.capacityUnit.TB; - } else if (capacity / (1024 * 1024 * 1024) < 1) { - ret = capacity / (1024 * 1024); - unit = this.capacityUnit.PB; - } else if (capacity / (1024 * 1024 * 1024 * 1024) < 1) { - ret = capacity / (1024 * 1024 * 1024); - unit = this.capacityUnit.EB; - } - - ret = this.numberFormat(ret, decimals); - return ret + " " + unit; - } - - /** - * Help get validation information. - * @param control form information - * @param page extra validation information param - * @returns {string} - */ - static getErrorKey(control,page){ - if(control.errors){ - let key = Object.keys(control.errors)[0]; - return page ? "sds_"+ page +key:"sds_"+key; - } - } - /** - * remove one of array element - * @param prevArr origin array - * @param element remove element - * @param func remove methods - */ - static arrayRemoveOneElement(prevArr,element,func){ - let index = prevArr.findIndex(func); - if(index > -1){ - prevArr.splice(index,1); - } - } -} diff --git a/dashboard/src/assets/.gitkeep b/dashboard/src/assets/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/dashboard/src/assets/business/css/primeng.scss b/dashboard/src/assets/business/css/primeng.scss deleted file mode 100644 index 9da63e794..000000000 --- a/dashboard/src/assets/business/css/primeng.scss +++ /dev/null @@ -1,69 +0,0 @@ -@import './app/components/common/common.scss'; -@import './app/components/autocomplete/autocomplete.css'; -@import './app/components/accordion/accordion.css'; -@import './app/components/blockui/blockui.css'; -@import './app/components/breadcrumb/breadcrumb.css'; -@import './app/components/button/button.scss'; -@import './app/components/badge/badge.scss'; -@import './app/components/calendar/calendar.css'; -@import './app/components/card/card.css'; -@import './app/components/carousel/carousel.css'; -@import './app/components/checkbox/checkbox.css'; -@import './app/components/chips/chips.css'; -@import './app/components/colorpicker/colorpicker.css'; -@import './app/components/contextmenu/contextmenu.css'; -@import './app/components/datagrid/datagrid.css'; -@import './app/components/datalist/datalist.css'; -@import './app/components/datascroller/datascroller.css'; -@import './app/components/datatable/datatable.scss'; -@import './app/components/dataview/dataview.css'; -@import './app/components/dialog/dialog.scss'; -@import './app/components/dropdown/dropdown.scss'; -@import './app/components/dropmenu/dropmenu.scss'; -@import './app/components/fieldset/fieldset.css'; -@import './app/components/form/form.scss'; -@import './app/components/fileupload/fileupload.css'; -@import './app/components/galleria/galleria.css'; -@import './app/components/grid/grid.css'; -@import './app/components/growl/growl.css'; -@import './app/components/inplace/inplace.css'; -@import './app/components/inputswitch/inputswitch.css'; -@import './app/components/inputtext/inputtext.scss'; -@import './app/components/inputtextarea/inputtextarea.css'; -@import './app/components/lightbox/lightbox.css'; -@import './app/components/listbox/listbox.css'; -@import './app/components/menu/menu.css'; -@import './app/components/megamenu/megamenu.css'; -@import './app/components/menubar/menubar.css'; -@import './app/components/message/message.css'; -@import './app/components/messages/messages.css'; -@import './app/components/multiselect/multiselect.css'; -@import './app/components/orderlist/orderlist.css'; -@import './app/components/organizationchart/organizationchart.css'; -@import './app/components/overlaypanel/overlaypanel.css'; -@import './app/components/paginator/paginator.scss'; -@import './app/components/panel/panel.css'; -@import './app/components/panelmenu/panelmenu.css'; -@import './app/components/password/password.css'; -@import './app/components/picklist/picklist.css'; -@import './app/components/progressbar/progressbar.css'; -@import './app/components/progressspinner/progressspinner.css'; -@import './app/components/radiobutton/radiobutton.css'; -@import './app/components/schedule/schedule.css'; -@import './app/components/scrollpanel/scrollpanel.css'; -@import './app/components/selectbutton/selectbutton.css'; -@import './app/components/sidebar/sidebar.css'; -@import './app/components/slidemenu/slidemenu.css'; -@import './app/components/slider/slider.css'; -@import './app/components/spinner/spinner.css'; -@import './app/components/splitbutton/splitbutton.css'; -@import './app/components/steps/steps.css'; -@import './app/components/tabmenu/tabmenu.css'; -@import './app/components/tabview/tabview.scss'; -@import './app/components/table/table.css'; -@import './app/components/terminal/terminal.css'; -@import './app/components/tieredmenu/tieredmenu.css'; -@import './app/components/toolbar/toolbar.css'; -@import './app/components/tooltip/tooltip.css'; -@import './app/components/tree/tree.css'; -@import './app/components/treetable/treetable.css'; \ No newline at end of file diff --git a/dashboard/src/assets/business/css/site.scss b/dashboard/src/assets/business/css/site.scss deleted file mode 100644 index 43f6a1ce9..000000000 --- a/dashboard/src/assets/business/css/site.scss +++ /dev/null @@ -1,1563 +0,0 @@ -@charset "UTF-8"; -// @font-face { -// font-family: 'Roboto'; -// font-style: normal; -// font-weight: 400; -// src: url('../fonts/roboto-v15-latin-regular.eot'); -// /* IE9 Compat Modes */ -// src: local('Roboto'), local('Roboto-Regular'), url('../fonts/roboto-v15-latin-regular.eot?#iefix') format('embedded-opentype'), -// /* IE6-IE8 */ -// url('../fonts/roboto-v15-latin-regular.woff2') format('woff2'), -// /* Super Modern Browsers */ -// url('../fonts/roboto-v15-latin-regular.woff') format('woff'), -// /* Modern Browsers */ -// url('../fonts/roboto-v15-latin-regular.ttf') format('truetype'), -// /* Safari, Android, iOS */ -// url('../fonts/roboto-v15-latin-regular.svg#Roboto') format('svg'); -// /* Legacy iOS */ -// } - -/* ----------------------------------------------------------------------------------------------------- */ - -.layout-wrapper { - width: 100%; - height: 100%; -} - - -/* animation login */ - -@keyframes loginHide { - 0% { - width: 2000px; - } - 80% { - width: 320px; - opacity: 1; - } - 100% { - width: 320px; - opacity: 0; - } -} - -@-webkit-keyframes loginHide -/*Safari and Chrome*/ - -{ - 0% { - width: 2000px; - } - 80% { - width: 320px; - opacity: 1; - } - 100% { - width: 320px; - opacity: 0; - } -} - -.login-animation { - animation: loginHide 500ms ease; - -webkit-animation: loginHide 500ms ease; - /* Safari 和 Chrome */ -} - - -/* animation logout */ - -@keyframes loginShow { - 0% { - width: 320px; - opacity: 0; - } - 20% { - width: 320px; - opacity: 1; - } - 100% { - width: 2000px; - opacity: 1; - } -} - -@-webkit-keyframes loginShow -/*Safari and Chrome*/ - -{ - 0% { - width: 320px; - opacity: 0; - } - 20% { - width: 320px; - opacity: 1; - } - 100% { - width: 2000px; - opacity: 1; - } -} - -.logout-animation { - animation: loginShow 500ms ease; - -webkit-animation: loginShow 500ms ease; - /* Safari 和 Chrome */ -} - - -/* login */ - -.layout-wrapper .login-bg { - width: 100%; - height: 100%; - background: url('./assets/business/images/login-bg.png') #242e43 no-repeat center center; - position: absolute; - z-index: 1001; -} - -.layout-wrapper .login-form { - position: absolute; - left: calc(50% - 1.2rem); - top: 20%; - width: 2.4rem; - z-index: 1002; -} - -.login-form .form-list p { - padding-bottom: .2rem; -} - -.layout-wrapper .login-form { - .logo { - height: .75rem; - padding-bottom: .60rem; - background-image: url('./assets/business/images/logo.png'); - background-position: center top; - background-repeat: no-repeat; - } - .ui-button { - padding-left: 0; - padding-right: 0; - } - .ui-inputtext { - background: #303e58; - border: 1px solid #687284; - padding: .1rem .2rem; - color: #e8efff; - @extend .ui-corner-all-large; - } - ::-webkit-input-placeholder { - /* WebKit, Blink, Edge */ - color: #6a7ca0; - } - :-moz-placeholder { - /* Mozilla Firefox 4 to 18 */ - color: #6a7ca0; - opacity: 1; - } - ::-moz-placeholder { - /* Mozilla Firefox 19+ */ - color: #6a7ca0; - opacity: 1; - } - :-ms-input-placeholder { - /* Internet Explorer 10-11 */ - color: #6a7ca0; - } - ::-ms-input-placeholder { - /* Microsoft Edge */ - color: #6a7ca0; - } - .ui-placeholder { - color: #6a7ca0; - } -} - - -/* menu */ - -#layout-topbar { - background-color: #242e43; - background-image: url('./assets/business/images/menu-bg.png'); - background-position: 0 bottom; - background-repeat: no-repeat; - box-sizing: border-box; - display: flex; - flex-direction: column; - justify-content: flex-start; - width: 320px; - height: 100%; - position: fixed; - top: 0; - left: 0; - z-index: 1000; -} - -#layout-topbar .logo { - height: 0.7rem; - flex-shrink: 0; -} - -#layout-topbar .logo a { - display: inline-block; - background-image: url('./assets/business/images/logo-white.png'); - background-repeat: no-repeat; - background-position: center center; - width: 100%; - height: 0.40rem; -} - -#layout-topbar .user-info { - padding: 0.3rem 0.3rem 0.3rem 0.4rem; -} - -#layout-topbar .user-info>div { - display: flex; - justify-content: space-between; -} - -#layout-topbar .user-info>div h1 { - width: 100%; - height: 0.3rem; - color: #cdd3dd; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - -o-text-overflow: ellipsis; - -ms-text-overflow: ellipsis; - -ms-text-overflow: ellipsis; -} - -#layout-topbar .user-info .ui-button { - width: 0.24rem; - color: #54617a; - .fa { - font-size: 0.24rem; - margin-top: -0.12rem; - margin-left: -0.12rem; - width: 0.24rem; - height: 0.24rem; - } - &:hover { - color: map-get($color-primary, hover); - } - &:active { - color: map-get($color-primary, active); - } -} - -#layout-topbar .user-info p { - display: flex; - justify-content: space-between; -} - -#layout-topbar .user-info p span { - display: inline-block; - width: 50%; - height: 0.22rem; - color: #54617a; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - -o-text-overflow: ellipsis; - -ms-text-overflow: ellipsis; - -ms-text-overflow: ellipsis; -} - -#layout-topbar .user-info p span i { - margin-right: 0.05rem; -} - -.topbar-menu { - display: inline-block; - list-style-type: none; - margin: 0.1rem 0 0; - padding: 0 0.3rem 0 0.4rem; - height: 100%; - // overflow: scroll; -} - -.topbar-menu>li:first-of-type { - border-top: 1px solid #323d54; -} - -.topbar-menu>li { - border-bottom: 1px solid #323d54; -} - -.topbar-menu>li>a { - padding: 0.18rem 0; - text-decoration: none; - transition: color .3s; - display: inline-block; - width: 100%; - box-sizing: border-box; - h1 { - color: #cdd3dd; - } - p { - color: #54617a; - font-size: 0.12rem; - } - &:hover { - h1 { - color: #fff; - } - } - &.active-item { - h1 { - color: map-get($color-primary, normal); - text-shadow: 0 2px 10px #074f98; - } - &:hover { - h1 { - color: map-get($color-primary, normal); - } - } - } -} - -#layout-content { - margin-left: 3.20rem; - background-color: #ffffff; - height: 100%; -} - -#layout-content .content-work { - min-height: calc(100% - 0.6rem); - margin: 0 auto; - padding: 0.3rem 0.4rem; -} - -.content-header { - padding: 0 0; - margin-bottom: 0.3rem; -} - -.content-header h1 { - padding-bottom: 0.2rem; - color: map-get($color-title, primary); -} - -.form-con { - padding: 0 0 0.2rem; -} - -.form-con h3 { - margin-bottom: 0.2rem; -} - -.form-btn { - padding: 0 0 0.3rem; -} - -.form-btn button { - float: left; - margin-right: 0.1rem; -} - -.table-toolbar { - display: flex; - display: -webkit-flex; - justify-content: space-between; - align-items: center; - padding-bottom: 0.1rem; -} - -.table-toolbar>div { - display: flex; - align-items: center; - flex-wrap: nowrap; -} - -.table-toolbar>div.left>button { - margin-right: 0.1rem; -} - -.table-toolbar>div.right>button { - margin-left: 0.1rem; -} - -.table-detail-con { - padding: 0.2rem 0.3rem; -} - -.table-detail-con h3 { - margin-bottom: 0.15rem; -} - -.layout-mask { - z-index: 9998; - width: 100%; - height: 100%; - position: fixed; - top: 100px; - left: 0; - display: none; - background-color: #4c5254; - opacity: .7; -} - -.content-section { - display: block; - border-bottom: solid 1px #dde3e6; - padding: 30px; - overflow: hidden; - background-color: #f5f7f8; -} - -.content-section.introduction { - background-image: linear-gradient(to left, #2bc0ec, #1b81d7); - color: #ffffff; -} - -.content-section.introduction a { - color: #ffffff; - font-weight: 700; -} - -.content-section:first-of-type>div>span { - line-height: 1.5em; -} - -.content-section h2 { - margin-top: 0; -} - -.feature-title { - font-size: 30px; - margin-bottom: 20px; - display: block; -} - -#layout-footer { - color: #6d6d81; - height: 0.4rem; - background: #333; - display: flex; - justify-content: center; - align-items: center; -} - -#layout-footer .footer-text { - display: inline-block; - line-height: 0.2rem; - font-size: 0.12rem; -} - - -/* Demos */ - -.implementation { - background-color: #FFFFFF; - overflow: visible; -} - -.implementation>h3 { - margin-top: 30px; - color: #5C666A; -} - -.implementation h3.first { - margin-top: 0px !important; -} - -.implementation h4 { - color: #5C666A; -} - -.content-submenu { - background-image: linear-gradient(to left, #20272a, #20272a); - padding: 15px 30px; - border-bottom: 1px solid #1b81d7; -} - -.content-submenu ul { - margin: 0; - padding: 0; - width: 100%; -} - -.content-submenu ul li { - list-style: none; - width: 20%; - float: left; - margin-top: 5px; -} - -.content-submenu ul li a { - color: #cac6c6; - display: block; - width: 90%; - border: 1px solid transparent; - transition: border-color .1s; - padding: 6px 12px; - border-radius: 3px; -} - -.content-submenu ul li a:hover { - border: 1px solid #ffffff; - color: #ffffff; -} - - -/* Documentation Section */ - -.documentation .ui-tabview-panel { - color: #404C51 !important; -} - -.documentation h3 { - margin-top: 25px; - margin-bottom: 0px; - font-size: 24px; - font-weight: normal; -} - -.documentation h4 { - margin-top: 25px; - margin-bottom: 0px; - font-size: 20px; - font-weight: normal; -} - -.documentation p { - font-size: 16px; - line-height: 24px; - margin: 10px 0; - opacity: .90; -} - -.documentation .doc-tablewrapper { - margin: 10px 0; -} - -.documentation a { - color: #0273D4; -} - -.documentation .btn-viewsource { - background-color: #444444; - padding: .5em; - border-radius: 2px; - color: #ffffff; - font-weight: bold; - margin-bottom: 1em; - display: inline-block; - transition: background-color .3s; -} - -.documentation .btn-viewsource i { - margin-right: .25em; -} - -.documentation .btn-viewsource:hover { - background-color: #595959; -} - - -/* Tabs Source */ - -.documentation .ui-tabview { - background: none; - border: 0 none; - color: #5C666A; - font-weight: lighter; - -moz-border-radius: 4px !important; - -webkit-border-radius: 4px !important; - border-radius: 4px !important; -} - -.documentation .ui-tabview .ui-tabview-nav { - background: #1976D2 !important; - ; - margin-bottom: -1px; - padding: 3px 3px 0px 3px !important; - border-top-right-radius: 4px !important; - border-top-left-radius: 4px !important; - border-bottom-right-radius: 0px; - border-bottom-left-radius: 0px; -} - -.documentation .ui-tabview .ui-tabview-nav li, -.documentation .ui-tabview .ui-tabview-nav li.ui-state-hover { - border: 0px none !important; - background: #3F94E9 !important; - ; - border-color: #3F94E9 !important; - ; - box-shadow: none !important; - border-top-right-radius: 4px !important; - border-top-left-radius: 4px !important; -} - -.documentation .ui-tabview .ui-tabview-nav li a { - padding: .5em 1em !important; -} - -.documentation .ui-tabview .ui-tabview-nav li.tab-doc { - margin-right: 0; -} - -.documentation .ui-tabview .ui-tabview-nav li.ui-state-default a { - color: #fff !important; - font-weight: normal !important; - text-shadow: none; -} - -.documentation .ui-tabview .ui-tabview-nav li.ui-state-active a { - color: #5C666A !important; - font-weight: normal !important; -} - -.documentation .ui-tabview .ui-tabview-nav li.ui-state-hover { - box-shadow: none !important; - ; -} - -.documentation .ui-tabview .ui-tabview-nav li.ui-tabview-selected { - background: #F5F6F7 !important; -} - -.documentation .ui-tabview .ui-tabview-panels { - border-top: 1px solid #F5F6F7 !important; - ; - color: #5C666A !important; - background: #F5F6F7; -} - -.documentation .ui-tabview.ui-tabview-top>.ui-tabview-nav li { - top: 0px !important; -} - - -/* Docs Table */ - -.doc-table { - border-collapse: collapse; - width: 100%; -} - -.doc-table th { - background-color: #dae8ef; - color: #404C51; - border: solid 1px #C1D5DF; - padding: 5px; - font-size: 16px; - text-align: left; -} - -.doc-table tbody td { - color: #404C51; - padding: 4px 10px; - border: 1px solid #E5EBF0; - font-size: 15px; - opacity: .90; -} - -.doc-table tbody tr:nth-child(even) { - background-color: #FBFCFD; -} - -.doc-table tbody tr:nth-child(odd) { - background-color: #F3F6F9; -} - -@media screen and (max-width: 64em) { - .layout-mask { - display: block; - } - #layout-topbar { - text-align: center; - } - #layout-topbar .menu-button { - display: inline-block; - } - #layout-topbar .logo { - margin: 7px 0 7px 0; - } - .topbar-menu { - background-color: #363c3f; - float: none; - width: 100%; - height: 40px; - margin: 0; - text-align: center; - } - .topbar-menu>li>a { - padding-bottom: 0; - line-height: 40px; - min-width: 100px; - } - .topbar-menu>li.topbar-menu-themes>ul { - top: 40px; - } - #layout-sidebar { - top: 100px; - left: -300px; - transition: left .3s; - z-index: 9999; - } - #layout-sidebar.active { - left: 0; - } - #layout-content { - margin-left: 0; - padding-top: 100px; - } - .topbar-menu>li.topbar-menu-themes>ul { - text-align: left; - } - .home .introduction>div { - width: 100%; - } - .home .features>div { - width: 100%; - } - .home .whouses>div { - width: 100%; - } - .home .templates>div { - width: 100%; - } - .home .prosupport>div { - width: 100%; - text-align: center; - } - .home .book>div { - width: 100%; - } - .home .book .ui-g-12:last-child, - .home .book .ui-g-12:first-child { - text-align: center !important; - } - .home .testimonials>div { - width: 100%; - } - .support .support-image { - text-align: center; - } - .support .support-image .ui-md-6:last-child { - text-align: center; - padding-top: 2em; - } - .content-submenu ul li { - width: 50%; - } -} - -@media (max-width: 768px) { - .doc-table tbody td { - word-break: break-word; - } -} - - -/* Code Styles */ - -pre { - white-space: pre-wrap; - white-space: -moz-pre-wrap; - white-space: -o-pre-wrap; - word-wrap: break-word; - font-family: Courier, 'New Courier', monospace; - font-size: 14px; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - padding: 1em; - background-color: #CFD8DC; - color: #404C51; - margin: 10px 0px; -} - -.ui-tabview-left>.ui-tabview-nav { - height: 150px; -} - -.col-button { - width: 10%; - text-align: center; -} - -.whouses { - background: #ffffff; -} - -.whouses img { - width: 100%; -} - -.ui-growl { - top: 100px; -} - -a { - text-decoration: none; - color: #1b82d7; -} - - -/* Animation */ - -@-webkit-keyframes fadeInDown { - from { - opacity: 0; - -webkit-transform: translate3d(0, -20px, 0); - transform: translate3d(0, -20px, 0); - } - to { - opacity: 1; - -webkit-transform: none; - transform: none; - } -} - -@keyframes fadeInDown { - from { - opacity: 0; - transform: translate3d(0, -20px, 0); - } - to { - opacity: 1; - transform: none; - } -} - -@-webkit-keyframes fadeOutUp { - from { - opacity: 1; - } - to { - opacity: 0; - -webkit-transform: translate3d(0, -20px, 0); - transform: translate3d(0, -20px, 0); - } -} - -@keyframes fadeOutUp { - from { - opacity: 1; - } - to { - opacity: 0; - -webkit-transform: translate3d(0, -20px, 0); - transform: translate3d(0, -20px, 0); - } -} - - -/* Introduction */ - -.home p { - line-height: 1.5; -} - -.home h3 { - font-size: 1.5em; -} - -.home-button { - font-weight: bold; - background-color: #FBD17B; - color: #B27800; - padding: 8px 14px; - border-radius: 3px; - transition: background-color .3s; - display: inline-block; - min-width: 120px; - text-align: center; -} - -.home-button:hover { - background-color: #f9c55a; -} - -.home .introduction { - background-color: #1976d2; - background-repeat: no-repeat; - background-size: cover; - color: #ffffff; - padding: 80px 30px 80px 50px; -} - -.home .introduction>div { - padding: 100px 100px 0 100px; - height: 200px; -} - -.home .introduction img { - width: 480px; - position: absolute; - bottom: 0; - right: 0; -} - -.home .introduction h1 { - font-weight: normal; - margin-bottom: 5px; -} - -.home .introduction h2 { - font-weight: bold; - margin-bottom: 40px; - margin-top: 0; -} - - -/* Features */ - -.home .features { - background-color: #f5f7f8; - text-align: center; - padding: 30px; -} - -.home .features h3 { - margin-bottom: 10px; -} - -.home .features p { - margin-bottom: 30px; -} - -.home .features p.features-tagline { - margin-bottom: 0; - margin-top: -5px; -} - -.home .features p.features-description { - text-align: left; -} - -.home .features .feature-name { - display: block; - font-size: 18px; - margin-top: 4px; -} - -.home .features .ui-g p { - color: #535d62; - font-size: 14px; - margin-bottom: 30px; -} - -.home .features .ui-g>div { - padding: .5em 2em; -} - -.home .features img { - width: 57px; -} - - -/* block: volume css start */ - -.volume-item { - padding: 1em 0; -} - -.item-flex { - display: flex; - align-items: center; -} - -.item-flex-justify { - justify-content: center; -} - -.margin-between-img-text { - margin-left: 0.5em; -} - -.second-content-header { - font-size: 0.16rem; - color: #2e3039; - margin: 1em 0; -} - -.bottom-button-margin { - margin: 2em 0; -} - -.text-align-center { - text-align: center; -} - -.replication-item-border { - border-top: 1px dotted map-get($widget-border, hover); -} - -.replication-img-item-padding { - padding: .25em 0; -} - -.position-relative { - position: relative; -} - -.replication-img-item-height { - height: 120px; -} - -.replication-img-item-padding img { - position: absolute; - top: 50%; - left: -75px; -} - -.replication-img-item1 { - padding: 1em 0; - position: relative; -} - -.replication-img-item1-div { - height: 40px; -} - -.replication-img-item1-div img { - position: absolute; - top: 50%; -} - -.item-content-backgroud { - padding: 1em !important; - border-radius: 10px; - background-color: rgba(243, 246, 247, 1); -} - -.volume-basic-info { - background: #f3f6f7; - margin-bottom: .3rem; - padding: .2rem; - border-radius: 12px; -} - -.volume-basic-info h3 { - padding: 0 .08rem .2rem; -} -.volume-basic-info p { - padding: 0 .08rem .1rem; -} - -.volume-basic-item-class { - padding: 0.5em 0; -} - -.volume-basic-item-value-color { - color: #2E3039 !important; -} - - -/* block: volume css end */ - - -/* profile css start */ - -.relative-class { - padding-right: 0.40rem; - position: relative; -} - -.create-profile-form { - line-height: .32rem; - .profile-form-padding { - padding: .05rem 0; - & > div:first-of-type { - &::before { - content: "*"; - display: inline; - color: transparent; - padding-right: 0; - margin-left: -0.09rem; - } - &.required::before { - color: #cd0a0a; - } - } - .radio-groups > span { - padding-right: .30rem; - } - } - .form-submit-button { - padding: .30rem 0 .10rem; - } - .secondary-form { - padding: 15px 30px; - background: #f3f6f7; - border-radius: 12px; - } -} - -.profile-form-padding { - padding: .05rem 0; -} - -.create-profile-img { - cursor: pointer; -} - -.customization-item { - min-width: 46%; - margin: 0 0.5em; - overflow: hidden; -} - -.customization-container { - min-width: 30%; - max-width: 100%; - padding: 1em 2em !important; - background-color: rgba(243, 246, 247, 1); - border-radius: 10px; - display: flex; -} - -.ui-inputgroup .ui-inputtext:not(:first-child) { - border-left: 1px solid #cfd7db; -} - -.ui-inputgroup .ui-inputtext:enabled:hover { - border-color: #98a5bc; -} - -.input-text-vertical-align { - display: flex; - justify-content: flex-start; - align-items: center; -} - -.input-text-vertical-align span, -.execution-time-add { - padding: 0 0.5em; -} - -.execution-time-add { - cursor: pointer; -} - -.modify-profile-item { - margin-top: 0.5em; -} - -.margin-right-class { - margin-right: 0.5em; -} - -.suspension-frame-content h3 { - color: #fff; -} - -.font-primary { - color: #434B52; - h2 { - padding-bottom: .10rem; - } -} - -.padding-class { - min-width: 300px; - &:last-of-type { - padding-top: .10rem; - } -} - -.icon-color-class { - font-size: $fontSize; - color: map-get($color-primary, normal); - background: rgba(101, 125, 149, 0.149019607843137); - padding: 5px 10px; - border-radius: 10px; -} - -.font-color-class { - color: map-get($color-text, primary); -} - -.label-class { - color: #B9C3C8; -} - -.storage-count-capacity { - font-size: .2rem; - color: #438bd3 !important; - padding-right: 0.05rem; -} - -.suspension-frame-container { - position: absolute; - width: 200%; - top: -0.1rem; - left: -5px; - margin-left: 50%; - transform: translate(-50%, -100%); - z-index: 9999; -} - -.suspension-frame-content { - position: relative; - background-color: #242e43; - border-radius: 4px; -} - -.suspension-frame-content>div { - padding: 1em; -} - -.suspension-frame-content::after { - content: ''; - width: 0; - height: 0; - border-top: 6px solid #242e43; - border-left: 6px solid transparent; - border-bottom: 6px solid transparent; - border-right: 6px solid transparent; - position: absolute; - left: 50%; - margin-left: -6px; -} - -.mouse-cursor { - cursor: pointer; -} - - -/* profile css end */ - - -/* Who Uses */ - -.home .whouses { - background-color: #20272a; - color: #ffffff; - text-align: center; - padding: 30px; -} - -.home .whouses h3 { - margin-bottom: 10px; -} - -.home .whouses p { - margin-bottom: 30px; -} - -.home .whouses .ui-g>div { - padding: 1em 2em; -} - -.home .whouses img { - height: 42px; -} - -.home .testimonials { - border-top: 1px solid #4c5254; - padding-top: 20px; - margin-top: 30px; -} - -.home .testimonials .ui-g>div { - margin-left: -1px; - margin-top: -1px; - border: 1px solid #333D41; -} - -.home .testimonials .ui-g>div:nth-child(2n) { - background-color: #283134; -} - -.home .testimonials p { - font-size: 14px; - line-height: 1.5; - font-style: italic; -} - -.home .testimonials h3 { - margin-bottom: 26px; -} - -.home .testimonials img { - padding-top: 10px; -} - -.home .testimonials hr { - width: 40px; - color: #4c5254; -} - -.home .testimonials i { - font-style: normal; -} - - -/* Book */ - -.home .book { - background-color: #1976d2; - padding: 30px; - box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.3); - color: #ffffff; -} - -.home .book .ui-g-12:last-child { - text-align: center; -} - -.home .book .ui-g-12:first-child { - text-align: left; -} - -.home .book img { - width: 200px; - -webkit-box-shadow: 0 10px 20px rgba(0, 0, 0, 0.5); - -moz-box-shadow: 0 10px 20px rgba(0, 0, 0, 0.5); - box-shadow: 0 10px 20px rgba(0, 0, 0, 0.5); -} - - -/* Templates */ - -.home .templates { - background-color: #f5f7f8; - text-align: center; - padding: 30px; -} - -.home .templates h3 { - margin-bottom: 10px; -} - -.home .templates img { - width: 100%; -} - -.home .templates .ui-g>div { - padding: 1em; -} - -.home .templates .ui-g>div img { - box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.3); - transition: all .5s; -} - -.home .templates .ui-g>div a:hover img { - -webkit-transform: scale(1.05); - -moz-transform: scale(1.05); - -o-transform: scale(1.05); - -ms-transform: scale(1.05); - transform: scale(1.05); -} - -.home .why-templates { - background-color: #20272a; - text-align: center; - color: #ffffff; - padding: 30px; -} - -.home .why-templates h3 { - margin: 10px 0; - display: block; -} - -.home .why-templates hr { - border: 1px dotted solid #262626; - margin-bottom: 20px; -} - -.home .why-templates img { - width: 100%; -} - -.home .why-templates .ui-g>div { - padding: .5em 1em; -} - -.home .why-templates ul { - padding: 0; - margin: 0; - text-align: left; - list-style-type: none; -} - -.home .why-templates ul>li { - padding-bottom: 10px; - text-align: left; - text-align: center; -} - - -/* PRO */ - -.home .prosupport, -.support-image { - background-color: #20272a; - padding: 30px; - color: #ffffff; -} - -.support-image .ui-md-6:last-child { - text-align: right; -} - -.support li { - line-height: 1.5; -} - -.home .prosupport p { - font-size: 14px; - line-height: 1.5; -} - -.home .prosupport .ui-md-6:last-child { - text-align: center; -} - -.home .prosupport .home-button { - margin-top: 10px; -} - -.support p { - line-height: 1.5; -} - - -/* NGCONF */ - -.home .ngconf, -.ngconf-image { - background-color: rgba(79, 41, 64, .8); - padding: 30px; - color: #ffffff; -} - -.ngconf-image .ui-md-6:last-child { - text-align: right; -} - -.ngconf li { - line-height: 1.5; -} - -.home .ngconf p { - font-size: 14px; - line-height: 1.5; -} - -.home .ngconf .ui-md-6:last-child { - text-align: center; -} - -.home .ngconf .home-button { - margin-top: 10px; -} - -.ngconf p { - line-height: 1.5; -} - - -/*NOTIFICATION*/ - -.notification-topbar { - width: 100%; - height: 150px; - cursor: pointer; - position: relative; - display: block; - -webkit-animation-duration: 1.5s; - -moz-animation-duration: 1.5s; - animation-duration: 1.5s; - -webkit-animation-fill-mode: both; - animation-fill-mode: both; -} - -.notification-topbar .notification-topbar-image { - background-position: center; - background-repeat: no-repeat; - background-size: cover; - height: 100%; - position: absolute; - float: left; -} - -.notification-topbar .notification-topbar-close { - position: absolute; - top: 15px; - right: 15px; - color: white; -} - -.notification-topbar .notification-topbar-image-mobile { - width: 100%; - top: 45px; - display: none; - position: absolute; - float: left; -} - -@media (max-width: 450px) { - .notification-topbar .notification-topbar-image { - display: none; - } - .notification-topbar .notification-topbar-image-mobile { - display: block; - } -} - - -/* custom breadcrumb start */ - -.custom-breadcrumb { - padding: 0 0 0.3rem; -} - -.custom-breadcrumb a { - color: map-get($color-text, primary) !important; -} - -.custom-breadcrumb .font-color-class { - color: #478CD0 !important; -} -.create-profile-snap-policy{ - margin-top: 2px; -} -.create-profile-snap-col-6{ - width:50% -} -.create-profile-snap-col-8{ - width:66.66666%; -} -.a-rep-disabled{ - pointer-events:none; - cursor:default; - opacity:0.5 -} -.line-arrow-right{ - width:200px; - height:4px; - font-size: 0; - text-align: right; - background-color:#ccc; - margin: auto; - margin-top: 10px; -} -.line-arrow-right::before{ - content: ''; - font-size:0; - position: relative; - width: 0; - height: 0; - border: 8px solid transparent; - border-left-color: #ccc; - right: -16px; top: 2px; -} -.line-arrow-right.enabled{ - background-color: #438bd3; -} -.line-arrow-right.enabled::before{ - border-left-color: #438bd3; -} - -/* custom breadcrumb end */ diff --git a/dashboard/src/assets/business/favicon/favicon.ico b/dashboard/src/assets/business/favicon/favicon.ico deleted file mode 100644 index fee6aea0d4d072fcb386eaf2bf87424d5ba8eb40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1150 zcma)*yGjE=7)JlasD-F2h*n}ikf0!5ip4^(5zC0Rg@vH_0BI%BfOfutm&VR^2P6<* zKrAG&5fnQM3-3r^J%bU4adu+DNp`;fJ2SA!iUhpFQ25NsMn+^nL~=kx@}2V~^UPYk z9^#397-`jW&GCld7G7Z0)$wIG`73tMx5iz73S5Eyzqa}MX*0ZkJmtUkb0Tv0 Y19zy=De}R|COWG^aTw@o&fy)t08%gctN;K2 diff --git a/dashboard/src/assets/business/fonts/roboto-v15-latin-regular.eot b/dashboard/src/assets/business/fonts/roboto-v15-latin-regular.eot deleted file mode 100644 index d26bc8f519b5b90a0639f82a18bfef133599196a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16227 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 v#g4%>=-%`rNTT$Q3+IGsv=@uepU+g& - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dashboard/src/assets/business/fonts/roboto-v15-latin-regular.ttf b/dashboard/src/assets/business/fonts/roboto-v15-latin-regular.ttf deleted file mode 100644 index 7b25f3ce940cbba3001420d38b7d0f12fb7f2142..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32652 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 N6K0jQ!xePm{|7p>-q!#C diff --git a/dashboard/src/assets/business/fonts/roboto-v15-latin-regular.woff b/dashboard/src/assets/business/fonts/roboto-v15-latin-regular.woff deleted file mode 100644 index 941dfa4bae83483cf1784641063ce1deceda1406..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18520 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 diff --git a/dashboard/src/assets/business/images/cloud_service/AWS S3.png b/dashboard/src/assets/business/images/cloud_service/AWS S3.png deleted file mode 100644 index a98735d089813b41a7fe957cb7c7e2bc160bdf54..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10197 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 P00000NkvXXu0mjf6_v*L diff --git a/dashboard/src/assets/business/images/cloud_service/Huawei OBS.png b/dashboard/src/assets/business/images/cloud_service/Huawei OBS.png deleted file mode 100644 index f44c58a86bb07f0c1c0d8089a098bb2cbc701e96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12423 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 FV1mysw}t=! diff --git a/dashboard/src/assets/business/images/cloud_service/Microsoft Azure Blob Storage.png b/dashboard/src/assets/business/images/cloud_service/Microsoft Azure Blob Storage.png deleted file mode 100644 index 62caac4fa05284c01501c341957596e2c4cbdaab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6611 zcmV;^87$_BP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXf8E8pFK~#8N?OX|% z71fo#b*tWc{d%J}XjVlwQIJK}fSPDbG@4~5&S?C;iCbdSL?D_`6Gvyvn8k#s(adBU zl@N)EF&YvS0VOCAR8XL$frf^r>Am~)>$ktESIfQgpIfgRY;a=QCLc^V7WJxb-Q}GB zoO|v$x2n~oleeAn@*uXbP5Hc6W1?D2F_e?NUD+?jA|OL74`lO7M;q&_=y;>xcixX>6uw^}Y}ZMooLJmSB(jmN?D%oT6UGnKSb(2!DD-w9 zGy&c;>1&TlrRHfQvW`LUpGN;N822%eC9o88f5w8!d>+nteYOH<;|q0Z*^TqNT3 zM9iMH$ala0(Zydr@2|q~{m>wwAebkmN1`%~Gfjgu=+|cwos-u3bL>j5C!XzzX1lu0 zt}ZJYu?{wNG`7at+N@ZYn@rgW(@kd_&vu#ZP;(=|be);0hkkVVZC{>yVxiF6R)DyM z|DfUi%)tbr@oYyV740&ISCwpf^Wcu!j;5AGTWdBRbCOBV%*dSO=3I{;!_3z?(*@&z zRWhA~C#R^vh%}Z;{BY?dOKzTXBH99xWI{^Y6|s0W4kgE|_OA4yrbts$tf3JCTb+@d zX=QI)@{wiBUT@g#u#g~YfwO}Fk+DE{%o50}%B8M(0ZbjiVFDKl{TT6Fib7pTtqP-&(k7bf+Cu?ypCzz8XOUB_b9^m)gbHS6p+FpMk#|p6o z!b&iKunIzKFd}dP^}}_L6+mVX%JGzl%;7{t;q98n&tLo7x<*fG0cM)Su5Qp_U>ZY_ zI`Pf@&av=|AQSg~+F8eQ9n`n*G-p`Ze4Tey>%HiElrPK}8PBjiA#*hJV27sz&!+Y_ zbUgCo*L%`-I2e3a7r24a{Gwj%2~Qfj{M2QWHg9QZ>q-ZB5J7jo+A%fU*IZT5C_>e( zoOA6}=X~s<$>90$PV8XNz-_@5BAv-)6D*lDl4+StNjmpCP^gYnnk5pjfM7DIr4k~U z6#1w9&V5b#uKP+-BAxO~m*7$9%3#vKZQ<3;`#$-}-=t%b6$Dgf_+I@eZMuSSao2xd zx@_57UG?qED8g<2(J`p6{K$&{vy%_}=;L?Y`eEcRYKvyjXyCRGG=e3?WvsYFs|stC zIG515-+{uaQk+?3X{fTOs8A~_FJ_e$sxrz;^L6^peNFP$eHDhF2aFXCgfTSj;SMSd z90l5B<0cb=Il7dd6hg|Q4iu^bUV!|7kebRu^Y#5EN1pqd^j+smFq+GxEB&3AL3IkC zfunE)!Cc=zq4Hl<->1F}r~$P7%QPq`ob+@G1)@_Z5S>DS=x^^GPel3vDELlW>P!Yz zKR9rWGs>|ZBEZ9XHpolbaiR}m3+mm0?nv&c)Dm~}&RX>e2mr*%0Rd>>C?KV@O~GXL2{{ z&HaNX)Z1FLB7^U5O0ICy8IefX9UbxZj%ah6)zq49ZBMtgrjk89S6)AF`On|1+n!($ z)eADt>7_2tA@n>-rm#MneFJZJGz`ir`Z+FBoZm+VfqA+tP&3R4H(Se z8o>ld%O!^`#D2K+(j{M-r-m5#Tt1ox83o$^K;npQRrX6)@4>ER+ZoeIWo$DI!$}=# zinp}eEp74k&S+<+)z#@nV-DsNb6^*kJ_ZZG(WD-J^fO<*WiC=oZBRe&8gvu{`o#2B zP7$+)piriP36G3gr@b>=K;eh&1&#nm2(@!LH)p%KoR`jekw~__zN5J<-qw);I+3nS zb7R-tcYXY(FU$qcYt5A1oK@Px?O zULs|e6dGki!u{%ea5^3+9CtdQZ2?{N^~ULYx08mB7q5c|?%#k;${8`}bTZlP@uO2H z5S>DS=t#fdf2u|wDxyeZ9z{0{0j%v3SO{zBhhRhcEa+F`i1r;O3n<&+e)4z(tbWIS z|CC3nmr=AUqsqCfLMsC+9)(iEP=%-iHVhS6pdO+r5H8Ry8miUNUm{UP6^KPur1CKk zm8-K)R2c%Pp?ldsn(`=6-#AW}c{p)ZL<71Umg)NRQCL;=B#l+#tQkPcXL z3RZ*ussPvYCJr*7eL$h$>j=M`QZniZO#0&aLn>T=wR%Q``XrDKt}5?+(noo0{BQKs zbAJbbbU{zSBMTy}dF0_$kKVubTlYNk(%Kr=)e+Zo`d%BIBJat!Qx`rfir2#jX_$JY zdf-VN6gUPj05zl0{7z8Q*PH4TOw*UcA%cL4gpx;zL=eCX0Rd!FQXom^IhBkeNQe2V ztuXZI_XG4vL=bh}k9-vTu|c>cMmcWLhU^?Bt8aKCvUPKc1;;Tt@}+fM8Osy8)Po)} zKE?`29O?%DFaY@TSC&GRvC^5 zcGMmOJq7N_L2y8-pb`%?)jkET0G0?dH>mnhgXViea~LT`SI`_q#J(C21K`^KdK)9V z^iml5;mncj*UxN>M(wFHXN);x(kmMp-rC+RkuJ-O1{9zx%qh|#dV%lIaR_Dz7C?F| zDMzA1aZHlX8%uhD?W2q~ej0(X)ZavaYZ+E{i$|&g8ICH}vP?@e303=&p#lU0hYsUO zro{m+AO&267&Y~kp|nc_sSb%$$-Bu%p;zABNT@9fL)Dun1SQf>kCG^f7CZ~Pb2XXuQZBRLKj2GTCT-z(0%^D7N)sMLQbWp0(Ztrf z9btPSNMF9F4``H(ia+)5X!23;q3XMWzI5;bO{0UIHBGyAHjEw@yyO$ZF1oNRSXQ$B zrMGH#cL%gW+G|B+utR{bWZLfTF=Gico-(7UY){JUNm;uPM0=MRPv_tmxz4Seoib&2%#0@-u9w?lXiE#*^-lW0ft)J? zF3)+~!bQd$Qd_IP@Ir3wOR0ut%W?}e9tJK@g9jH&%I&3NgMf0Rt|BMk@m&eYUFiWx z#}%%Nbk?<8@ufx2Gk)FY7cIA>JkXq)dErl4@z=ij(92*P6{wYKOPP(vt!r+0eB|l3 zjh%S=__Mxt+N338&%9&Y+5a*2%x|ADdFkZI_kU>NqOG;{4PDtwKJ)#_Q}0;uo2}FV z^pC+^*AXdj^56fne$44NTyfP8a$pCHNb!>=UK%&?j_a>q-P|sJx@_xdV{d2dhK1)p z+?kX)nM&l+t5(;2`cuCs4Bf@pS8js0*GP$MjORo1u6AxW^$JwNc)m zlr6xbq0~H1;GSLbB z>6jiU)PqB$QS2GTyr7a73}w91)yi7C?7DraGtZneddx`6b6Z<@V?)5UX@60GC+Y%z zi0rB(Vm2SLx;ia`+@kcD?21|q4OT41SFG5zWXVH3SUGLxd0K&MdZuj`Kl0$KU%2*( z=bzs-ZSI7d|MkP4|H|C*Q58=w-~7cJ9^drmwveHM5e}>FvjOF6jwT@Cc`jxdL50~U zUDyH4!x2$OX1=v_BV%_g{K!*Hk*oyzQvU3zZK3k}%SL{C-KImNOehRfRoEF<)U_tI z?v3o+-??*tWXJyQZ3lbaXh>ai+d5uy>&*EN9&Cm&$z6w%Q|3NaQ2xE2EZ>IaQsl@A zJ;xLo7}vjlcQw;)T6odJq%xSJ6yN^Qnn20z)8{-nZt|U9T>SHzJ+VCv*6VexQOADl z$!$eNi^@vBe&07YAL__j66R#T_D=g{pIOG(^%sBQq2@^1f_Op!l(>%K6~Nxaia?3?Ja*?zm1|6_yf3n zz{ln2k)`KOs+>B$eCqhB>EkPBjxBF%Zhc|p%hgq59$0$i*wI+tSP@Le@T@>e7^c!p zP}6BKEYJ`>Val)T$WdKURWBLY#0*#Mf za??x?M;7!$tgh7TJGwLVWjVfyH4=g!EbjJ_9B6Y*3yAKd`;9wSZhx)gpFeluqFd&Nu=4s*08K%hFs|Z^CN6m* z^~fhYS5;`i#~Jo#O_(@()R+q8y8s#Wvv+T+8BLZB9eJR|`t^%De!J%FXV&a^diD0- zt>3xo<=Sk@LO|2roWb&?q7NSh)xoh)P&o{BjflnP3`?%dHFtlj^V)_u^M*NA)$f1T z;bbz%DIj1$K{y&`mF06<_rJ4#UEPiUGP^j0=r~A!0SR#chHi0I^w_f3RzAD)tf`~! zyZ5rnvJgCt?vDj4Bi(_sJSc>_;;h#KC~PMp-5{5P&#@}1ii?U0h)?0Dz>#%#;BItN zefUdP|3c%5pzgv7b2-l_2ua%JfjsL^7!kiE!m3@-9*)LtN0Gw4w&p*ARXb zytsOA!yXuU$t$ZizOr(q%J~Xa6N_3IqnR?Fe108dxj`AE%F)$`ILS`m5?r8t< zqnks8p*!#X*yKsY(#c7V6-Eh8=^Ggqq9zoODbZ>`Q&ETJ=^ZaEH$L+qdafgq03uk) zXsyEoFzh-8)3YOndvnj7!rYh+GekoTDIH|-0$kU$>N&Hk$*hE+H(m;NT8)l?q>l&% z_$#`EL7)+>e8H}C_W2jK*k*M4f{8O{jt|Hb>`<_f&@pctY&-H_O~1L!rV9Rp8M%b$E$>n<_y?}#-Rnw|wDK)s>LW;=z)%#UFTJZOx{JkA8B&;;$?y3<+V=MA48^fHa45VIUZA znVF{Vx^*7#WDaWJoFmijXwSeB6%Zu1YNGzBtO=R`d!$>&hYk(1P(@2)Pc&kU8D4nI?U-C+iTFXEP(!bARP-M(m7Zq}@^GiMBkDPs(S zC2x<<%8H&*1?b zuG2siM!}U^I;3d$h@s4M_wK0&LkN>OEQNw~*4mcdvAv$@aKOIpC}v4CK!5|c1|=P8 zt(kJp*%c!uMWWiuRa-)s%*a<*mPr#C29$+?A%>Nax)#(ZG52#>>hG9DC?JlNlseLs zL-SPD-MDF=V6k}%Dyz!F#0aSdQhLy+X2Jgq!33Q*chbz6;~bN{vY{@X5qh9#)7#D8 z`R;REFI{}+)sv@GC(~X!A(9y{X0m8nB+>|!SxIqd%30-1WM5oU^X%_-lZW5|L)RlQ z`^W$FeC_T=EgYasjuZw5fpKvu$X)pXAid)w=^?OXX35rDu znHEfEK+dP@eElm2w{DAa!5UXAi&Z)jQI6Bkcb8N*7&lEvrEJg4yLE6#d$#oE?G?2dc>^xVq_#!W7_)7GX3obb0 z{Do&Cf>0I+gG5VOMCk=GZ85?-1Qwn@_KY)FbJNb6nz~)}=GIMnN=qgp_kH!n8X*xx zU`QAb6d|0fHKHna-E}jd*jZDnfBB0WZolp6+P%$Bt!QL=+AuQJ)s^2{x~S>k!OgF% zE-tKq!Vts*1Vgt=ic&*L%mDrWJm^~o>XN*JTrjWt*UJ~*d+&?uH#YqKH*YeQArI*W z!$#SxY4dMcbZJp>&?CQ2BKjLAYFgF&Ju#`&zX`~&@K*GCaYi%;+jUHV!rnII3FknI58fKQg`NsZOJU;2{u}shH-`A;&A^?p=PYtC|paUXl;R0j& zv{986P$tduefy)E-mGux$hcN!%!tA{^JYvtr)t;U*1dHHtE(y(%s-232tbYc{jq)f z4h*X*n=)-eVK|^8LR0#Lk3>eG>qYHd-j?l+`wn(=N4pI!s;h>M8*}=Uvqy~@MZUme zsenXM6;?9~JW;6bmD0uWII5=$2LpmM^801}W=O$qNoEOv1A3;F&0`G}wMmqzv zwqu$qUxKOPvHouN( zYv71~mF9A`9So8ssQHZxG%!66@mL@bg8K%c+(a&lW!M(T9dKn!q%3-oN+qbq|Ahjv zrzS6iL?(wJz$RuSIRc3Q0Um+E4an}n3MkJoFx_cQMeYEN3AnQ`$NGIsoK3`md-Dtze!ALf}F zc`F1dRG?HtKCh-1|X;P6^YF};Q|M8R)`%GFw$PO)FP5myVV7%e|iDDZ<1~!k#gNE@**-J0c7$m(XHCuIsxk}q%D1kOz`jQRy zfKh05r`oV$4XZYQ0}m?4qaLYKzZFSFZ!vHSo`618^T8nvP%Xa^eo+_PLO=|Xhqxd0 z*#gdZsyd{OfD6bM34DRTy3d0GUZJMO_J_p{IEF*%Z)`r%08|HygYTaZ0_KgvZw|^! z=-<$&=n#~@rOxwAs%FFi#zJksl~S@V#u07QmCvxc@!324I8Qzbf8WH|{{lX+;G>j1 R!yo_v002ovPDHLkV1nD_&Y}PS diff --git a/dashboard/src/assets/business/images/cloud_service/u2309.png b/dashboard/src/assets/business/images/cloud_service/u2309.png deleted file mode 100644 index 04c81c90667223077d7f9373fc61140b68720ac7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8761 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 diff --git a/dashboard/src/assets/business/images/home_admin/Cross-Region Migrations.png b/dashboard/src/assets/business/images/home_admin/Cross-Region Migrations.png deleted file mode 100644 index 13403ec736aa7d7ddf71d9d4fb185f0d54c24790..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1408 zcmV-`1%LX9P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXf1rJM>qkkTJR+c|mI_k2&bxr`M#^y!IV)>=Nn+oNP6@OMcWXyy<7#tf-i^>-M zxcWO-+RTY#C#kC9^YiC|Zw5uBIv5^i@4oY1xsyiV({tyeS0bWP9Slc?x{%^f4(Z60 z144zu=AT2CM7;{s*-RY~eC;i(#bU_JUTS_MKv--xyQowL^O`a01o(dsv(3UL4pA`~ zWFlj;nlzq<9}7;bR!mMa!myb~=>&_WC{+iO4j4dUW}49qHnLQp?5tKF3NxC)MivI_ zTTZIq*P77`Hh!uB6sq3`nsm;n1`O?J_dYe56(TY>C#Sys>cZH_HEOLLZEbDOAMG1F z8|pmRDViFuBFuzNe^^Hi6|cTN@a5NEh)UyCgc*8&jHUi!C+mUyN8q^i=WIpb(?h*BfraA;I2MCL?vlAV!-({B6qtLI$rV(zpvu)_|@-kRe5qDI49&kGS z57_Uj$;=Vn7x8!!?D4YOsvwoScm4%8H#hS(Nl+e}yfFnW_q9Q0f+g3_RB6c)Y+Jq;P#Go-lhSm zP!{sbcA1x}#G)+wm#S#yM#sL6>l0ZN$hri`OgcT@)B6;)lmjZmJfTTPh8B-RJgHOB zm_cTko|-|Sr&V%AYj0vV%-zrFmdjE=<;vwD6lzpKir1-V%ph-q*Vfj+`>P9rl!@vclh^ zB*rrh&c((1V4aG_3@tz-!)!oH&atA;qm1H|n znPJ9NB15rq6}=g+&vSeJ4ho$uY>Q?c6w^50<;q*c&m6;zg1@}(i{(Ef=aV*aVk#j3 O0000&p800001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXf1+z&+K~!i%-I@DO z990y@XLn(NT^>@P6r@dUciCN}7Olj#T1;zFf6{Ge%!_5my`3$z=dJj$cciYcWKo`GGzcg}Toc6N5zxjWNPKG_`ZxidT8 zIdkth_wHbuUtE&53U>Z?OR%Mav38n$d+x&J)*rbeNheOe_2H=xxMKkp26OcAao$Sg zj~l=7mf2Vp%&P}qv)dhIW!qYRy2QIA>ExU5K6o$_jjsRMeua0LiX}NSJ^gPCmv-1G z5@m?sq7#R30`-`S$jCIm*K)Hj!W|XL{Gq#7yXvWxe3Tj*K0kY==~xqYGQ;r5oOt6M z-AK}dJEjl!GvKo`XM@)}xRV)%M@I8pb zDDH-A#$d2rLI5mk|CEUu3NIaM{POEBxMRHv4~Dk1o#DUO zK{HrdTxxpxbv(IWuf$(9nXamkvSS1VMj!9Iqbh2 z*e%7R#uu8>jm*`znH9$-9cjg%#^>WITdJDzVElDHYM2FW6Zh?}Czmi?g-}%f4<=x; zOf(vWeYQS8E@8R~p{OJTGkJFkHc*%+_X)DEFdue!=nkyMyI1bxkjm=nDsvp{G;wl^ zU=|h@U=X?p-h=!=tc@ z3J+$_-e+Lj}2IG;x9uD=wZm+D6`#7W$>IyTbsFqn_iv2L1!4RyX!h-=QaQ*$a z(eSvk3dZYVwSQn>u&TO>delHA+}+1or44e2DBBugdcu8bm3T1zK<&^VTVeLdcOy)N zGY1xP$(uOG2&lBT1zD^7pxhx!5xaQXji6d39*jqx&}(aJuvqxyKEqV!<-*R*&BJ(9+_H2H8OIDkz1^w(YzPHE9YBxs0UVeRUwthse8;3E@-YA7_Xw!zb=Bm@J>%F6~QXyXOVL%Xv6LE2EJ0V?5cwiBf-mNCi? z!F05DCaY+Jsr7m8P2ESMGLPk%A!rkX-xxlB%Iqhga_wpxYZa$Vt&})RVerUwROT0# z)SnCA{qSPL5yTS{Vq#(vU%zPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXf0%S=6- z!$1^-1q`TMFo3-3c3;mMZtyO(v{#|5UCeLA3}5^h-;xm>IE+-C@OA!0k0tF zrcFHUOw-gd(`n~qIt}?+re}uS{+_wzH@|;=ji6xB-#`#3F$mpkVSe%H@tIZ_IF4gG zHUtqXLRwr_R+o~)Nm`LZR?NiM^ykMHtuWvyA#84?2V#S?B7v-!)X*rDxA$kH+64VQ zN!u=*ULVuC1g#%41-n2aX)rUBx_K$JiIN-WhO##rGYumknE@phV=OgF>&0Lx0m4O7 zS3)t>AkM9l$coWN34o9p%haW>%034uF-=%1v_Mu2iW1nH(MXQg_YlNUr$u)U&US|N zlG6lQWCjZ~G5LI+Mvc(iSu8@UNmqE8;n*&9JqqBT?V`ZMVT$3{E+R?@uI-}6#9@lT zwO!PhI6jUU+zqwJ)r2zR%*~eCL@{^vp!C`wAB>@WREiI>1`5w zDJy|-!kqe4DslhW{e#_(u1?ZO2-g{136L1W_yeWzY0MC}5d{DM002ovPDHLkV1gM` BJPZH; diff --git a/dashboard/src/assets/business/images/home_admin/Tenants.png b/dashboard/src/assets/business/images/home_admin/Tenants.png deleted file mode 100644 index 091a075c04cc0145d6b82fa7aeb3bc053d7367e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1495 zcmV;|1t|K7P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXf1#C$~K~!i%?V68o z6J;33@2+dt(JY6nXpHecP=_N1QuZU;!Ul7d$(TlA1PL06I-O!7Ni<7%=$eK#5+xs|hTL-c-A2b3)Asn5xRPU?+b%pXf52 zJY-J#^=b@xkZ1JZPsMC`3JF=6(gM;rL4u!*4uUu=W zeQeyLHt`mKJkS=4MdM6-)N^9R-7BD{ucseh%81#SGj-luU+)G>EpC9b7e>L_ttG2h z)x{ZR;)k>4<>k<`uE9Nj%Wt)ocqcrG1C^jh&zz|#91brA7r_b<0c;w0%;%pDfHo-o zP#fSqe+q0QBA}}by=s9oUjBVrbc~GNCm$UJTV^i z=}ubCd+#~v8EST~C%!szJnun@b2uEtk$~eucj2M~UGgB`z+?Wp*!KTH+ysux+my3W zHrgP^Ko%vAI&vI6L(ws?DHFqz1wzNM+{GWqiLZh}ik`yV9XalZUUC9ez88exP=QZV zSij*hawpL=xdZt1G`))wJ@wiE-P+6{J$j&xlw(E$r5T9VddDRP(F1v;WhAkfI66$= zj_4gZ^uc!{r!wAn1~QIYg#!|6Q?UTJcu7MJ1hS3ZD{pjd+x`r3B;fakT#~&up69h{ z(?=oAdpanjc~1x0qNii@r_%L8_w{Rk5=R0KY<)X3@AT}gZ4ejAX_yziO|4HFqz%}& zx96AXpNW%#dC|l78n^KTNoztfkrv6dhrySUr|50(6m3p8_7#|_%C#`2i#B?4m3@)O zldJ4C%aa@BOA~GK3QHTHIeH59T!hk5xx-+TUfe|y^&oTD|N<33mRsFmm5(1DFZhkLOB3Rzg23K5li z`9^Dlnv=9rC?U^^Y<52d)?Q|xO5_zNtngltAP5#)DfA3}F(@7SlfiFY-@l?s1o4W;ea{3&)0EXh5!4sW3#Om?0 zqm*4C%q1`;)yi{k6fMfb_RI{(W1LQ|)xFH&VC3Zi`inBF)e5$$@o{tmfq)Pdx3+ga z|19>{N^NNmixuK(v)k>Zb}_uFh(yFkN_!zFmizESI&8MvFVT>jjn%FgFqc$RRDAjM z$1Tm`9uS;S(;R5%ia~BqTWxCD^Y-gteK&pjwB-ve>%FM(@{7A?{`&jX?w4AhXeFIX z8*R(kg2N1Xc-5)jnSorA&CX2fRbx_>q(vK>jkdHs5_6)rE*guGzd0Gns>*7ZkW;sB z&4?aoBQ4W0BYGVhpT6mvBaVceTyKdTH5is`?}2^Q^);l|9C^U_8E@Zy%AYV(t~c3n xlu=vq2l{qs;Jyd$$4;ckCkB%;XMSLq{{UPClirhS0k{AF002ovPDHLkV1mPd$o>ET diff --git a/dashboard/src/assets/business/images/home_admin/Users.png b/dashboard/src/assets/business/images/home_admin/Users.png deleted file mode 100644 index ed6afcf9cef5450bf9c30a828a6fc97bbb48a4cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1322 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 IM6N<$f`&;R=Kufz diff --git a/dashboard/src/assets/business/images/home_admin/Volume Snapshots.png b/dashboard/src/assets/business/images/home_admin/Volume Snapshots.png deleted file mode 100644 index 31b0ead9cf28ca5ded1c9f556979058230045e8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1658 zcmV-=28H>FP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXf1`kO@K~!i%?V4*$ z6jv0-XJ;)EmS{h;%BOy4qE*w_YD=wE2!bmMD=i|lG)>c_iT$7vjY4_!K^oiG($)s) zOA}HX(@0dX<)H$lJXAm_VAG~G{btfHyfN%9EbPqm?4HZ)?Ci|!%0C6;8n2gLc`~3U@ zaRhYswh>DU#>hBU`N?nX-CzhWIzOjyVq%hIneP4$GNl@0Y9m+!aIvY5Hq#vOv|(6@ zFOQEykSChv~P~EH1>_Dsp&lX zs~pEQw|O(?&BC{*r|#ibkyJ=bWw@L!yEPXyboI59sVJdAhRHK+xh>oCaOOnkrc=a` zVsK!%_)sawv0Z(?lBwvSN=D-EZxBlbQwduh*-%8BMK07ee0%bHmSwy9qptx7Aw!b@ zA+zf%8OvIk~u=Frl9iA?E+L^LALC188;xO<)h4MSfifeYD%^Ex4x z5n4mS6V!8G5u4{4>GP0nN5@C4p@+@Fxp?vF0D9Sz&LMc@5=|;6y5O29 zDmya|#*VILba@J2_r-@c2WXHX{_YRN3WcNw0B86UFS3mMlq4yg7(T{E$6;Ktas|4= z$dr^GKJj@?aB9H`iRD-@1Si$@&fbzUwP$~jBo!YJ9?6=KtPN)6v$JbTh@%KZ3C13&_8x*G zItgpo1TMFF9|B~g?M9aeN}O0KP^kg1SS%1IQ4Ihv17U9KZXv#pMH%#RVkmOF>LVC8 zKeH`)b1G~g!$W^S9KNiohDlKHS6)smg8qt93ZfUwaH#@g~Uy)A(6CWQ3;I~LP z+n>#vD@y3tY<~b$OJXCkuKs(!7$9SzSq``m7^Q1M88k~ z{@Or96#^R=O$W9ZQioW!J5Ts)c!&jK;N;^t1H@DYAY1D)z)lq0O&R=10Wh&H%g{dJ zgbT}38RaAQoE+aT>59Zk#nB0o-#j=Yc7C?{$t3S46}%Hi9oYppDrs=$=PO&bz5s^a zN+gm>h}Jsc34Rm}hJM)hBS$3IG5A07*qoM6N<$ Ef<7+v_5c6? diff --git a/dashboard/src/assets/business/images/home_admin/Volumes.png b/dashboard/src/assets/business/images/home_admin/Volumes.png deleted file mode 100644 index f5d363213cd8565bba1deac6885d1bdf12204620..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1635 zcmV-p2AuhcP)0ssI2x)geW00001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXf1^7usK~!i%?V5c| zRb?E$tkzspwn~`G zQOJzS)@q^i6$dFO|1{DdtxS|@TL|8JfqVPj`+GQ^^PJb~<-%?Av$Kca?|IHS&-eV! z^ZcIYTs04k+%QEL7WOxixUI<;k*G;B#^daYp5A#J!V|x07%+Z6(nYXBEUTz@< z0gXSk=u)eZgc7Qzs>)Y>?L7wrT_#j-x@&#`QZ+S+8R|T7XG8snrke`|jv+xV04niSI}Ml=}@eDECX6&DMMChbh4#$R={XG<2JD_MdmhU3!K&8#69#9ix*aRdp1 zGFpFRz6_`tIn!nKPe*pEk?vE%{8vOCDlQf}nzSPXK`2YhmeU4}j?(fMP^m3T8y!tR z?S+z{U5z_y-g%p9h>e>zH0-X&w4f8@^p!n_@M~ZH-78iyM+TOTTxT|OL}X@V zVEdu?ZO~uwJf<;)U&x{y`f-Xce1ch0AZXsBPUZwUpguevkK65bIvo~Sfcq@#)u z7_PIu1KZw%k+AXI*o;i7RD|+7*9C<(xP9h5Q97qVM{+|G4sAjIw*7$87Gon<4MUph zlkQ|zXbgU`17&;10dmzaqzN>q#WPC}SMM)a>BfeyGk*fbx2A|uO#rfttoA;e{}bTC znhJ6Wy0EgUj9hJaOdZ0bs~}`W zU^ZJ)n!hnyB?$&QBypTw}f#V%*`FX`?)&A80nsBXh zeu5xo83598U`^b<<9)b-pwF8=qb3|NF){nT-h)c<1IW3RJRTwg1DBUB@y|H5J9Bw_ zDl~zsSFbHzb zGBp{{PV&Qq#{DIl{Qr1mGPEt6bi`|#L=yxF2@0bstOHAYf3L=V9D?wn7}i%N$LYw& zt15qc~AETc8=PCAkvx+8`;VHT8Sw{_>F3cnK(O8Lo=MDCO^x90-N z|5bj91SIb+&K^sXjxs0rngyt}D<`F-_u`-KF?!b&f3lsYe^0X8S~C-=QVd;-JrOp8 zR6`&ysQ&)~wD|)6`mQGEX6x=frWpzTDi}Bdcs^~w;cvZnhEOR$*9PDPF)M&1P7#7~ hFs7H=nv7sF{Ra&_?z913Y;XVo002ovPDHLkV1nR?_`CoB diff --git a/dashboard/src/assets/business/images/home_admin/u199.png b/dashboard/src/assets/business/images/home_admin/u199.png deleted file mode 100644 index f2728844d6675ecb4c49dc13fc4bfeb22fba1a08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23145 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 Uw3(>(V*mgE07*qoM6N<$f^&vmZvX%Q diff --git a/dashboard/src/assets/business/images/home_admin/u236.png b/dashboard/src/assets/business/images/home_admin/u236.png deleted file mode 100644 index 0c54aa149d94b19249cce77c2b3ef772b0c53e20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 152 zcmeAS@N?(olHy`uVBq!ia0y~yU^xn8GjXs1$q1h8Iv~YZ9OUlAulFz$#8yq%#e}6fP>lKLt}mF*MswR rD(t-ExeX}K@StPn%XkoD$D&t^^Cqz{9bJ5X4~XyS>gTe~DWM4fyg@5G diff --git a/dashboard/src/assets/business/images/icons/button-active.svg b/dashboard/src/assets/business/images/icons/button-active.svg deleted file mode 100644 index 179a25ba3..000000000 --- a/dashboard/src/assets/business/images/icons/button-active.svg +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/button.svg b/dashboard/src/assets/business/images/icons/button.svg deleted file mode 100644 index 699c492e8..000000000 --- a/dashboard/src/assets/business/images/icons/button.svg +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/charts-active.svg b/dashboard/src/assets/business/images/icons/charts-active.svg deleted file mode 100644 index ee34b6061..000000000 --- a/dashboard/src/assets/business/images/icons/charts-active.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/charts.svg b/dashboard/src/assets/business/images/icons/charts.svg deleted file mode 100644 index 0e98eafd1..000000000 --- a/dashboard/src/assets/business/images/icons/charts.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/data-active.svg b/dashboard/src/assets/business/images/icons/data-active.svg deleted file mode 100644 index ea319ce5e..000000000 --- a/dashboard/src/assets/business/images/icons/data-active.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/data.svg b/dashboard/src/assets/business/images/icons/data.svg deleted file mode 100644 index 625502ca7..000000000 --- a/dashboard/src/assets/business/images/icons/data.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/dragdrop-active.svg b/dashboard/src/assets/business/images/icons/dragdrop-active.svg deleted file mode 100644 index dfd016bc9..000000000 --- a/dashboard/src/assets/business/images/icons/dragdrop-active.svg +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/dragdrop.svg b/dashboard/src/assets/business/images/icons/dragdrop.svg deleted file mode 100644 index 45b0aa2d4..000000000 --- a/dashboard/src/assets/business/images/icons/dragdrop.svg +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/file-active.svg b/dashboard/src/assets/business/images/icons/file-active.svg deleted file mode 100644 index 05d3423d5..000000000 --- a/dashboard/src/assets/business/images/icons/file-active.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/file.svg b/dashboard/src/assets/business/images/icons/file.svg deleted file mode 100644 index a8735eb1d..000000000 --- a/dashboard/src/assets/business/images/icons/file.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/input-active.svg b/dashboard/src/assets/business/images/icons/input-active.svg deleted file mode 100644 index 7aae76f52..000000000 --- a/dashboard/src/assets/business/images/icons/input-active.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/input.svg b/dashboard/src/assets/business/images/icons/input.svg deleted file mode 100644 index 17193c3b0..000000000 --- a/dashboard/src/assets/business/images/icons/input.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/menu-active.svg b/dashboard/src/assets/business/images/icons/menu-active.svg deleted file mode 100644 index cbb4412dc..000000000 --- a/dashboard/src/assets/business/images/icons/menu-active.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/menu.svg b/dashboard/src/assets/business/images/icons/menu.svg deleted file mode 100644 index 0a72b4528..000000000 --- a/dashboard/src/assets/business/images/icons/menu.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/message-active.svg b/dashboard/src/assets/business/images/icons/message-active.svg deleted file mode 100644 index 1b1ce469f..000000000 --- a/dashboard/src/assets/business/images/icons/message-active.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/message.svg b/dashboard/src/assets/business/images/icons/message.svg deleted file mode 100644 index 48c7029ec..000000000 --- a/dashboard/src/assets/business/images/icons/message.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/misc-active.svg b/dashboard/src/assets/business/images/icons/misc-active.svg deleted file mode 100644 index 99f37dd2e..000000000 --- a/dashboard/src/assets/business/images/icons/misc-active.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/misc.svg b/dashboard/src/assets/business/images/icons/misc.svg deleted file mode 100644 index aed6a1f1a..000000000 --- a/dashboard/src/assets/business/images/icons/misc.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/multimedia-active.svg b/dashboard/src/assets/business/images/icons/multimedia-active.svg deleted file mode 100644 index ec9b166f2..000000000 --- a/dashboard/src/assets/business/images/icons/multimedia-active.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/multimedia.svg b/dashboard/src/assets/business/images/icons/multimedia.svg deleted file mode 100644 index d7df87d84..000000000 --- a/dashboard/src/assets/business/images/icons/multimedia.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/overlay-active.svg b/dashboard/src/assets/business/images/icons/overlay-active.svg deleted file mode 100644 index a856e158b..000000000 --- a/dashboard/src/assets/business/images/icons/overlay-active.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/overlay.svg b/dashboard/src/assets/business/images/icons/overlay.svg deleted file mode 100644 index 47dda994d..000000000 --- a/dashboard/src/assets/business/images/icons/overlay.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/panel-active.svg b/dashboard/src/assets/business/images/icons/panel-active.svg deleted file mode 100644 index 0495bc992..000000000 --- a/dashboard/src/assets/business/images/icons/panel-active.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - diff --git a/dashboard/src/assets/business/images/icons/panel.svg b/dashboard/src/assets/business/images/icons/panel.svg deleted file mode 100644 index 785cd112f..000000000 --- a/dashboard/src/assets/business/images/icons/panel.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - diff --git a/dashboard/src/assets/business/images/login-bg.png b/dashboard/src/assets/business/images/login-bg.png deleted file mode 100644 index 134c2bc8abf0bda00208a7382b7e188f812621fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66797 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 diff --git a/dashboard/src/assets/business/images/logo.png b/dashboard/src/assets/business/images/logo.png deleted file mode 100644 index a970902478caecbcb180d959420493e21499d216..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7009 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 Y?ozmU1*!w?c|M@5@LIk~*5dtt0r5}5^8f$< diff --git a/dashboard/src/assets/business/images/profile/u1065.png b/dashboard/src/assets/business/images/profile/u1065.png deleted file mode 100644 index e589739d30488f48adbe1913f7d767037283d7ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 513 zcmV+c0{;DpP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0hUQbK~y+TrBts= zLs1m|&Sf~`nxJK2QNv(mU{Ekv4T1&{nZKgJf55EWIaZb|YX$`kf`&B>2El;_i?Fb$ zpzr#f^R7%~b9?iH$2;e{=Y99PKh6_$f!{*b10_T#K#+q+iti?eZsAaKW!%M;9sCgT ztH}5?4oNNrsw+6j1t(c^RXhi(BNT085+67bK{il-!h5t>yC4-@Yi>g3WCS;ZihP02 z+WaOjM|g5Z=yDQ@DCi)I@(K#K> zDWS@I9WZ~>ycg&^O`#punF;1i71}4UYZXI+LUpIT6Y}8^p++-&e_LKs*olo}%5Jtc zAc>a63BV=2ipR3-#is`CVsTjHK-($?fQrz-id6Y)A!0`a8}E|Gm}fyFP(2Y}Kon`9 z9;mqce}nxuqt~8cflp5F2`7kuY`U=%IMd~5Z4BTOmXd$+$7YHt00000NkvXXu0mjf DgY?@E diff --git a/dashboard/src/assets/business/images/profile/u1985.png b/dashboard/src/assets/business/images/profile/u1985.png deleted file mode 100644 index 8b5e8e5978f5e2f65cec4d741f8bc30c20bb58b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 584 zcmV-O0=NB%P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0o_SNK~y+TrBty> z13?hoxg2O`L_->j6e(?l6cL0Z5V5w?!b0)`mg&Ua!cJQ&8^OXxNx&Rh*qOpYFolJU zB%*c-*^F;?H@Q2xsOW>eo%eQcZf17pNF|_j@scAws42w-&^(3@yQ37fS<_*#GIMJ- zMi6rZ2Wjf-eW+_r8Ut=}iZ+AF?4uJxN2T-Uc}npq%$!wz0IMD=y&5cMuY?*$CK9c0 zU?w=>YdcfX&Ji%bvhObhmFWjhxJf6;38{ltHM1x~5$!oO1Q7!0ABpKnVaL^k2mItr z*n>A`egPFrjc(bqr}ICMq8d^&M;rp_F!PQKu$C1KS|c5MP@lfj<(&eRo4tFOa#sMp zHud-g@ZKe+B}3rU!(-AA0}8+LGa?a@kBGVrSXCoPxJ0`M|HE*k6D(&;dQwnKGO&dv zaF4c-(lCe)YD8^EjAuOS*tjhNwt3N^9MS6$CkTMrp7f5Re+F*&p=TSAn@)>?Ja5XG zHl1YLDL-@OTBJ9JGT$KFS+g_*t9NL&MOYPM=?JjS1HBlmWZPlWqL?5j_;lJy-$R^` z-UzDMW1%BQ0{b75-brZCIPO^Mb&16BxT7I#bX3D?0aqgLPO~GYBZZZk1eNHWQ|c2l WmA){7?r(qq0000vT8Gl)dpK4_;kXX=M|NozFi_t@d zi~~^`!mJ6V4I&0Hya`E3znGRh2yEp~FlCrwbe|zvN$7-128W-1N?O`FMz>hCDc!;k tc$pIp&15!Vnd0vdSH&Ra!pOtJ@LAQza@JZkPN0VvJYD@<);T3K0RYX|T#5hy diff --git a/dashboard/src/assets/business/images/profile/u2987.png b/dashboard/src/assets/business/images/profile/u2987.png deleted file mode 100644 index bb832ed597312824fe778344c621329394a1044d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 572 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 P00000NkvXXu0mjfd4)3F diff --git a/dashboard/src/assets/business/images/volume/u585.png b/dashboard/src/assets/business/images/volume/u585.png deleted file mode 100644 index 0e5ed3f01715cb80e752ea8cac8814f6c8986971..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2472 zcmV;Z30L-sP)1^@s6E5F@k000SZNkl*GVdzCJWBAb{r2n@fQU=2J*eAcchlQ)GA;`TO~q z!JcLxUPfFUgsrTt=Tb*C^^Ih)+Q@8w>BTIEg@#aEOf<#EF5wbm`ef)9{_eedRCc?P zu9V!Mike!x7B#2UvdStteeMETY#nY#o5hSR z3=5@jE)iUU0vCv-ykP!3p)G$uU(s%kzrVN+3=WDbUWI|dA?ohwrQZI2>g?*KR*RL| zEEa0F*yzrGuZioRcrA8kZK37y%Ur8G`mGcm+WzJ2dAeLwJf_pAh=r7rlt4?DET$z< zi^zxHUo&Zh?L=KuGga3$(2ep6YHDp8)BVQP8MJrjHu5&O3Y5aod}6!|HTlnCuk~;ft-ai~cIQMg_&!#A=a4?%KMEwr^Y~e|mIP3jg89p9)Kj9@A5n zQ_fS_G&f+5M+2Dsa9{rbo&5a_T`MgUUBhF%|L)s{hEWDNa8Y)exP7sAW#$(r9zE<> zx1YyMmseI#xn=L6yiSkn79Oo&ne#3eh!PzcVK;a&FnF^)>dJ`;cRxl(N2$KCnX2mQ z=_b3_#+Fuhk4@;FVUEF!WJu-eU?dUE!7s~*4MEa9_9R-au3fl0tEQ`)ki-s+4GZtk zhhVa~t({OFB~lu^M@bMPyv_)3WY!*sHZz)k9JFXeh8fKpnYG8EjWV$r8Xlo}a|7tJ zufG$i-I$ou+>2PkvRDw;KG)}+giXcD}DCy?aP z2xH0!FYi);02Vi`T}}IUXVcaVYw6OJt914H4Kd?J1~l3RD=;H<1%VfUoS=(;7ZG^e zxp||ZZk56V$vOGkS-M?aOHXHK2~-u=Jy}}?aCxh$nku-im62O5$jJ~_+z1+uU<5Z| zX)Gl#TPlD|x$*#~oyt8&H!CWQb}!l~g_k`etGZQDMJpJ#TAz_diOfuV93!e+KzHuk z5zuurLrvC>PO^1%QBO~wz~zv{jEs!ZAmert;RQ6{&v>4X&uo$G2l;LItuyi)%RP}X`uMmQv6_PU zb-)B;H4O4tHr^F#Y-tm#0xQBOnIgQ=!Cl)yK)A6Dt5#CL9QQyetUk(;=qP?RV?thM z$_SsfJc&KZc1DK-#GGL74|siTLld>zY}7w6NHCO`6l_{x8!II-fjvT~>m2I-J?X+@ z8|v97chK6EPY9;5Ns)WuBGoZ|=Z?C2dkF>D-r4-i6t_5|Ozc!uXv!lSf4*rFNI7VqDhMG&Ir|-yWs4>1ni&cW-8U0HjW;@XxTuvE|jzTiHjB zour257AccQR~W*=Yb7Gqcc=-IiJGKe_e&R6IsK(t1h`xUL<4<>0WA05#N}IhUld>|`3#0Yr_s7RD zC2wrwL@G5okz(1XNvh>{98u=^zy6lD#$4eQ-hBB5ZWlGC&hds)^D` z;K6YR*pVrGKeT@z?aR(`5*+t25x9?fErJbz#~6>42Jbr_dp5Ojt)+Gf@uxAL}YuYZ{jFVYX#uAOdId~;LwB?DTRL!DJ>Eq5CRx2 z!URb=`CBfPmj9o+ViFD?d|p(eFD>EmKq-%5Sa`{RnJH~_QPgMYWCUF_fBj>=>)SjFc9x4P;>rYSGowo3vwdrl`j9MuDNL;`Fw> zs>W$0X!U{n7OVCcsMjq#9+qTAO54vTEVKw({`t%~Vc6s|Fmx!G6xe~>^Z8Wx&vjYt z_S*m7!6&zseAAHduAO<3(thyXJGzdM;a$f2jWa;W3Co;@#9_q)&+MU);6OT^m+w^P z$q!S6_hdjELqld3z-M~^JF5uqw={O^*vdyQir_PN2?8uZyG#Z%^9zd@3~|4TkRq!{ z>E~4qjn?5*6)23|mKLQZ#nbNXn+ZXVBrNeCPoJTWKKV@GiMS7xNEOJ0^9fEBJ#@_j zfmysLQZS8-%pK)Cwaczu9DtOTUOwBw0I42|Wxzv44_))H*dSzcT2xf>zae|&`5Z#f zBMGY^5U}NlFxv9HP0m4!`Uu zll}YI3zzKQUB3Y2Pz5-6Ua5ItWoFYTWBdih|A=mPZQ10udl<0KzxkeuOK-TXhpRjG z)32J*9TFRy%p8xDS)J?g)A2gfTaVcOoi`2(yza!WxdOdWwS@tcgve0Ky31$Q@y1Hd zlRM>4&8t#)M0HvRk2QPLSphKP;M02qnDGUtwPxk?Fs5%FI-m>AQVK8SDC4cF(|OuQ z&gFBSUZ2~&i?g&;!g<=Sj~j=vLA zUwiG=xlhine5jYF(J+0>wYA0TB8_?3|L828;%#Ft)9^emuH*2g z)r1MBbL;;6Fs%Ro@2^gP;+lq(=7kC^{r&l7Q+h=Wn38|nPw_Qk*j3lGabuz4ly0UI zrG^p=!CgF4IvFJvn#4664!5?e|M%wgix)rGPq{Ou?38$MNm)ilX5kJVR>n!ZY*JOs z65ATBtgPY}I7Kk7WV8SI{r&vKot-D8HRRP5jy@1~c$1Zv$G3=+X%P=wmHd;p4hy{V p9b8thG^{+tc1nhI2@@L|L&#;XJVC7jaiHfJJYD@<);T3K0RS5zeGUKs diff --git a/dashboard/src/assets/business/images/volume/u760p000.png b/dashboard/src/assets/business/images/volume/u760p000.png deleted file mode 100644 index 6d82d4d4056962cc8a0ba72ac672fc2f58c4f8a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 211 zcmeAS@N?(olHy`uVBq!ia0y~yU@QT$Svc5$E)e-c@Ne9i)o$YKTtzQZ8Qcszea3Q#b^)5S3)!u{W5Z{$ycwQJPBwggQu&X%Q~lo FCIFyfN|^uv diff --git a/dashboard/src/assets/business/images/volume/u937.png b/dashboard/src/assets/business/images/volume/u937.png deleted file mode 100644 index 61dee4c36208e96ecb3776b046ae4195f8d5ee24..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1794 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 P00000NkvXXu0mjf!c_V* diff --git a/dashboard/src/assets/components/themes/_theme.scss b/dashboard/src/assets/components/themes/_theme.scss deleted file mode 100644 index cb06cdeb7..000000000 --- a/dashboard/src/assets/components/themes/_theme.scss +++ /dev/null @@ -1,712 +0,0 @@ -@mixin hover-element() { - border-color: $stateHoverBorderColor; - background: $stateHoverBgColor; - color: $stateHoverTextColor; - - a { - color: $stateHoverTextColor; - } -} - -@mixin icon-override($icon) { - background: none !important; - display: inline-block; - font: normal normal normal 14px/1 FontAwesome; - font-size: inherit; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - text-indent: 0px !important; - text-align: center; - - &:before { - content: $icon; - } -} - -.ui-widget { - font-family: $fontFamily; - font-size: $fontSize; - - input, select, textarea, button { - font-family: $fontFamily; - font-size: $fontSize; - } - - :active { - outline: none; - } -} - -.ui-widget-content { - border: $contentBorderWidth solid $contentBorderColor; - background: $contentBgColor; - color: $contentTextColor; - - a { - color: $contentTextColor; - } -} - -.ui-widget-header { - border: $headerBorderWidth solid $headerBorderColor; - background: $headerBgColor; - color: $headerTextColor; - font-weight: $headerFontWeight; - - a { - color: $headerTextColor; - } -} - -.ui-widget-overlay { - background: #010610; - opacity: .35; - filter:Alpha(Opacity=50); -} - -.ui-state-default { - border: $stateDefaultBorderWidth solid $stateDefaultBorderColor; - background: $stateDefaultBgColor; - color: $stateDefaultTextColor; - - a { - color: $stateDefaultTextColor ; - } -} - -.ui-state-active { - border-color: $stateActiveBorderColor; - background: $stateActiveBgColor; - color: $stateActiveTextColor; - - a { - color: $stateActiveTextColor; - } -} - -.ui-state-highlight { - border-color: $stateHighlightBorderColor; - background: $stateHighlightBgColor; - color: $stateHighlightTextColor; - - a { - color: $stateHighlightTextColor; - } -} - -.ui-state-focus { - border-color: $stateFocusBorderColor; - background: $stateFocusBgColor; - color: $stateFocusTextColor; - - a { - color: $stateFocusTextColor; - } -} - -.ui-state-error { - border-color: $stateErrorBorderColor; - background: $stateErrorBgColor; - color: $stateErrorTextColor; - - a { - color: $stateErrorTextColor; - } -} - -.ui-state-disabled, -.ui-widget:disabled { - opacity: $disabledOpacity; - filter: Alpha(Opacity= $disabledOpacity * 100); - background-image: none; - cursor: default !important; - - * { - cursor: default !important; - } -} - -/* Forms */ -.ui-inputtext { - background: $inputBgColor; - color: $inputTextColor; -} - -.ui-inputtext:enabled:hover { - border-color: $stateHoverBorderColor; -} - -.ui-inputtext.ui-state-focus, -.ui-inputtext:focus { - outline: 0 none; - border-color: $stateFocusBorderColor; - -moz-box-shadow: 0px 0px 5px $stateFocusBorderColor; - -webkit-box-shadow: 0px 0px 5px $stateFocusBorderColor; - box-shadow: 0px 0px 5px $stateFocusBorderColor; -} - -.ui-inputgroup { - .ui-inputgroup-addon { - border-color: $stateDefaultBorderColor; - background-color: lighten($stateDefaultBorderColor, 10%); - color: $inputGroupTextColor; - - &:first-child { - border-top-left-radius: $borderRadius; - border-bottom-left-radius: $borderRadius; - } - - &:last-child { - border-top-right-radius: $borderRadius; - border-bottom-right-radius: $borderRadius; - } - } - - .ui-button { - &:first-child { - border-top-left-radius: $borderRadius; - border-bottom-left-radius: $borderRadius; - } - - &:last-child { - border-top-right-radius: $borderRadius; - border-bottom-right-radius: $borderRadius; - } - } -} - -.ui-inputsearch { - display: flex; - .ui-inputtext{ - padding-left: .15rem; - padding-right: .4rem; - @extend .ui-corner-all-large; - } - .ui-button { - margin-left: -.35rem; - } -} - - -.ui-float-label input.ng-dirty.ng-invalid ~ label { - color: $stateErrorTextColor; -} - -.ui-autocomplete { - .ui-autocomplete-multiple-container:not(.ui-state-disabled) { - &:hover { - border-color: $stateHoverBorderColor; - } - - &.ui-state-focus { - border-color: $stateFocusBorderColor; - - } - } -} - -.ui-chips { - > ul:not(.ui-state-disabled) { - &:hover { - border-color: $stateHoverBorderColor; - } - - &.ui-state-focus { - border-color: $stateFocusBorderColor; - } - } -} - -.ui-button:focus, -.ui-button:enabled:hover, -.ui-fileupload-choose:not(.ui-state-disabled):hover { - outline: 0 none; - @include hover-element(); -} - -.ui-button:enabled:active, -.ui-fileupload-choose:not(.ui-state-disabled):active { - border-color: $stateActiveBorderColor; - background: $stateActiveBgColor; - color: $stateActiveTextColor; -} - -.ui-chkbox-box:not(.ui-state-disabled):not(.ui-state-active):hover { - @include hover-element(); -} - -.ui-radiobutton-box:not(.ui-state-disabled):not(.ui-state-active):hover { - @include hover-element(); -} - -.ui-dropdown .ui-dropdown-clear-icon { - color: lighten($inputTextColor, 40%); -} - -.ui-dropdown:not(.ui-state-disabled):hover { - @include hover-element(); -} - -.ui-dropdown-panel .ui-dropdown-item:not(.ui-state-highlight):hover { - @include hover-element(); -} - -.ui-listbox { - .ui-listbox-header { - .ui-listbox-filter-container { - .fa { - color: $inputTextColor; - } - } - } - - &:not(.ui-state-disabled) { - .ui-listbox-item:not(.ui-state-highlight):hover { - @include hover-element(); - } - } - - &.ui-state-disabled { - .ui-chkbox-box:not(.ui-state-active):hover { - border-color: $stateDefaultBorderColor; - background: $stateDefaultBgColor; - color: $stateDefaultTextColor; - } - } -} - -.ui-multiselect:not(.ui-state-disabled):hover { - @include hover-element(); -} - -.ui-multiselect-panel .ui-multiselect-item:not(.ui-state-highlight):hover { - @include hover-element(); -} - -.ui-multiselect-panel .ui-multiselect-close { - color: $headerIconTextColor; -} - -.ui-multiselect-panel .ui-multiselect-filter-container .fa { - color: $inputTextColor; -} - -.ui-spinner:not(.ui-state-disabled) .ui-spinner-button:enabled:hover { - @include hover-element(); -} - -.ui-spinner:not(.ui-state-disabled) .ui-spinner-button:enabled:active { - border-color: $stateActiveBorderColor; - background: $stateActiveBgColor; - color: $stateActiveTextColor; -} - -.ui-selectbutton .ui-button:not(.ui-state-disabled):not(.ui-state-active):hover { - @include hover-element(); -} - -.ui-togglebutton:not(.ui-state-disabled):not(.ui-state-active):hover { - @include hover-element(); -} - -.ui-paginator a:not(.ui-state-disabled):not(.ui-state-active):hover { - @include hover-element(); -} - -.ui-paginator a { - color: $stateDefaultTextColor; -} - -.ui-datatable { - .ui-rowgroup-header a { - color: $headerTextColor; - } - - .ui-sortable-column:not(.ui-state-active):hover { - background: $stateHoverBgColor; - color: $stateHoverTextColor; - } - - .ui-row-toggler { - color: $contentTextColor; - } - - tbody.ui-datatable-hoverable-rows { - > tr.ui-widget-content:not(.ui-state-highlight):hover { - cursor: pointer; - background: #ebf0f2; - } - } -} - -.ui-orderlist { - .ui-orderlist-item:not(.ui-state-highlight):hover { - @include hover-element(); - } -} - -.ui-picklist { - .ui-picklist-item:not(.ui-state-disabled):not(.ui-state-highlight):hover { - @include hover-element(); - } - - .ui-picklist-droppoint-highlight { - border-color: $stateHighlightBorderColor; - background: $stateHighlightBgColor; - color: darken($contentTextColor,1%); - - a { - color: darken($contentTextColor,1%); - } - } - - .ui-picklist-highlight { - border-color: $stateHighlightBorderColor; - color: darken($contentTextColor,1%); - - a { - color: darken($contentTextColor,1%); - } - } -} - -.ui-tree { - &.ui-treenode-dragover { - border-color: $stateHighlightBorderColor; - } - - .ui-treenode-content { - &.ui-treenode-selectable { - .ui-treenode-label:not(.ui-state-highlight):hover { - @include hover-element(); - } - } - - &.ui-treenode-dragover { - background: $stateActiveBgColor; - color: $stateActiveTextColor; - } - } - - &.ui-tree-horizontal { - .ui-treenode-content.ui-treenode-selectable { - .ui-treenode-label:not(.ui-state-highlight):hover { - background-color: inherit; - color: inherit; - } - - &:not(.ui-state-highlight):hover { - @include hover-element(); - } - } - } -} - -.ui-treetable { - .ui-treetable-row.ui-treetable-row-selectable:not(.ui-state-highlight):hover { - background: $stateHoverBgColor; - color: $stateHoverTextColor; - } -} - -.ui-organizationchart { - .ui-organizationchart-node-content { - &.ui-organizationchart-selectable-node:not(.ui-state-highlight):hover { - @include hover-element(); - } - } -} - -.ui-accordion { - .ui-accordion-header:not(.ui-state-active):not(.ui-state-disabled):hover { - @include hover-element(); - } -} - -.ui-fieldset { - &.ui-fieldset-toggleable { - .ui-fieldset-legend:hover { - @include hover-element(); - } - } -} - -.ui-panel { - .ui-panel-titlebar { - .ui-panel-titlebar-icon:hover { - @include hover-element(); - } - } -} - -.ui-tabview { - .ui-tabview-nav { - li { - &:not(.ui-state-active):not(.ui-state-disabled):hover { - @include hover-element(); - } - } - } -} - -.ui-dialog { - .ui-dialog-titlebar-icon { - color: $headerTextColor; - - &:hover { - @include hover-element(); - } - } -} - -.ui-sidebar { - .ui-sidebar-close { - color: $headerTextColor; - - &:hover { - @include hover-element(); - } - } -} - -.ui-overlaypanel { - .ui-overlaypanel-close:hover { - @include hover-element(); - } -} - -.ui-inplace { - .ui-inplace-display:hover { - @include hover-element(); - } -} - -.ui-breadcrumb { - a { - color: $headerTextColor; - } -} - -.ui-menuitem { - .ui-menuitem-link { - color: $contentTextColor; - - &:hover { - @include hover-element(); - border-color: transparent; - } - } - - &.ui-menuitem-active { - > .ui-menuitem-link { - @include hover-element(); - border-color: transparent; - } - } -} - -.ui-tabmenu { - .ui-tabmenu-nav { - li:not(.ui-state-active):hover { - @include hover-element(); - } - } -} - -.ui-steps { - .ui-steps-item:not(.ui-state-highlight):not(.ui-state-disabled):hover { - @include hover-element(); - } -} - -.ui-panelmenu { - .ui-panelmenu-header { - &:not(.ui-state-active):hover { - @include hover-element(); - border-color: $stateDefaultBorderColor; - - a { - color: $stateHoverTextColor; - } - } - - &.ui-state-active { - a { - color: $stateActiveTextColor; - } - } - } - - .ui-panelmenu-content { - .ui-menuitem-link { - color: $contentTextColor; - - &:hover { - @include hover-element(); - border-color: transparent; - } - } - } -} - -.ui-datepicker { - .ui-datepicker-header { - a { - color: $headerTextColor; - - &:hover { - @include hover-element(); - } - } - } - - .ui-datepicker-calendar { - td:not(.ui-state-disabled) { - a:hover { - @include hover-element(); - } - } - } -} - -.fc { - .fc-toolbar { - .fc-prev-button { - .ui-icon-circle-triangle-w { - margin-top: .3em; - @include icon_override("\f053"); - } - } - - .fc-next-button { - .ui-icon-circle-triangle-e { - margin-top: .3em; - @include icon_override("\f054"); - } - } - } -} - -.ui-rating { - a { - color: $inputTextColor; - } -} - -.ui-organizationchart { - .ui-organizationchart-line-down { - background-color: darken($contentBorderColor, 10%); - } - - .ui-organizationchart-line-left { - border-right: 1px solid darken($contentBorderColor, 10%); - } - - .ui-organizationchart-line-top { - border-top: 1px solid darken($contentBorderColor, 10%); - } - - .ui-organizationchart-node-content { - border-color: darken($contentBorderColor, 10%); - } - - .ui-organizationchart-node-content .ui-node-toggler { - color: darken($contentBorderColor, 10%); - } -} - -/* TurboTable */ -.ui-table { - .ui-table-thead > tr > th, - .ui-table-tfoot > tr > td { - background: $headerBgColor; - border: 1px solid $headerBorderColor; - color: $headerTextColor; - } - - .ui-table-tbody > tr { - background: $contentBgColor; - color: $contentTextColor; - - > td { - border: 1px solid $contentBorderColor; - background: inherit; - } - - &.ui-state-highlight { - background-color: $stateHighlightBgColor; - color: $stateHighlightTextColor; - } - - &.ui-contextmenu-selected { - background-color: lighten($stateHighlightBgColor, 20%); - color: $stateHighlightTextColor; - } - } - - .ui-sortable-column { - &.ui-state-highlight { - background-color: $stateHighlightBgColor; - color: $stateHighlightTextColor; - } - - &:not(.ui-state-highlight):hover { - background: $stateHoverBgColor; - color: $stateHoverTextColor; - } - } - - &.ui-table-hoverable-rows { - .ui-table-tbody > tr:not(.ui-state-highlight):hover { - cursor: pointer; - background: $stateHoverBgColor; - color: $stateHoverTextColor; - } - } -} - -@media ( max-width: 35em ) { - .ui-table-responsive .ui-table-tbody > tr { - border-top: 1px solid $contentBorderColor; - border-bottom: 1px solid $contentBorderColor; - } -} - -/* Row Reorder */ -.ui-table .ui-table-tbody > tr.ui-table-dragpoint-top > td { - box-shadow: inset 0 2px 0 0 $stateHighlightBgColor; -} - -.ui-table .ui-table-tbody > tr.ui-table-dragpoint-bottom > td { - box-shadow: inset 0 -2px 0 0 $stateHighlightBgColor; -} - -/* Validation */ -.ui-inputtext.ng-dirty.ng-invalid, -p-dropdown.ng-dirty.ng-invalid > .ui-dropdown, -p-autocomplete.ng-dirty.ng-invalid > .ui-autocomplete > .ui-inputtext, -p-calendar.ng-dirty.ng-invalid > .ui-calendar > .ui-inputtext, -p-chips.ng-dirty.ng-invalid > .ui-inputtext, -p-inputmask.ng-dirty.ng-invalid > .ui-inputtext, -p-checkbox.ng-dirty.ng-invalid .ui-chkbox-box, -p-radiobutton.ng-dirty.ng-invalid .ui-radiobutton-box, -p-inputswitch.ng-dirty.ng-invalid .ui-inputswitch, -p-listbox.ng-dirty.ng-invalid .ui-inputtext, -p-multiselect.ng-dirty.ng-invalid > .ui-multiselect, -p-spinner.ng-dirty.ng-invalid > .ui-inputtext, -p-selectbutton.ng-dirty.ng-invalid .ui-button, -p-togglebutton.ng-dirty.ng-invalid .ui-button { - border-bottom-color: $invalidInputBorderColor; -} - -/* Cornering */ -// .ui-corner-tl { -moz-border-radius-topleft: $borderRadius; -webkit-border-top-left-radius: $borderRadius; border-top-left-radius: $borderRadius; } -// .ui-corner-tr { -moz-border-radius-topright: $borderRadius; -webkit-border-top-right-radius: $borderRadius; border-top-right-radius: $borderRadius; } -// .ui-corner-bl { -moz-border-radius-bottomleft: $borderRadius; -webkit-border-bottom-left-radius: $borderRadius; border-bottom-left-radius: $borderRadius; } -// .ui-corner-br { -moz-border-radius-bottomright: $borderRadius; -webkit-border-bottom-right-radius: $borderRadius; border-bottom-right-radius: $borderRadius; } -// .ui-corner-top { -moz-border-radius-topleft: $borderRadius; -webkit-border-top-left-radius: $borderRadius; border-top-left-radius: $borderRadius; -moz-border-radius-topright: $borderRadius; -webkit-border-top-right-radius: $borderRadius; border-top-right-radius: $borderRadius; } -// .ui-corner-bottom { -moz-border-radius-bottomleft: $borderRadius; -webkit-border-bottom-left-radius: $borderRadius; border-bottom-left-radius: $borderRadius; -moz-border-radius-bottomright: $borderRadius; -webkit-border-bottom-right-radius: $borderRadius; border-bottom-right-radius: $borderRadius; } -// .ui-corner-right { -moz-border-radius-topright: $borderRadius; -webkit-border-top-right-radius: $borderRadius; border-top-right-radius: $borderRadius; -moz-border-radius-bottomright: $borderRadius; -webkit-border-bottom-right-radius: $borderRadius; border-bottom-right-radius: $borderRadius; } -// .ui-corner-left { -moz-border-radius-topleft: $borderRadius; -webkit-border-top-left-radius: $borderRadius; border-top-left-radius: $borderRadius; -moz-border-radius-bottomleft: $borderRadius; -webkit-border-bottom-left-radius: $borderRadius; border-bottom-left-radius: $borderRadius; } -// .ui-corner-all { -moz-border-radius: $borderRadius; -webkit-border-radius: $borderRadius; border-radius: $borderRadius; } diff --git a/dashboard/src/assets/components/themes/default/default.scss b/dashboard/src/assets/components/themes/default/default.scss deleted file mode 100644 index 7429b3be4..000000000 --- a/dashboard/src/assets/components/themes/default/default.scss +++ /dev/null @@ -1,926 +0,0 @@ -$color-primary: (normal: #438bd3, hover: #4596e8, active: #1f5fac); -$color-disabled: #c9d1d8; -$color-text: (primary: #657D95, secondary: #8893a6, tertary: #b9c3c8, auxiliary: #c9d1d8 ); -$color-title: (primary: #2e3039, secondary: #657D95); - -$color-splitline: #ecf0f2; -$color-panelbg: #f3f6f7; -$widget-border: (normal: #cfd7db, hover: #98a5bc, focus: #98a5bc, active: #98a5bc); -$widget-bg: (normal: #fdfdfd, hover: #ffffff, focus: #ffffff, active: #f1f1f1); - -//Alert Colors [type, border, backgroud, text] -$color-alert: (success, #3DCCA6, #F0FBF8, #3DCCA6 ), - (error, #FF4C4C, #FFF1F1, #FF4C4C ), - (info, #499DF2, #F1F7FE, #499DF2 ), - (warn, #FF8833, #FFF6EF, #FF8833 ), - (describe, #CACACA, #FFFFFF, #657D95); - -$border-radius: (small, 3px), (medium, 10px), (large, 20px); //@extend .ui-corner-bl-small; -@each $type, $size in $border-radius{ - $radius-pos: (tl, $size 0 0 0 ), - (tr, 0 $size 0 0 ), - (br, 0 0 $size 0 ), - (bl, 0 0 0 $size ), - (top, $size $size 0 0 ), - (right, 0 $size $size 0 ), - (left, $size 0 0 $size ), - (bottom, 0 0 $size $size ), - (all, $size); - @each $pos, $cornerStyle in $radius-pos{ - .ui-corner-#{ $pos }-#{ $type }{ - -moz-border-radius: $cornerStyle; - -webkit-border-radius: $cornerStyle;; - border-radius: $cornerStyle; - } - } -} - - -$fontFamily: "Roboto", "Trebuchet MS", Arial, Helvetica, sans-serif; -$fontSize: 0.14rem; -$borderRadius: 3px; -$disabledOpacity: 0.35; - -//Header -$headerBorderWidth: 1px; -$headerBorderColor: #d9d9d9; -$headerBgColor: #f6f7f9; -$headerTextColor: #1b1d1f; -$headerFontWeight: normal; -$headerIconTextColor: #1b1d1f; - -//Content -$contentBorderWidth: 1px; -$contentBorderColor: #D5D5D5; -$contentBgColor: #ffffff; -$contentTextColor: map-get($color-text, primary); - -//Default State -$stateDefaultBorderWidth: 1px; -$stateDefaultBorderColor: map-get($widget-border, normal); -$stateDefaultBgColor: map-get($widget-bg, normal); -$stateDefaultTextColor: map-get($color-text, primary); - -//Active State -$stateActiveBorderColor: map-get($widget-border, active); -$stateActiveBgColor: map-get($widget-bg, active); -$stateActiveTextColor: map-get($color-text, primary); - -//Highlight State -$stateHighlightBorderColor: map-get($color-primary, normal); -$stateHighlightBgColor: map-get($color-primary, normal); -$stateHighlightTextColor: #FFFFFF; - -//Focus State -$stateFocusBorderColor: map-get($widget-border, focus); -$stateFocusBgColor: map-get($widget-bg, focus); -$stateFocusTextColor: map-get($color-text, primary); - -//Error State -$stateErrorBorderColor: #f44336; -$stateErrorBgColor: #f5554a; -$stateErrorTextColor: #cd0a0a; - -//Hover State -$stateHoverBorderColor: map-get($widget-border, hover); -$stateHoverBgColor: map-get($widget-bg, hover); -$stateHoverTextColor: map-get($color-text, primary); - -//Forms -$inputBgColor: #ffffff; -$inputTextColor: map-get($color-text, primary); -$invalidInputBorderColor: #f44336; -$inputGroupTextColor: map-get($color-text, primary); - -@import '../_theme.scss'; - -//-------------------------------------------------------------// - -/* roboto-regular - latin */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 400; - src: url('./assets/components/themes/default/fonts/roboto-v15-latin-regular.eot'); /* IE9 Compat Modes */ - src: local('Roboto'), local('Roboto-Regular'), - url('./assets/components/themes/default/fonts/roboto-v15-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ - url('./assets/components/themes/default/fonts/roboto-v15-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */ - url('./assets/components/themes/default/fonts/roboto-v15-latin-regular.woff') format('woff'), /* Modern Browsers */ - url('./assets/components/themes/default/fonts/roboto-v15-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */ - url('./assets/components/themes/default/fonts/roboto-v15-latin-regular.svg#Roboto') format('svg'); /* Legacy iOS */ -} - -html, body, div, ul, li, p, input, textarea, select, h1, h2, h3, h4, h5{ - margin: 0; - padding: 0; -} -html, body { - box-sizing: border-box; -} -html { - height: 100%; - font-size: 625%; /*1em = 100px*/ -} - -body { - font-family: 'Roboto', "Trebuchet MS", Arial, Helvetica, sans-serif; - font-weight: normal; - font-size: $fontSize; - color: map-get($color-text, primary); - background-color: #fff; - height: 100%; - overflow: auto; - -webkit-font-smoothing: antialiased; -} - -h1,h2,h3,h4,h5{ - font-weight: 500; -} - -h1{ font-size: 0.24rem; line-height: 0.28rem;} - -h2{ font-size: 0.20rem; line-height: 0.24rem;} - -h3{ font-size: 0.18rem; line-height: 0.24rem;} - -h4{ font-size: 0.16rem; line-height: 0.22rem;} - -h5{ font-size: 0.14rem; line-height: 0.22rem;} - -ol,ul,li{ - list-style: none; - list-style-type: none; -} - -input, textarea, keygen, select, button{ - font-family: inherit; - font-size: inherit; - font-weight: inherit; - display: block; -} - -input::-ms-clear{ display: none; } - -input:-ms-input-placeholder, textarea:-ms-input-placeholder{ - color: #666666; -} - -fieldset{ - border: 0; - padding: 0; - margin: 0; -} - -textarea{ - resize: none; -} - -::selection{ - background: #1f89ce; - color: #fff; -} - -::-moz-selection{ - background: #1f89ce; - color: #fff; -} - -::-webkit-selection{ - background: #1f89ce; - color: #fff; -} - -a{ - color: map-get($color-primary, normal); - text-decoration: none; - cursor: pointer; - - &:hover,&:active{ - color: map-get($color-primary, active); - } - &:disabled{ - color: $color-disabled; - cursor: default; - } -} - -.ui-widget-content a{ - color: map-get($color-primary, normal); -} - - -p{ - line-height: 1.5; - color: map-get($color-text, primary); - word-wrap: normal; - word-break: break-word; -} - -/* Validation */ -.ui-inputtext.ng-touched.ng-invalid, -p-dropdown.ng-dirty.ng-invalid > .ui-dropdown, -p-autocomplete.ng-dirty.ng-invalid > .ui-autocomplete > .ui-inputtext, -p-calendar.ng-touched.ng-invalid > .ui-inputtext, -p-chips.ng-dirty.ng-invalid > .ui-inputtext, -p-inputmask.ng-dirty.ng-invalid > .ui-inputtext, -p-checkbox.ng-dirty.ng-invalid .ui-chkbox-box, -p-radiobutton.ng-dirty.ng-invalid .ui-radiobutton-box, -p-inputswitch.ng-dirty.ng-invalid .ui-inputswitch, -p-listbox.ng-dirty.ng-invalid .ui-inputtext, -p-multiselect.ng-dirty.ng-invalid > .ui-multiselect, -p-spinner.ng-dirty.ng-invalid > .ui-inputtext, -p-selectbutton.ng-dirty.ng-invalid .ui-button, -p-togglebutton.ng-dirty.ng-invalid .ui-button { - border-color: $invalidInputBorderColor; -} - -/* Mask style */ -.mask-background{ - z-index: 100000000; - background: #666; - opacity: .30; - filter: Alpha(opacity=30); - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; -} - -/* loading */ -.M-loading-text{ - margin: auto; - font-size: 16px; - text-align: left; - margin-top: 30px; -} -.M-loading-content{ - position:fixed; - top: 40%; - left: 49%; - margin: auto; - text-align: center; - z-index: 1000; -} -.M-loading{ - -webkit-transform: translateZ(0); - transform: rotate(-90deg); - -ms-transform: rotate(-70deg); /* IE 9 */ - -moz-transform: rotate(-90deg); /* Firefox */ - -webkit-transform: rotate(-90deg); /* Safari and Chrome */ - -o-transform: rotate(-90deg); - width: 30px; - height: 30px; - margin-left: 20px; -} -.M-load{ - opacity: 0; - font-size: 20px; - text-indent:-9999em; - overflow: hidden; - width: 21px; - height: 21px; - border-radius: 50%; - position: fixed; - transform: rotate(-90deg); - -ms-transform: rotate(-90deg); /* IE 9 */ - -moz-transform: rotate(-90deg); /* Firefox */ - -webkit-transform: rotate(-90deg); /* Safari and Chrome */ - -o-transform: rotate(-90deg); - animation: load6 1300ms cubic-bezier(0.4, 0, 0.2, 1) infinite; - transform: translateZ(0); -} -.M-loader{ - box-shadow: 0 -0.8em 0 -0.37em #3399ff; - animation-delay:100ms; -} -.M-loader1{ - box-shadow: 0 -0.8em 0 -0.37em #4da6ff; - animation-delay:200ms; -} -.M-loader3{ - box-shadow: 0 -0.8em 0 -0.37em #66b3ff; - animation-delay:300ms; -} -.M-loader3{ - box-shadow: 0 -0.8em 0 -0.37em #80bfff; - animation-delay:400ms; -} -.M-loader4{ - box-shadow: 0 -0.8em 0 -0.37em #99ccff; - animation-delay:500ms; -} - -@keyframes load6 { - 0%{ - opacity: 0; - -ms-transform: rotate(0deg); - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 15%{ - opacity: 1; - } - 75%{ - opacity: 1; - } - 76%{ - opacity: 0; - } - 100%{ - -ms-transform: rotate(360deg); - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - opacity: 0; - } -} - -//-------------------------------------------------------------// - -.ui-widget-header { - background: #f6f7f9 0 0 repeat-x; /* Old browsers */ - background: -moz-linear-gradient(top, #f6f7f9 0%, #ebedf0 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f6f7f9), color-stop(100%,#ebedf0)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #f6f7f9 0%,#ebedf0 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #f6f7f9 0%,#ebedf0 100%); /* Opera11.10+ */ - background: -ms-linear-gradient(top, #f6f7f9 0%,#ebedf0 100%); /* IE10+ */ - background: linear-gradient(to bottom, #f6f7f9 0%,#ebedf0 100%); /* W3C */ -} - -.ui-accordion { - .ui-accordion-header { - background: $headerBgColor; - border-top: 1px solid $headerBorderColor; - - a { - color: $headerTextColor; - } - - &:not(.ui-state-active):not(.ui-state-disabled):hover { - background: #ededf0; - } - - &.ui-state-active { - background: #ffffff; - border-left-color: transparent; - border-right-color: transparent; - border-bottom-color: transparent; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - } - } - - .ui-accordion-content { - border: 0 none; - } -} - -/* Tabview */ -.ui-tabview { - &.ui-widget-content { - border: 0 none; - } - - &.ui-tabview-top > .ui-tabview-nav { - background: transparent; - - > li { - &.ui-state-default { - background: none; - border:none; - a { - color: map-get($color-title, secondary); - } - } - - &.ui-state-active, - &:not(.ui-state-active):not(.ui-state-disabled):hover { - background: none; - a { - color: map-get($color-title, primary); - } - } - - &.ui-tabview-selected{ - border-bottom: 0.04rem solid map-get($color-primary, normal); - } - } - } -} - -/* Spinner */ -.ui-spinner:not(.ui-state-disabled) .ui-spinner-button:enabled:hover { - border: 1px solid #1f89ce; - background: #1f89ce; - outline: 0 none; - color: #ffffff; -} - -.ui-spinner:not(.ui-state-disabled) .ui-spinner-button:enabled:active { - border: 1px solid #156090; - background: #186ba0; - color: #ffffff; -} - -.ui-slider { position: relative; text-align: left; background: #838688; border: none; -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset; -moz-box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset; box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset;} -.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 17px !important; height: 21px !important; cursor: default; background: url("./assets/components/themes/default/images/slider_handles.png") 0 0 no-repeat; outline: none; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; border: none; } -.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background: #14a4ff; -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset; -moz-box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset; box-shadow: 0 1px 3px rgba(0,0,0,0.6) inset; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } -.ui-slider .ui-slider-handle.ui-state-active { background-position: -17px 0; } - -.ui-slider-horizontal { height: 6px; } -.ui-slider-horizontal .ui-slider-handle { top: -2px !important; margin-left: -.6em; } -.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } -.ui-slider-horizontal .ui-slider-range-min { left: 0; } -.ui-slider-horizontal .ui-slider-range-max { right: 0; } - -.ui-slider-vertical { width: .8em; height: 100px; } -.ui-slider-vertical .ui-slider-handle { left: -.1em !important; margin-left: 0; margin-bottom: -.6em; } -.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } -.ui-slider-vertical .ui-slider-range-min { bottom: 0; } -.ui-slider-vertical .ui-slider-range-max { top: 0; } - -.ui-progressbar { - &.ui-progressbar-determinate { - .ui-progressbar-value { - border: 0 none; - background: #8ec5fc; - } - - .ui-progressbar .ui-progressbar-label { - color: #222222; - } - } - - &.ui-progressbar-indeterminate { - background: #8ec5fc; - - .ui-progressbar-value { - border: 0 none; - background-color: $stateHighlightBgColor; - } - } -} - - - -.ui-widget-header .ui-button, -.ui-widget-content .ui-button, -.ui-widget.ui-button, -.ui-button { - // color: #FFFFFF; - // background: #2399e5; - // -webkit-transition: background-color .2s; - // -moz-transition: background-color .2s; - // transition: background-color .2s; - - // &:enabled:hover, - // &:focus { - // border: 1px solid #1f89ce; - // background: #1f89ce; - // outline: 0 none; - // color: #ffffff; - // } - - // &:enabled:active { - // border: 1px solid #156090; - // background: #186ba0; - // color: #ffffff; - // } - // &.ui-button-icon-only{ - // border: none; - // background: none; - // &:hover,&:active{ - // border: none; - // background: none; - // box-shadow:none; - // } - // } -} - -.ui-fileupload-choose:not(.ui-state-disabled):hover, -.ui-fileupload-choose.ui-state-focus { - border: 1px solid #1f89ce; - background: #1f89ce; - outline: 0 none; - color: #ffffff; -} - -.ui-fileupload-choose:not(.ui-state-disabled):active { - border: 1px solid #156090; - background: #186ba0; - color: #ffffff; -} - -/* Checkbox and Radio */ -.ui-chkbox-box.ui-state-active, -.ui-radiobutton-box.ui-state-active { - border: 1px solid #156090; - background: #186ba0; - color: #FFFFFF; -} - -.ui-chkbox-box.ui-state-focus, -.ui-radiobutton-box.ui-state-focus { - -moz-box-shadow: 0px 0px 5px #1f89ce; - -webkit-box-shadow: 0px 0px 5px #1f89ce; - box-shadow: 0px 0px 5px #1f89ce; -} - -.ui-chkbox-box.ui-state-focus.ui-state-active { - background: #186ba0; -} - -/* Inputs */ -.ui-inputtext { - background: #ffffff; - color: #222222; - -webkit-transition: .2s; - -moz-transition: .2s; - transition: .2s; -} - -.ui-inputtext.ui-state-focus, -.ui-inputtext:focus { - -moz-box-shadow: 0px 0px 5px #1f89ce; - -webkit-box-shadow: 0px 0px 5px #1f89ce; - box-shadow: 0px 0px 5px #1f89ce; -} - -/* InputSwitch */ -.ui-inputswitch-on { - background: #186ba0 !important; - color: #ffffff !important; -} - -.ui-paginator .ui-paginator-pages .ui-paginator-page.ui-state-active { - background: #1f5fac; - color: #ffffff; - border-color: #1f5fac; -} - -/* DataTable */ -.ui-datatable { - th { - &.ui-state-default { - background: #dfe6e9; - } - - &.ui-sortable-column:not(.ui-state-active):hover { - background: #dfe6e9; - } - - &.ui-state-active { - background: #186ba0; - color: #ffffff; - } - &.table-col-expander{ - width: .40rem; - } - &.table-col-selection{ - width: .40rem; - } - } - - tbody { - > tr.ui-widget-content { - - &.ui-datatable-odd { - background-color: #f5f8f9; - } - - &.ui-datatable-even { - background-color: #ffffff; - } - - &.ui-state-highlight { - background-color: #ebf0f2; - color: #657D95; - } - } - } - - tfoot { - td { - &.ui-state-default { - background: #ebedf0; - border-color: #d9d9d9; - } - } - } - - .ui-datatable-scrollable-header{ - background: #dfe6e9; - } - - .ui-datatable-tablewrapper, .ui-datatable-scrollable-body{ - border-bottom:1px solid #dfe6e9; - } - - .ui-paginator-bottom{ - border: none; - background: none; - text-align: left; - - &.ui-paginator{ - padding: .15rem 0; - } - } - - -} - -/* TurboTable */ -.ui-table { - .ui-table-thead > tr > th, - .ui-table-tfoot > tr > td { - background: #ebedf0; - border-color: #d9d9d9; - } - - .ui-sortable-column:not(.ui-state-highlight):hover { - background: #d3d5d8; - border-color: #d9d9d9; - } - - .ui-table-tbody > tr:nth-child(even) { - background-color: #fafafb; - - &.ui-state-highlight { - background-color: $stateHighlightBgColor; - color: $stateHighlightTextColor; - } - - &.ui-contextmenu-selected { - background-color: lighten($stateHighlightBgColor, 20%); - color: $stateHighlightTextColor; - } - } -} - -/* Panel */ -.ui-panel.ui-widget { - padding: 0; - - .ui-panel-titlebar.ui-corner-all { - -moz-border-radius-bottom-left: 0; - -webkit-border-bottom-left-radius: 0; - border-bottom-left-radius: 0; - -moz-border-radius-bottom-right: 0; - -webkit-border-bottom-right-radius: 0; - border-bottom-right-radius: 0; - } - - .ui-panel-titlebar { - border-width: 0 0 1px 0; - } - - .ui-panel-titlebar-icon span { - position: relative; - top: 1px; - } - -} - -/* TreeTable */ -.ui-treetable { - th.ui-state-default { - background: #ebedf0; - border-color: #d9d9d9; - } -} - -/* ButtonSet */ -.ui-togglebutton.ui-button.ui-state-default, -.ui-selectbutton .ui-button.ui-state-default { - border: 1px solid #d6d6d6; - background: #ffffff; - font-weight: normal; - color: #555555; -} - -.ui-togglebutton.ui-button.ui-state-hover,.ui-togglebutton.ui-button.ui-state-focus, -.ui-selectbutton .ui-button.ui-state-hover,.ui-selectbutton .ui-button.ui-state-focus, .ui-selectbutton .ui-button:focus { - border: 1px solid #c0c0c0; - background: #eeeeee; - font-weight: normal; - color: #212121; -} - -.ui-togglebutton.ui-button.ui-state-focus, -.ui-selectbutton .ui-button.ui-state-focus.ui-state-active, -.ui-selectbutton .ui-button.ui-state-active:focus { - -moz-box-shadow: 0px 0px 5px #1f89ce; - -webkit-box-shadow: 0px 0px 5px #1f89ce; - box-shadow: 0px 0px 5px #1f89ce; -} - -.ui-togglebutton.ui-button.ui-state-active, -.ui-selectbutton .ui-button.ui-state-active { - border: 1px solid #156090; - background: #186ba0; - color: #FFFFFF; -} - -.ui-multiselect { - .ui-multiselect-label { - background-color: #ffffff; - } -} - -.ui-dropdown.ui-state-focus, .ui-multiselect.ui-state-focus { - -moz-box-shadow: 0px 0px 5px #1f89ce; - -webkit-box-shadow: 0px 0px 5px #1f89ce; - box-shadow: 0px 0px 5px #1f89ce; -} - -/* Growl */ -.ui-growl-item-container.ui-state-highlight { - &.ui-growl-message-info { - background-color: #2196f3; - border-color :#2196f3; - } - - &.ui-growl-message-error { - background-color: #f44336; - border-color :#f44336; - } - - &.ui-growl-message-warn { - background-color: #FFB300; - border-color :#FFB300; - } - - &.ui-growl-message-success { - background-color: #4CAF50; - border-color :#4CAF50; - } -} - -/* TabMenu */ -.ui-tabmenu { - border: 0 none; - - .ui-tabmenu-nav { - background: none; - - > li { - &.ui-state-default { - background: #f6f7f9; - } - - &.ui-state-active { - background: #ffffff; - font-weight: normal; - color: #555555; - } - - &:not(.ui-state-active):not(.ui-state-disabled):hover { - background: #ededf0; - } - } - } -} - -/* Menus */ -.ui-menu, -.ui-menubar, .ui-menubar .ui-submenu-list, -.ui-tieredmenu, .ui-tieredmenu .ui-submenu-list, -.ui-slidemenu, .ui-slidemenu .ui-submenu-list, -.ui-contextmenu, .ui-contextmenu .ui-submenu-list, -.ui-megamenu { - color: #1b1d1f; - background: #f6f7f9 0 0 repeat-x; /* Old browsers */ - background: -moz-linear-gradient(top, #f6f7f9 0%, #ebedf0 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f6f7f9), color-stop(100%,#ebedf0)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #f6f7f9 0%,#ebedf0 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #f6f7f9 0%,#ebedf0 100%); /* Opera11.10+ */ - background: -ms-linear-gradient(top, #f6f7f9 0%,#ebedf0 100%); /* IE10+ */ - background: linear-gradient(to bottom, #f6f7f9 0%,#ebedf0 100%); /* W3C */ -} - -.ui-menu .ui-menuitem > .ui-menuitem-link:hover, -.ui-menubar .ui-menuitem > .ui-menuitem-link:hover, -.ui-tieredmenu .ui-menuitem > .ui-menuitem-link:hover, -.ui-slidemenu .ui-menuitem > .ui-menuitem-link:hover, -.ui-contextmenu .ui-menuitem > .ui-menuitem-link:hover, -.ui-megamenu .ui-menuitem > .ui-menuitem-link:hover { - background-color: #a6a6a6; - color: #ffffff; -} - -.ui-menu .ui-menuitem.ui-menuitem-active > .ui-menuitem-link, -.ui-menubar .ui-menuitem.ui-menuitem-active > .ui-menuitem-link, -.ui-tieredmenu .ui-menuitem.ui-menuitem-active > .ui-menuitem-link, -.ui-slidemenu .ui-menuitem.ui-menuitem-active > .ui-menuitem-link, -.ui-contextmenu .ui-menuitem.ui-menuitem-active > .ui-menuitem-link, -.ui-megamenu .ui-menuitem.ui-menuitem-active > .ui-menuitem-link { - background-color: #a6a6a6; - color: #ffffff; -} - -/* PanelMenu */ -.ui-panelmenu .ui-panelmenu-header.ui-state-active, -.ui-panelmenu .ui-panelmenu-header.ui-state-active a { - border-color: #156090; - background: #186ba0; - color: #FFFFFF; -} - -/* DatePicker */ -.ui-datepicker.ui-widget { - padding: 0; - - .ui-datepicker-header { - -webkit-border-radius: 0px; - -moz-border-radius: 0px; - border-radius: 0px; - border-top: 0 none; - border-left: 0 none; - border-right: 0 none; - - a { - &:hover { - border-width: 1px; - } - } - } - - .ui-datepicker-calendar { - margin: 0; - - thead th { - background-color: #f6f8fa; - padding: 8px; - } - - td { - border-bottom: 1px solid rgba(213, 213, 213, 0.5); - padding: 0; - - a { - border: 0 none; - text-align: center; - padding: 8px; - - &.ui-state-highlight { - background-color: #d6d6d6; - color: #212121; - } - - &.ui-state-active { - background-color: #186ba0; - color: #ffffff; - } - } - } - - tr:last-child td { - border-bottom: 0 none; - } - } - - .ui-timepicker { - border-bottom: 0 none; - border-left: 0 none; - border-right: 0 none; - -moz-border-radius: 0; - -webkit-border-radius: 0; - border-radius: 0; - } - - &.ui-datepicker-timeonly { - .ui-timepicker { - border-top: 0 none; - } - } -} - -/* Steps */ -.ui-steps .ui-steps-item.ui-state-highlight .ui-menuitem-link { - color: #ffffff; -} - -/* Dialog */ -.ui-dialog.ui-widget .ui-dialog-titlebar { - padding: 1em 1.5em; -} - -.ui-dialog.ui-widget .ui-dialog-titlebar .ui-dialog-title { - font-size: 1.25em; -} - -.ui-dialog.ui-widget .ui-dialog-content { - padding: 1em 1.5em; -} - -/* Schedule */ -.fc { - .fc-button-group { - .ui-state-active { - border: 1px solid #156090; - background: #186ba0; - color: #ffffff; - } - } -} diff --git a/dashboard/src/assets/components/themes/default/fonts/roboto-v15-latin-regular.eot b/dashboard/src/assets/components/themes/default/fonts/roboto-v15-latin-regular.eot deleted file mode 100644 index d26bc8f519b5b90a0639f82a18bfef133599196a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16227 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 v#g4%>=-%`rNTT$Q3+IGsv=@uepU+g& - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dashboard/src/assets/components/themes/default/fonts/roboto-v15-latin-regular.ttf b/dashboard/src/assets/components/themes/default/fonts/roboto-v15-latin-regular.ttf deleted file mode 100644 index 7b25f3ce940cbba3001420d38b7d0f12fb7f2142..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32652 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 N6K0jQ!xePm{|7p>-q!#C diff --git a/dashboard/src/assets/components/themes/default/fonts/roboto-v15-latin-regular.woff b/dashboard/src/assets/components/themes/default/fonts/roboto-v15-latin-regular.woff deleted file mode 100644 index 941dfa4bae83483cf1784641063ce1deceda1406..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18520 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 diff --git a/dashboard/src/assets/components/themes/default/images/icons_16.png b/dashboard/src/assets/components/themes/default/images/icons_16.png deleted file mode 100644 index 09d6ec7f8400c4bcc654498766e98c431cadb61c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4020 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 QzV{z(Wp)Z#YT`xxA2To<0ssI2 diff --git a/dashboard/src/assets/components/themes/default/images/slider_handles.png b/dashboard/src/assets/components/themes/default/images/slider_handles.png deleted file mode 100644 index 0fddde5fe8644ac598faa60941e47ecd8e995e32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1945 zcmaJ?eOOcV9-mu5yy!$S$CNq^^8&i2!FK8kuw+2|+BckLR28t*o0SSW3m#%~X7eo;PIy15R$K{^qIp_ECd_JG=+vj;s zeq2n%d{?R~fk2oa6)BY9D-C}azvP5}eR%vXeDT88Bx3RC7R)R+AcQa_sz87!tvm&h zAaZ4T>ScsaAdmpHG!aV_M?)~GWyl>EhDEE#*#rVV)S{Qe+Yk&;ASr5H2yN)}SsI{L zhR_m%#GqIoj;Pd;83rUiBSs2mY=eW9w9q#Jz6HVsv~t zfTs{_TL|s1q!Pt(KsahZfFK4)hd~Yqa99jhKp>aPT?Mc~7RUtIOctBY;z9vz2n2y= z4-JoIP;P-FLeaBW_$h>@!Z1C=WSY%phB<(N8d8|7;NW0~2AfUC5p-j^4wGBxI-}35 zf)Fvn2DKhjqdLH$C|96qSO^Wz^sf@M`scDbfgB|alUll~O0LGj8z_yf zzkh$YP2&4;cF|=kbxH9hcQ@bV!fC=1Vomfylg_$QaA=0Ot~7@2;#L8=Rfq(N7kZ1_ zi;2|2VTAOFqFmrNHCWwh+}?V3Qwn8&Mselin|-6xgOh33zAu^h_bJC`=6Q1Zu+%@xv*3q8IA+b;JO4<@z2|+js;Zt782E5we0=<>;>-UkF7`|_ znT`m`KXi54GvRJ;7#kZiH#IexDCayX*f{L^iF8pmV$n_=OXPwtTrZZ1oyE612%J7Qr0V?;> zL7xTg??)opejT3^+;TuTM@+rhId>sMB|k?boeFV?a#nk37hg^Kn#laAmvN+oioZ zSBcqdHnKWatIgA&>F1rT6L0miBtNksD8so}d&H`EImhDy;>=0j(YG>IEbd(mL7Q@?(5e8h z%*@Pc7>3Q~ho_b{-o1Nw>du`zLwKDJYHkk>4t89>UR2;c(sAwDwd`HPE!~O@_xGn} zX09fk6YyW1S!9yMB~ji0M+yoGwk9Xr?+s97GFhpor{_Bd%icLZn8McFD8HeWiu|itm`|H9;jVlbyNCU54gBC z2pUf13u)xWzLu7jE{jKzN8Yr3^lDG3_{!ML7khJ)@{)EX*&or@J$QLy@kA86Q1J>M zO=j?eDk@I&80tlT4n7$HB|W7N4$UR^Y?rE zpU3X44c&ibs=lSm{qzFqDDPgg5K0J~eAl`%cHDQw;IEK*RJtuXSLZ8B=scTM{^_=L z&A)u|dk=|A)*pQm9f+8gFCE)R5Amz$3<7O~XSi@HRR5^&DDSblEc8VR;m}4|>ejpq R4;(+ss5LRd8bR{zKLL|S9X|j7 diff --git a/dashboard/src/assets/components/themes/default/images/slider_handles@2x.png b/dashboard/src/assets/components/themes/default/images/slider_handles@2x.png deleted file mode 100644 index d8c901ec80cc8ad5aaa9142d0d5cda4c12471f91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3603 zcmaJ^c{r5o-ydr;mP~eKnGv##Sq#QttYa7k5gI9snF(QrF&IR)%2xJ~6vaKA-RBd*9#txvnQ;zl*)3*lsZZ03b

        '; ?> \ No newline at end of file diff --git a/dashboard/tsconfig-aot.json b/dashboard/tsconfig-aot.json deleted file mode 100644 index 41466c267..000000000 --- a/dashboard/tsconfig-aot.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "compilerOptions": { - "outDir": "components", - "rootDir": "src/app/components", - "target": "es5", - "module": "es2015", - "baseUrl": "src", - "moduleResolution": "node", - "sourceMap": true, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "removeComments": false, - "noImplicitAny": false, - "suppressImplicitAnyIndexErrors": true, - "lib": ["dom","es6"] - }, - "include": [ - "src/app/components/**/*" - ], - "angularCompilerOptions": { - "genDir": "aot", - "skipMetadataEmit" : false - } -} \ No newline at end of file diff --git a/dashboard/tsconfig-release.json b/dashboard/tsconfig-release.json deleted file mode 100644 index 72ddd76b1..000000000 --- a/dashboard/tsconfig-release.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "compileOnSave": false, - "compilerOptions": { - "outDir": "./components", - "baseUrl": "src", - "rootDir": "src/app/components", - "sourceMap": true, - "declaration": true, - "moduleResolution": "node", - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "target": "es5", - "typeRoots": [ - "node_modules/@types" - ], - "lib": [ - "es2016", - "dom" - ] - }, - "include": [ - "src/app/components/**/*" - ] -} diff --git a/dashboard/tsconfig.json b/dashboard/tsconfig.json deleted file mode 100644 index a35a8ee3a..000000000 --- a/dashboard/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compileOnSave": false, - "compilerOptions": { - "outDir": "./dist/out-tsc", - "baseUrl": "src", - "sourceMap": true, - "declaration": false, - "moduleResolution": "node", - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "target": "es5", - "typeRoots": [ - "node_modules/@types" - ], - "lib": [ - "es2016", - "dom" - ] - } -} diff --git a/dashboard/tslint.json b/dashboard/tslint.json deleted file mode 100644 index 0db5751c7..000000000 --- a/dashboard/tslint.json +++ /dev/null @@ -1,142 +0,0 @@ -{ - "rulesDirectory": [ - "node_modules/codelyzer" - ], - "rules": { - "arrow-return-shorthand": true, - "callable-types": true, - "class-name": true, - "comment-format": [ - true, - "check-space" - ], - "curly": true, - "eofline": true, - "forin": true, - "import-blacklist": [ - true, - "rxjs" - ], - "import-spacing": true, - "indent": [ - true, - "spaces" - ], - "interface-over-type-literal": true, - "label-position": true, - "max-line-length": [ - true, - 140 - ], - "member-access": false, - "member-ordering": [ - true, - { - "order": [ - "static-field", - "instance-field", - "static-method", - "instance-method" - ] - } - ], - "no-arg": true, - "no-bitwise": true, - "no-console": [ - true, - "debug", - "info", - "time", - "timeEnd", - "trace" - ], - "no-construct": true, - "no-debugger": true, - "no-duplicate-super": true, - "no-empty": false, - "no-empty-interface": true, - "no-eval": true, - "no-inferrable-types": [ - true, - "ignore-params" - ], - "no-misused-new": true, - "no-non-null-assertion": true, - "no-shadowed-variable": true, - "no-string-literal": false, - "no-string-throw": true, - "no-switch-case-fall-through": true, - "no-trailing-whitespace": true, - "no-unnecessary-initializer": true, - "no-unused-expression": true, - "no-use-before-declare": true, - "no-var-keyword": true, - "object-literal-sort-keys": false, - "one-line": [ - true, - "check-open-brace", - "check-catch", - "check-else", - "check-whitespace" - ], - "prefer-const": true, - "quotemark": [ - true, - "single" - ], - "radix": true, - "semicolon": [ - true, - "always" - ], - "triple-equals": [ - true, - "allow-null-check" - ], - "typedef-whitespace": [ - true, - { - "call-signature": "nospace", - "index-signature": "nospace", - "parameter": "nospace", - "property-declaration": "nospace", - "variable-declaration": "nospace" - } - ], - "typeof-compare": true, - "unified-signatures": true, - "variable-name": false, - "whitespace": [ - true, - "check-branch", - "check-decl", - "check-operator", - "check-separator", - "check-type" - ], - "directive-selector": [ - true, - "attribute", - "app", - "camelCase" - ], - "component-selector": [ - true, - "element", - "app", - "kebab-case" - ], - "use-input-property-decorator": true, - "use-output-property-decorator": true, - "use-host-property-decorator": true, - "no-input-rename": true, - "no-output-rename": true, - "use-life-cycle-interface": true, - "use-pipe-transform-interface": true, - "component-class-suffix": true, - "directive-class-suffix": true, - "no-access-missing-member": true, - "templates-use-public": true, - "invoke-injectable": true - } -} From 57b54a5f7687b6fdce7ada5d289c4bb5556214c3 Mon Sep 17 00:00:00 2001 From: jerry Date: Thu, 29 Nov 2018 06:39:38 +0000 Subject: [PATCH 19/20] update go version from go1.9.2 to go1.11.1 --- script/devsds/bootstrap.sh | 39 +++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) mode change 100644 => 100755 script/devsds/bootstrap.sh diff --git a/script/devsds/bootstrap.sh b/script/devsds/bootstrap.sh old mode 100644 new mode 100755 index 406579eb0..9dff79858 --- a/script/devsds/bootstrap.sh +++ b/script/devsds/bootstrap.sh @@ -22,7 +22,7 @@ OPT_DIR=/opt/opensds mkdir -p $OPT_DIR # Golang version -GOLANG_VERSION=${GOLANG_VERSION:-1.9.2} +MINIMUM_GO_VERSION=${MINIMUM_GO_VERSION:-go1.11.1} GOENV_PROFILE=${GOENV_PROFILE:-/etc/profile.d/goenv.sh} # Log file @@ -49,16 +49,25 @@ log OpenSDS bootstrap starting ... # load profile source /etc/profile -# Install Golang environment -if ! which go &>/dev/null; then + +# if not found, install it. +if [[ -z "$(which go)" ]]; then log "Golang is not exist, downloading..." - wget https://storage.googleapis.com/golang/go${GOLANG_VERSION}.linux-amd64.tar.gz -O $OPT_DIR/go${GOLANG_VERSION}.linux-amd64.tar.gz > /dev/null - log "tar xzf $OPT_DIR/go${GOLANG_VERSION}.linux-amd64.tar.gz -C /usr/local/" - tar xzf $OPT_DIR/go${GOLANG_VERSION}.linux-amd64.tar.gz -C /usr/local/ - echo 'export GOROOT=/usr/local/go' > $GOENV_PROFILE - echo 'export GOPATH=$HOME/gopath' >> $GOENV_PROFILE - echo 'export PATH=$PATH:$GOROOT/bin:$GOPATH/bin' >> $GOENV_PROFILE - source $GOENV_PROFILE + wget https://storage.googleapis.com/golang/${MINIMUM_GO_VERSION}.linux-amd64.tar.gz -O $OPT_DIR/${MINIMUM_GO_VERSION}.linux-amd64.tar.gz > /dev/null + log "tar xzf $OPT_DIR/${MINIMUM_GO_VERSION}.linux-amd64.tar.gz -C /usr/local/" + tar xzf $OPT_DIR/${MINIMUM_GO_VERSION}.linux-amd64.tar.gz -C /usr/local/ + echo 'export GOROOT=/usr/local/go' > $GOENV_PROFILE + echo 'export GOPATH=$HOME/gopath' >> $GOENV_PROFILE + echo 'export PATH=$PATH:$GOROOT/bin:$GOPATH/bin' >> $GOENV_PROFILE + source $GOENV_PROFILE +fi + +# verify go version +IFS=" " read -ra go_version <<< "$(go version)" +if [[ "${MINIMUM_GO_VERSION}" != $(echo -e "${MINIMUM_GO_VERSION}\n${go_version[2]}" | sort -s -t. -k 1,1 -k 2,2n -k 3,3n | head -n1) && "${go_version[2]}" != "devel" ]]; then + log_error "Detected go version: ${go_version[*]}, OpenSDS requires ${MINIMUM_GO_VERSION} or greater." + log_error "Please remove golang old version ${go_version[2]}, bootstrap will install ${MINIMUM_GO_VERSION} automatically" + exit 2 fi GOPATH=${GOPATH:-$HOME/gopath} @@ -68,16 +77,16 @@ mkdir -p ${OPENSDS_ROOT} cd ${OPENSDS_ROOT} if [ ! -d ${OPENSDS_DIR} ]; then - log "Download the OpenSDS source code." - git clone https://github.com/opensds/opensds.git -b master + log "Downloading the OpenSDS source code..." + git clone https://github.com/opensds/opensds.git -b master fi cd ${OPENSDS_DIR} if [ ! -d ${OPENSDS_DIR}/build ]; then + log "Building OpenSDS ..." sudo apt-get update > /dev/null - sudo apt-get install librados-dev librbd-dev -y > /dev/null - log "Build OpenSDS ..." - make + sudo apt-get install librados-dev librbd-dev -y > /dev/null + make fi log OpenSDS bootstrapped successfully. you can execute 'source /etc/profile' to load golang ENV. From 1c25b8483365f163d8adf6729615961205e4d765 Mon Sep 17 00:00:00 2001 From: PengYiOfOpenSDS Date: Thu, 29 Nov 2018 19:18:35 +0800 Subject: [PATCH 20/20] Delete \r and \n in the result of GetFSType --- contrib/connector/common.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/connector/common.go b/contrib/connector/common.go index fb8d7f759..bdefb0a25 100644 --- a/contrib/connector/common.go +++ b/contrib/connector/common.go @@ -48,6 +48,8 @@ func GetFSType(device string) string { if strings.Contains(v, "TYPE=") { fsType = strings.Split(v, "=")[1] fsType = strings.Replace(fsType, "\"", "", -1) + fsType = strings.Replace(fsType, "\n", "", -1) + fsType = strings.Replace(fsType, "\r", "", -1) } } }

        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 RD{lX$5$#;?jW+%%{{u)x0*3$q diff --git a/dashboard/src/assets/components/themes/default/images/ui-bg_flat_0_aaaaaa_40x100.png b/dashboard/src/assets/components/themes/default/images/ui-bg_flat_0_aaaaaa_40x100.png deleted file mode 100644 index 5b5dab2ab7b1c50dea9cfe73dc5a269a92d2d4b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FscKIb$B>N1x91EQ4=4yQ7#`R^ z$vje}bP0l+XkK DSH>_4 diff --git a/dashboard/src/assets/components/themes/default/images/ui-bg_flat_75_ffffff_40x100.png b/dashboard/src/assets/components/themes/default/images/ui-bg_flat_75_ffffff_40x100.png deleted file mode 100644 index ac8b229af950c29356abf64a6c4aa894575445f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FsY*{5$B>N1x91EQ4=4yQYz+E8 zPo9&<{J;c_6SHRil>2s{Zw^OT)6@jj2u|u!(plXsM>LJD`vD!n;OXk;vd$@?2>^GI BH@yG= diff --git a/dashboard/src/assets/components/themes/default/images/ui-bg_glass_55_fbf9ee_1x400.png b/dashboard/src/assets/components/themes/default/images/ui-bg_glass_55_fbf9ee_1x400.png deleted file mode 100644 index ad3d6346e00f246102f72f2e026ed0491988b394..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnour0hLi978O6-<~(*I$*%ybaDOn z{W;e!B}_MSUQoPXhYd^Y6RUoS1yepnPx`2Kz)7OXQG!!=-jY=F+d2OOy?#DnJ32>z UEim$g7SJdLPgg&ebxsLQ09~*s;{X5v diff --git a/dashboard/src/assets/components/themes/default/images/ui-bg_glass_65_ffffff_1x400.png b/dashboard/src/assets/components/themes/default/images/ui-bg_glass_65_ffffff_1x400.png deleted file mode 100644 index 42ccba269b6e91bef12ad0fa18be651b5ef0ee68..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouqzpV=978O6-=0?FV^9z|eBtf= z|7WztIJ;WT>{+tN>ySr~=F{k$>;_x^_y?afmf9pRKH0)6?eSP?3s5hEr>mdKI;Vst E0O;M1& diff --git a/dashboard/src/assets/components/themes/default/images/ui-bg_glass_75_dadada_1x400.png b/dashboard/src/assets/components/themes/default/images/ui-bg_glass_75_dadada_1x400.png deleted file mode 100644 index 5a46b47cb16631068aee9e0bd61269fc4e95e5cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq|7{B978O6lPf+wIa#m9#>Unb zm^4K~wN3Zq+uP{vDV26o)#~38k_!`W=^oo1w6ixmPC4R1b Tyd6G3lNdZ*{an^LB{Ts5`idse diff --git a/dashboard/src/assets/components/themes/default/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/dashboard/src/assets/components/themes/default/images/ui-bg_highlight-soft_75_cccccc_1x100.png deleted file mode 100644 index 7c9fa6c6edcfcdd3e5b77e6f547b719e6fc66e30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 101 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 diff --git a/dashboard/src/assets/components/themes/default/images/ui-icons_2e83ff_256x240.png b/dashboard/src/assets/components/themes/default/images/ui-icons_2e83ff_256x240.png deleted file mode 100644 index 84defe6e8ab878a83d7ed145c4734e5e1117cf0f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5355 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 X_Gc^EhHU=dFY}4IzFMt{L(KmGE`UUf diff --git a/dashboard/src/assets/components/themes/default/images/ui-icons_454545_256x240.png b/dashboard/src/assets/components/themes/default/images/ui-icons_454545_256x240.png deleted file mode 100644 index 59bd45b907c4fd965697774ce8c5fc6b2fd9c105..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4369 zcmd^?`8O2)_s3^p#%>toqJ#RmwV2==ic*rz7lOw=eaq=H~;_ux21)-Jpcgw zdj+hrf&W^f<%Qk9Zpqf#;jH;N^Z%VA?R|9mZ{esQd(2F=?y+!`XZ5CR?ue=UdHIfUDFM*m15I;g=VN2jw zQW9?wOhDI#+P0|`@JQoC3!pu=AzGMtYB>V&?8(2>_B5_p`1Sb1t{^|J%bZYv09RS? zQ*dcs7}$)taJ@vX0E<96P{ur)Eygr{&ALyNoMP%_94m}=qFVT)&CeG1DBBMLUSKP^ zp%%Q3$MEtKll)X*+$)3O_3x`4%cHY0uhy7U;5x^Ir}X1)mv&B%|A)@A$a>f}tP{5X z9-gkti`YyT+hk9)cZW7fAQhjT%$XLLI^&VR=qev36;`WGBOP!^&(?!sK6jSH0Dnz4 zoEMMNu}y&n=rd-GWI?rGBI8!GD*NJ$k&e5-6+~-9F^6tV<=5`FcY~t{iqRcncEU+F zkT~jww!oy(@~b~WGI8!lzjURX&IpJjFGxShOKUunP+rW$I{c|x0qM6!Gxf6n(;$D> z+QYiULqq)Fy4VDk&Mev)NyM@nvF z7O6M*A$C)kBi0HGMT_+xfQ^USTM)>*h_Rx%eSRxA%n|FuC&=F=Pz}E5uCqbcy;7j=%Qh`glqEA-jx0(a<)uKO5Fe|JLD-ndZ-vnW`G=O&^%pa}Ah(2%m?oANs{lJ`?RhrZ8n!`Q97TKw{YAw9 zD)=M{mD(~_jj`LTd%q6Veum)Cnd!7lw}(5h%ubHcg^2O`prn%u9es3C#&%TsnmSD3%3Ik^Yd@6-d%(I7kqT(B@dVX2 zIidXgd>qYT-oTZ=1sGI7^*_E9Q)1F2mooE0R zXopPnh^ci@+wz2ZDjo&Owyxh6t90Gt!u0miLxc!bue^LvHF?)O@Yf!dQUXfW$u8(f_n07^N)-vpIe;TrHv5uKm{h_v`-IN^zwWc>Lk ziGsSr89sDcdOR_wa~DjrqV&Nd*$18(vohPJ3hSzEJPF2d!u}415wrSMtS(zNa7 zbO0G4ajgKNp{`D7DO<(T?wowarQ0dIKLb<}#prQM)ytB73YNTPQgX^xoT zm>;yKSJ*c@QfD8HW`6&+mowOaA|A&~G0fO6&xwj;E3O9^Zu~ZXts~;-d%FyyeXrijORi<_S(dw_5@h&-fTY?#FJo% zQZZ1&ED%$if+n8JVM{s-ZoK@P>p@z4s`AoI6hYxE!Ie_Y)cpjZjc8@~uNMYVfy#J$ z)+sdEX7DK^{}kUAST8U6^p6#c>0Lc>T~9`0}`*2 zizaU)TFS4(u;BenUWZr?s{D)Z)rc9L5&gUvz3iSQaF#J)D)Ts{YgagdDcI1S`dtes zPqb4|h-RIkjhnpmn(Q2Je6Di5C?MkCUL)!WoKn|P#al41v#-Q8`K1$Gh64UhPQj|T zaZb%tJ}O{A?Cvl26!jeKS3OUkp5@8RDBYwh`Loxb5W<^m*R37+v}#*m-G{{ocF-#r z7!k3ZS^4Qu9sNRNZ3`laW2TqV{rsR#~gtVp6C zL0?}~gbLTv^jqtPQD@Cpq6{B6v&*Y)?tx})z=qQNB4Z_59 zpI2L)xQ`!|J8wWgs82jSw_8(;#}y7~Y^&hY9P1G)@`CGtIi*tZ%-%&;$PuG(!M%)E zQ?T#imBH8dCZxUBX^RWPwIh9LcnL3#$befQDr@UJl{=}o0){qIt52vU9X=3L_gvVW zPqp_YhhpM6XiE7Lvn-G0Wzo>0;g|$_-7|ucz~*w%bW@hr6M?~v9dT}L=>UotTj13& z?Uvt0_uOvzMq4iG6)gZqeU;W=P@EVod;}Vr7P*@=C19v;iz$4N+c5ewauTtKK5e;yIx(FQUec0 z`G)VlTUY|m2L=KusMRgMlapu#wt8MohK3=y`!J`tD6nYd%?xIZO`Q)skL)R%3Vf(P z__5Sx3h%fKF=sNdZo2p(w=_|}1M%ri7fO?8))sU1ySG;M4p4;zrr}4l0lzvA!WQ&a zrwX>%lJkv`Gr_u=K>kHOg6(AB(R3FOryElY)-vi|fRsBS<)$1;TC_?BnyScjY6>_ZD=T|bjcbjz@D6V+yfHd4SU+J*2Dh%n;$5ou zHh6R=)$>IH@%5js2KH#JkfFCVI}P>~U;|}>kk|06tA}^~B;|gJ$UvSF-l4GX43DAR z&M2mp8OgiTaK4li0|Q2qmGNYsm+Qq^JM8yfCP>5!31rjh4Mnq~+5X8+_$scfP1Fp!c zcQO*#6cfJ?ZRxn_$Se_|}Xo1oIF7s(7CllypCW@W8-y5%Bel_K*0G zd~8UWeYCWz>~^hF3ond|tQcClJ(8^9FW&&?U)a4O-pE;Y*u|FHGax>F*Kg_beOF5c z&?#xRN5Q?ckEwCnNr-${XC=w-te5%QH(6O~yxke=R!_ns))PU07Pu)CY`<>$+XicZ zCI=g^;q7NZnw=-vf;HoWLD+}`&Bph>kiqyX5jxjI1A41d$R3nahq@CHULV#9ItIwJ z0)^JGy{hB;@SD|}Zel8~2z;UjN96MR@dt;EV`9RP4X&zn8ib=n*107cICSp7z6srZ~4Qg|Vp$OB0By{IxAPaD7HGFw_HTza~wWN1A6 z3`7BZFse2a4{y#V^&;nRVcZOz*2>A?jm$%?)KawLR0cEz24qxxOOo9_2)9MrWpSg7 zPiPz+M7(zPRZ3$#11ti?uI!}bM!Dg%L#+uR+^2L2RX+QlMpL zg_DrR=GIT7C~b+^OZK)?l7*9c-78zWVbLo1oS}bItdscuF80}guwA8c^(47DfaBjV z^V@&JJHxYHqS+e7&X;ezZwsE2+t~n0?*m^(db@WnI{LgAnOqOa<8pRvo0E>*O&~J_ z&A)t2LOG)5=3$3n2_gi2Kpvgv)#LCUh2Y~ z!A&(~-8reT$sJk0=L;m~ES3k}k% zkF%gzzT(+nRU0IeUvuW8pq=8uzr&7HW>K5ZiD*8qL17AI^ zGqo>*mvIChU6+&t{A3|!W?~pi9_O$>k2d|#(Z721wcT{S1)_UFZ+}QS^KZ*u?5Y~bz z^cLI;2{$C_ZwWqM@sYMYwG+^N<^Ivq8ZOwV;7xT+WCh)I9PHC}ut;VNr?&Z`mr_kcwz5Nh&gy7G+@45H9p05OJ)J0CH2owMSaGIN$+5!N; z<11j56?ANg=9hMl-IBGX-T8hf$N$b*H?$f4Xt&I`oABt1nR=k%#z{{*a!Axm|t}hCz zJg0Ln7;M4Zjx{$mwhMW+kWN;|j>qTx_-zNX!GzqEZRa}QF8_0yk6+=w}$QD^&hM4%OkT=uh$q9;5u~NL-I+NQyaVc|3l+iWI5~|(hA-G z08i8AMr@{uY_cWTxo^y|Qyb33mlZLvc7H2Zm~>mB7&=-1X^@|D z&0*~i?GBE&NM(Pv&Vt^zWu_bD3e|R?wTL{cSFwD^Ij9v%g=aLY@1U2Bxn#Te*{>%D zOOW-O-bfnJ7T8jd<*>8`Z2DsFQi~S$%^npJwXam5>>p zMd}QEjM)@~##n$LXpz1Hkl|2UGXi-JFFePXBWL+-5f%!S>L#KL3>Vl0w#d^21Jn<~_7q zWx^Xg1(>PsPGO&cu{S;(pRQ;=Vw2J<9NdQVWx<+g-`ia=Q@puS)75M+?u>DTa95e9 zt#1T?#a)uWC>Mia!K6>g|InPW{&Kp9$tC_3*;R_Xsz6^Eu|xW1$6j#0?XLs7^l+%O zlxddE)h^|=K(2UqS*0ECuDe0ic|H_^t*VOoTCKx0Qmn_^LyJ|b8l$Jvl3{2=3x8&7 z$1ik&YG>w#@x@y~$r`fhlUDo;yXecc6$`30m`3K8s{k8G&3RVp8n#|l6h(Xw`Axw9 z%6Y^J6k0P@4YAuSd%q7=eg)&u8EMoEmq$CWj1GY|rGQWw3ida!FHk&wCqrQh_0Bcw z!ZBS3CbxgZ+}~wzgGIQ#QId%T_TE~_qdUqxjqS#8#jPxdwO@(@-5_nSP&uT?aGYYD z6km36K9=gjUjImwO=5Hl#u85VF?r0HbW)#h^SR|s_L47Tl$&Z&Rz*ksl!t*(2O2;D z+8`6$qpLn}LchhCmv*X}moGMX5?F@juGeHQAddAn}0~r zS_0|d3*0v%Y)8+8K{ zGyoYPb|W9Grm9M4E?vb^@16ePbI4omZv+(NoZ##fLUmKlB(G_jEbtDCM*27t$v`JovAZa+%*Q5dDXF*Ftt*n!O>#ohCM4lZ)h5rdKV-3A za}2AO6@!`W>ROk5FN*>2Zza^Z%}8KT%*jBGH|rml2X1LR{wZhWx8V4>|5i}; zMnLIHn3!^)`87GYh}&Y`KMwyLbA#^pch}Z!`@P_qH&N^LS9SxpEy8mc!wFusq&Z@` zeO}<6PC@VNaII|=n(^cNUiLseig*$;NjG7;IwvfYCBN>kzv@v-V2eBQZ@oIs^)NLqMR935k|1}U;5<{s(Ebdj4r`?QtrrAPfQooq zmPs_(YTy|??+nitNIFDoR7~qLPPFFCf^_~8OUt{#!|9o*3Q{!@9ZAI$7O~piD!;WX8#v&RxNH27i59$`1{o zEYU_zE{bKEI%f3BbE0Fc;f2!4LjUlC`wgh4@R{1?O78r5t$hWKiLV{#QWWq{QZiPx zm3?x$;&DDRVt0SByRiFczw$-e)GSvpCRbzk^=E zz=(+LjEc{Ps_2(OYg=G(93!oS=IeJ|WA8STv+LgI*Oj1c-QC06N~mvJ&KKx{arGp5 zswvJ6{%BvBYo>#2$%O$~TITuh?Rr^jCpAUXh)}m74`O|aOU>w2KI`k<#efwa5=-l4Xx!o>Z9Evg`RLN5W7SQp3$@D3_hY4EV!0( ztMm6>zBcgY{RvHZ{9Ey&&)jr2B4s0qDPBUh1ITaAp&>rj3ng*B=VGXz* zs@eR<;J(XkpD6Q1U3}#FR)wlafiFMU(-=&e9(eQ`isrS-9aNwJ)7frS8RiXM4*SbC zL|4*c?h^jfYvSOpn%Z$W?C|TuZ;uy2pFWHXuGW`ZkGV&kPJsKqJJQ!NswAE!!cb2k zumi=AE$YIkm})cVlg>nn&PBjBRI*@mfhhRMsa5U8k#A!ztfiw)d7I_UyAif8$5sJ9a7WUv5!o%fL z(J7-8EQzv1YIc)BNeWkLK~m%y4vqe&q@|_ZR5;eC3-9rkf*T{_19jtuWKhdW4Bn|~ zZ-YyFLN!k)0AKg{dO)|v3K?=oy+dzb4%T1F4}JsByncB1Z(`2p@O0!E!JQelouN^* z%Q^YfQUh66D$Zx-RDZvLctsr9`_+1p#tz&4SMd@i_-8()tyg3OyhU~?Gt#-a{NKFN z0VGf+AH%@o6;-_*?$$T4QX-f_>Ny-5CV8Ccq+@>gNSeovbFr0@b}RiTcJbLx>ws&r zsvY!rR{4al#MpVKut~?&kTmF>_v3UaC!gvuxgg%5-{l{20}~&F6CUarF9N=u)BG71 zoQDlAwT+T=mfo&$Xy%4-kmW;4wuh6{{ABClybHV6L>t&k4?9_Ny8A_^?)ff#dEjhL z2RbC~cFVbz^fJ`$I0%prYc0g-9(7X3eUp}^#Mzv)Z1EsGW;qr3cY$+e2HU5d_O9L% zpbljP*1!A0PqpzNo3W&y(hD87qgweq5YQWYEkxrOuSain2-q@Z*P`x*ht-9)Fr5Ho zSTKduvc9h6`S^#$i)LgjDi3_PQ+RbaGP!!di^Y;4kB0lGo$y{if)rJIaXTbpRgO#B z1El6|18;s}$0FRjgK-7~ZwmI`_1{a`32+Y>&O_iTpm%vz6hNkjGR(#*! zpfJ2>OAQbTFba9S3j9BlRHXaG{)Zt(J<3ppA?}j+7F#{bV{M7zU)5e@~R&J_xf$+GKK~ z3{R;Y9fZGe^ifEqKL;!VMXv26=R~^TG(#*2!JKCWoo&c^$utAs#Gfq-?t!c&9TH5- zj&i5L4NWbdNs*djvsY}bC&ddUbh=iyc0;3-@Y#d^s8|Ql{ax(yenFcG#i|K%lRxy| zFys4w!@EPXp2AsbMUGc*eP|7uliAq-O6~(+MR>V(EZTd&9G+MY&gF2lZ=I8j*o`OC z`AxrmOGMeD=H_9Cq47clT|h34>-EI=%;E!my;o&wU(aKV&PymBzrV9q2uA62XS@JrjKYANZAU>;8mag#BU?Nv`+ZVhlAPV`HF_gKY_O zhbV2L`8qvR&f=@M5vH~geD+L&*L2s<)|5)clA0yt9TM{X)iWtx@wJO_!{vR#|AD6t z*OAg2&P_i8jjW5y0DdtOGcqvrCHD*1Uq_q1ZQmngPnf!2fHizH%sSX>#$2Rh!>1ur z+s(*-)abDuePc6~XNG8m@|KMXHVM#G4?~+V z1z!An!D0GD-7WqXE8ddUXLkI%u01$fTEhhytoqJ#RmwV2==ic*rz7lOw=eaq=H~;_ux21)-Jpcgw zdj+hrf&W^f<%Qk9Zpqf#;q3n5{{POY;f!wmTR1An9(4&I0z1LNX50QSTV2M%4|y9c z#{ZQIVJKu~aY5?ZaZP*GIGqGs=e@q6o|EPhZB3CC?@LnORK8O@z{{<0KtSn5?#~OW zy=L;x8T&*%xqElS;s5~Pjk7d2bqIaA)xZbovnZd7eX17WNxx=w`p(8vulwUZ zl{so}MuRNJx5!8S5G;$o2?BApPHt+)!^#*Ww`?rcVE}mcyuY`X2o|uVUyI9o1t11O zemGWR?;aD#0$vJhiPhv~0iXS#iLq!>Qd$` zU{}<|Vb9Md>$4TMbL7C3GP#r;4Wc$}Z;^j;n}yc!E3d;`wry$!JkmJP0%(tIh!!TET8=+{rhUi^60G0t2HJSxXv-*DgC(HrJd8`|Dp3NvL5yg>xAvU zho|fEA~w^-HrW&H-JwkqNX2I-bEXBR&Uhp+y2^)1h1IIlNCzC!v-Mz@&z&VPz+cl1 z=f&f6Y*U~C`ixm4Sy1hl$hg(4%Dy;bq~k7d1<@K&%%NLT`L+A)-QXyKVswX?op90( zB#yeFEih@c{OXU8Oq~1CFI_38GXmns3(`;W(i+bslovCx4u7gvK>DrGOug*?G|1nz z_OR}|ZYS3pq-p?rS7G0qa`TM}r5XqDT4cV>%Qyk#9ES}`jc+Ww|DcbZrF6UG>CeXp zOVIV}K1e#z9@tu#?X)Ri=?zXMB`X3G-_I7FL-Zq`nbfWtX_EO1*!+U6pJW-_k&+vk zMd}THh}{(Ch_wPk(PI4vVB_KT76kGxVytLxpWg}&bHw`a3G#QzxV@ICNax&@hk3<_ zBh`Tq66G{-tCw$V{(y0v7l!tp20~@gdFXjzFbF#bJE7i>T4ux zQdrF3org^wFcnw$#bQMv@SfN3$Fuo7HnB_`2ZGB{ZqGr>%xP;2_!Q{=N-ZhU1c~^5 zdt=OO#wmcpkXJyCG?{{&n=R{Sn=Ytg;<09CH)l7TA&wkt{Q;>RrA2Ia6-QixEPLrU z%0)N$3Nh0?U825&v($Sz}0G_(!v&xSSAzje4{rup+^W@^}ByqOb95$E0sbwK*%#GP}!6`%*Z@L;&C z3^dE&>5%bWAXmP*X1 z_m}Pivs*u7@9i>qA!58fDCwj^M<1P(u^m;urVdlM@>aIf+E3-d9ZW>fc4cS7w5O3sCmKKn z+94A?VyfSBb9{}rEbCIYtXORJBCv__fnZ>?a}edaA%bP$jI?J^q0UKO!mduA8U!3b z0CJ_Js}NWQZoebapVUHP%pPOUm?1<)zd%`hzUM-Y6g1z|@@3G_kio?S0bcbjQuxJd>vU$Uyz(4*peEDSVc-G;O;% z9Y97%Tq}TRsH+oN%2u(oyC=W<9`e@&m;i;jC%L;sP(9RBDQnth3;ZMEQNFH3GEf0c zU<3RF!hNG-vCDooYFS^nPlFnv4(ElI1=vNcr42TF^uq67f{MoN>{f&>xA91r4pz5Zc&@P^i-9||`98v$Si!U@}ouZ88W zg;YL=OQ;4}UQtkpyd~lD{qWy0H|lwJXKmenz#E=*9kt$YX*X!wDk7ITlIUGWnj>a7 z<_GQR752@J)Y(U)ncu(dIit7P}oBq8x$FP85)&Nsw<#rOW z8U_x(1J)Zgm(8tZXU%+(yYcO+Z7#ZszPwa2`ygiMPayX9KondtFMRK!7x`9uWN;(f zfWW?8yOdj;GA3We0YAW92gWipn(d>zcbA+vZ_21BxF?-pfcW` zbqY??6ie(6M)p@6@WQ?Tl7 zoKrKEj|x~2yZehhMLkFRRnOC>XL&L+N;m0B{_OQ9gzzTYb!!Jct=bk?_hIpY9rOwY zMnr69R(?8EN52qR+k!~qnCYc-KmV&*d$&NY?t5cjR)V+ncMor=puTRoo?{5dH;@!* z<~RrV!+ljAN+;Qx2LraY&JWnz^|sYbZjP+Y;|pC#DuHUH+>F~x3PqTkx)=OAE0X9( z(AO6gp~AH^{nq+n)LHYDD8mQN?DDFcd!U&d4PaajzSD1~lXq3p{x=^vItrq3gD^4O z=hYS`?&C-0&KuAV>Jv}T?ba0IafL$~+bZ}p$9lwyyx=-uPN`Hpvv<)Ia>OWHa4+N4 z6zscrW$^XA32EJw^7hYtkRJr{Q8 zQ|*1pp_q6Mno|D6EX!kgSv0h0I3~ef_l%$DTFjL`0y16n%^dGNQn;2V82mqoIi9i{15vu zLq&(BTl9CInUjZlTIa>^!!HlMK3W8Sd_Ow0+E8IT?h$=55$^Z)$WYIuig=O;Lp_1Q z4wOT;XbWQ!>Mh`pdXuSo=KBba;wT!wK`Hf1Ueh04*%D7Kfj*#b~BNfvz zsbf?uiMm5-xhaQ|7Om2OrYbU>ngUM9%F5nU<65IFyu(`yZ;Vb1)=wCd!L2K?c$ezE z4IbS|^?Z>)eEp}ZfjwF)Waw?pPJ?{~*g%;efxO~Nx7dQGLWZ)cPQ*T!((W- zGm2?tM)K}7oG<0Xz<`ltWjxvE<$AH!4*R{A2~uYGr@m!vm*j+e#CE9^*}Oc#uihB| z5;#kMY2^8mrr80%*+02bDx6B{Jsch(d7kQGV7~iGTgFZBu$Pf`tNf`B2{|t7fGhIq zos0xF#l$bfxOtcGDd*MDbdKBaCKxgCEbr8JTNd_1bjWC{Ubgk z9~)9;A1&=FyIt$l!VBXfD~6VCk0fjO%QwLJ7k00RH*%I8cCqF542VzP^;`OU-_?=< zbV}OoQE)HqV`|)X5+WbgSxGWH>t+7-O;(l~Z+FJJ)sygu^+eF01#Suj+pnAcw!s>p z$-xF}c>7t9X6H$^V9hvT5H{jKv+=zzWHA0pgw8e5fZpm9vIphVq3%S4*N3%&jsY^Q zK%sSPuj=?d{ATs0o0y6#0w3%YT^@-_sTuTUwI(Q{;l3KjeAbVk#Wmi%PDxm`zoqQ~ z((<-}*FSP%5gt7uI3t1&75ne{@1^bpdW1;MMGNkSr~UAuDbB4+VQi|x(gdO^zin_) zncfs2hj8xdiiy)@vVkfkItLKvsGtJhrTb0T~tFl4Q3J!flauS==b& z6Bm!g%dDvlCf(St$kVofvH90|9yl-gmvRvcKS&Ye9DdoTK@2m}iSvC{3m%4E0 z@TJD7c1V?!URM7+t?f3)%{X(6JXg~A9TvGQyX6n(^Yt0NX;>vDPcr~mICPooLWA_` z<1A>FuXr|C)dtDr*PQt%Xs5WePWUB&gBj$zZ#BIY%?jDdpbSA-PV0`dGf^oa_Jp}Z zlrGV7oe`#B^+nPIQ`ZDJeJas=ru#=*YL#+n?Go}f33>1GsZ{TTy2bdBihj}mz*mp! zOzn%{WgLM=*CpiuKUs*GnHa{B$2siJqfNi|Z;|rH%stM*8b26kAMCYY&NHwPGtlYn z7UVx_^sgR$Z8x27foS63FCPt|gtcG_ zy#@C|!VQV~TY}G5e57qp?F4jRxqq~@h6^?-cvD>ySwVLl2m7=gERtEn>Fw_@ND%pO oiVC*mbz<%I+0K1Z`+LWvZ$3~$+A!Gm?^hpSc@||}WrmLVKLvuzv;Y7A diff --git a/dashboard/src/environments/environment.prod.ts b/dashboard/src/environments/environment.prod.ts deleted file mode 100644 index 3612073bc..000000000 --- a/dashboard/src/environments/environment.prod.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const environment = { - production: true -}; diff --git a/dashboard/src/environments/environment.ts b/dashboard/src/environments/environment.ts deleted file mode 100644 index b7f639aec..000000000 --- a/dashboard/src/environments/environment.ts +++ /dev/null @@ -1,8 +0,0 @@ -// The file contents for the current environment will overwrite these during build. -// The build system defaults to the dev environment which uses `environment.ts`, but if you do -// `ng build --env=prod` then `environment.prod.ts` will be used instead. -// The list of which env maps to which file can be found in `.angular-cli.json`. - -export const environment = { - production: false -}; diff --git a/dashboard/src/index.html b/dashboard/src/index.html deleted file mode 100644 index ebb96da59..000000000 --- a/dashboard/src/index.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - OpenSDS - - - - - - - - - - - diff --git a/dashboard/src/main.ts b/dashboard/src/main.ts deleted file mode 100644 index a9ca1caf8..000000000 --- a/dashboard/src/main.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { enableProdMode } from '@angular/core'; -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; - -import { AppModule } from './app/app.module'; -import { environment } from './environments/environment'; - -if (environment.production) { - enableProdMode(); -} - -platformBrowserDynamic().bootstrapModule(AppModule); diff --git a/dashboard/src/polyfills.ts b/dashboard/src/polyfills.ts deleted file mode 100644 index 49bdde6fc..000000000 --- a/dashboard/src/polyfills.ts +++ /dev/null @@ -1,73 +0,0 @@ -/** - * This file includes polyfills needed by Angular and is loaded before the app. - * You can add your own extra polyfills to this file. - * - * This file is divided into 2 sections: - * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. - * 2. Application imports. Files imported after ZoneJS that should be loaded before your main - * file. - * - * The current setup is for so-called "evergreen" browsers; the last versions of browsers that - * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), - * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. - * - * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html - */ - -/*************************************************************************************************** - * BROWSER POLYFILLS - */ - -/** IE9, IE10 and IE11 requires all of the following polyfills. **/ -import 'core-js/es6/symbol'; -import 'core-js/es6/object'; -import 'core-js/es6/function'; -import 'core-js/es6/parse-int'; -import 'core-js/es6/parse-float'; -import 'core-js/es6/number'; -import 'core-js/es6/math'; -import 'core-js/es6/string'; -import 'core-js/es6/date'; -import 'core-js/es6/array'; -import 'core-js/es6/regexp'; -import 'core-js/es6/map'; -import 'core-js/es6/weak-map'; -import 'core-js/es6/set'; - -/** IE10 and IE11 requires the following for NgClass support on SVG elements */ -// import 'classlist.js'; // Run `npm install --save classlist.js`. - -/** IE10 and IE11 requires the following to support `@angular/animation`. */ -import 'web-animations-js'; // Run `npm install --save web-animations-js`. - - -/** Evergreen browsers require these. **/ -import 'core-js/es6/reflect'; -import 'core-js/es7/reflect'; - - -/** ALL Firefox browsers require the following to support `@angular/animation`. **/ -// import 'web-animations-js'; // Run `npm install --save web-animations-js`. - - - -/*************************************************************************************************** - * Zone JS is required by Angular itself. - */ -import 'zone.js/dist/zone'; // Included with Angular CLI. - - - -/*************************************************************************************************** - * APPLICATION IMPORTS - */ - -/** - * Date, currency, decimal and percent pipes. - * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10 - */ -import 'intl'; // Run `npm install --save intl`. -/** - * Need to import at least one locale-data with intl. - */ -import 'intl/locale-data/jsonp/en'; diff --git a/dashboard/src/styles.scss b/dashboard/src/styles.scss deleted file mode 100644 index b40462900..000000000 --- a/dashboard/src/styles.scss +++ /dev/null @@ -1,3 +0,0 @@ -@import './assets/components/themes/default/default.scss'; -@import './assets/business/css/primeng.scss'; -@import './assets/business/css/site.scss'; diff --git a/dashboard/src/test.ts b/dashboard/src/test.ts deleted file mode 100644 index cd612eeb0..000000000 --- a/dashboard/src/test.ts +++ /dev/null @@ -1,32 +0,0 @@ -// This file is required by karma.conf.js and loads recursively all the .spec and framework files - -import 'zone.js/dist/long-stack-trace-zone'; -import 'zone.js/dist/proxy.js'; -import 'zone.js/dist/sync-test'; -import 'zone.js/dist/jasmine-patch'; -import 'zone.js/dist/async-test'; -import 'zone.js/dist/fake-async-test'; -import { getTestBed } from '@angular/core/testing'; -import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting -} from '@angular/platform-browser-dynamic/testing'; - -// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. -declare const __karma__: any; -declare const require: any; - -// Prevent Karma from running prematurely. -__karma__.loaded = function () {}; - -// First, initialize the Angular testing environment. -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting() -); -// Then we find all the tests. -const context = require.context('./', true, /\.spec\.ts$/); -// And load the modules. -context.keys().map(context); -// Finally, start Karma to run the tests. -__karma__.start(); diff --git a/dashboard/src/tsconfig.app.json b/dashboard/src/tsconfig.app.json deleted file mode 100644 index 5e2507db5..000000000 --- a/dashboard/src/tsconfig.app.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "outDir": "../out-tsc/app", - "module": "es2015", - "baseUrl": "", - "types": [] - }, - "exclude": [ - "test.ts", - "**/*.spec.ts" - ] -} diff --git a/dashboard/src/tsconfig.spec.json b/dashboard/src/tsconfig.spec.json deleted file mode 100644 index 510e3f1fd..000000000 --- a/dashboard/src/tsconfig.spec.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "outDir": "../out-tsc/spec", - "module": "commonjs", - "target": "es5", - "baseUrl": "", - "types": [ - "jasmine", - "node" - ] - }, - "files": [ - "test.ts" - ], - "include": [ - "**/*.spec.ts", - "**/*.d.ts" - ] -} diff --git a/dashboard/src/typings.d.ts b/dashboard/src/typings.d.ts deleted file mode 100644 index 4999a068d..000000000 --- a/dashboard/src/typings.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -/* SystemJS module definition */ -declare var module: NodeModule; - -declare var require: any; - -interface NodeModule { - id: string; -} diff --git a/dashboard/src/upload.php b/dashboard/src/upload.php deleted file mode 100644 index b87a10417..000000000 --- a/dashboard/src/upload.php +++ /dev/null @@ -1 +0,0 @@ - Fake Upload Process