diff --git a/.gitignore b/.gitignore index 0c9d828..51e33aa 100644 --- a/.gitignore +++ b/.gitignore @@ -60,3 +60,4 @@ vendor /scrutiny /scrutiny-collector-metrics-linux-amd64 /scrutiny-web-linux-amd64 +scrutiny-*.db diff --git a/collector/pkg/collector/metrics.go b/collector/pkg/collector/metrics.go index b4927be..90b13b4 100644 --- a/collector/pkg/collector/metrics.go +++ b/collector/pkg/collector/metrics.go @@ -49,6 +49,7 @@ func (mc *MetricsCollector) Run() error { } mc.logger.Infoln("Sending detected devices to API, for filtering & validation") + mc.logger.Debugf("Detected devices: %v", detectedStorageDevices) err = mc.postJson(apiEndpoint.String(), models.DeviceWrapper{ Data: detectedStorageDevices, }, &deviceRespWrapper) diff --git a/go.mod b/go.mod index c390435..f61b5a6 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/analogj/go-util v0.0.0-20190301173314-5295e364eb14 github.com/fatih/color v1.9.0 github.com/gin-gonic/gin v1.6.3 + github.com/golang/mock v1.4.3 github.com/jaypipes/ghw v0.6.1 github.com/jinzhu/gorm v1.9.14 github.com/kvz/logstreamer v0.0.0-20150507115422-a635b98146f0 // indirect diff --git a/webapp/backend/pkg/config/mock/mock_config.go b/webapp/backend/pkg/config/mock/mock_config.go new file mode 100644 index 0000000..c9ee399 --- /dev/null +++ b/webapp/backend/pkg/config/mock/mock_config.go @@ -0,0 +1,203 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: webapp/backend/pkg/config/interface.go + +// Package mock_config is a generated GoMock package. +package mock_config + +import ( + gomock "github.com/golang/mock/gomock" + viper "github.com/spf13/viper" + reflect "reflect" +) + +// MockInterface is a mock of Interface interface +type MockInterface struct { + ctrl *gomock.Controller + recorder *MockInterfaceMockRecorder +} + +// MockInterfaceMockRecorder is the mock recorder for MockInterface +type MockInterfaceMockRecorder struct { + mock *MockInterface +} + +// NewMockInterface creates a new mock instance +func NewMockInterface(ctrl *gomock.Controller) *MockInterface { + mock := &MockInterface{ctrl: ctrl} + mock.recorder = &MockInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockInterface) EXPECT() *MockInterfaceMockRecorder { + return m.recorder +} + +// Init mocks base method +func (m *MockInterface) Init() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Init") + ret0, _ := ret[0].(error) + return ret0 +} + +// Init indicates an expected call of Init +func (mr *MockInterfaceMockRecorder) Init() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Init", reflect.TypeOf((*MockInterface)(nil).Init)) +} + +// ReadConfig mocks base method +func (m *MockInterface) ReadConfig(configFilePath string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ReadConfig", configFilePath) + ret0, _ := ret[0].(error) + return ret0 +} + +// ReadConfig indicates an expected call of ReadConfig +func (mr *MockInterfaceMockRecorder) ReadConfig(configFilePath interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadConfig", reflect.TypeOf((*MockInterface)(nil).ReadConfig), configFilePath) +} + +// Set mocks base method +func (m *MockInterface) Set(key string, value interface{}) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Set", key, value) +} + +// Set indicates an expected call of Set +func (mr *MockInterfaceMockRecorder) Set(key, value interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Set", reflect.TypeOf((*MockInterface)(nil).Set), key, value) +} + +// SetDefault mocks base method +func (m *MockInterface) SetDefault(key string, value interface{}) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetDefault", key, value) +} + +// SetDefault indicates an expected call of SetDefault +func (mr *MockInterfaceMockRecorder) SetDefault(key, value interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetDefault", reflect.TypeOf((*MockInterface)(nil).SetDefault), key, value) +} + +// AllSettings mocks base method +func (m *MockInterface) AllSettings() map[string]interface{} { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AllSettings") + ret0, _ := ret[0].(map[string]interface{}) + return ret0 +} + +// AllSettings indicates an expected call of AllSettings +func (mr *MockInterfaceMockRecorder) AllSettings() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllSettings", reflect.TypeOf((*MockInterface)(nil).AllSettings)) +} + +// IsSet mocks base method +func (m *MockInterface) IsSet(key string) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsSet", key) + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsSet indicates an expected call of IsSet +func (mr *MockInterfaceMockRecorder) IsSet(key interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSet", reflect.TypeOf((*MockInterface)(nil).IsSet), key) +} + +// Get mocks base method +func (m *MockInterface) Get(key string) interface{} { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Get", key) + ret0, _ := ret[0].(interface{}) + return ret0 +} + +// Get indicates an expected call of Get +func (mr *MockInterfaceMockRecorder) Get(key interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockInterface)(nil).Get), key) +} + +// GetBool mocks base method +func (m *MockInterface) GetBool(key string) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetBool", key) + ret0, _ := ret[0].(bool) + return ret0 +} + +// GetBool indicates an expected call of GetBool +func (mr *MockInterfaceMockRecorder) GetBool(key interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBool", reflect.TypeOf((*MockInterface)(nil).GetBool), key) +} + +// GetInt mocks base method +func (m *MockInterface) GetInt(key string) int { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetInt", key) + ret0, _ := ret[0].(int) + return ret0 +} + +// GetInt indicates an expected call of GetInt +func (mr *MockInterfaceMockRecorder) GetInt(key interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetInt", reflect.TypeOf((*MockInterface)(nil).GetInt), key) +} + +// GetString mocks base method +func (m *MockInterface) GetString(key string) string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetString", key) + ret0, _ := ret[0].(string) + return ret0 +} + +// GetString indicates an expected call of GetString +func (mr *MockInterfaceMockRecorder) GetString(key interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetString", reflect.TypeOf((*MockInterface)(nil).GetString), key) +} + +// GetStringSlice mocks base method +func (m *MockInterface) GetStringSlice(key string) []string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetStringSlice", key) + ret0, _ := ret[0].([]string) + return ret0 +} + +// GetStringSlice indicates an expected call of GetStringSlice +func (mr *MockInterfaceMockRecorder) GetStringSlice(key interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStringSlice", reflect.TypeOf((*MockInterface)(nil).GetStringSlice), key) +} + +// UnmarshalKey mocks base method +func (m *MockInterface) UnmarshalKey(key string, rawVal interface{}, decoderOpts ...viper.DecoderConfigOption) error { + m.ctrl.T.Helper() + varargs := []interface{}{key, rawVal} + for _, a := range decoderOpts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "UnmarshalKey", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// UnmarshalKey indicates an expected call of UnmarshalKey +func (mr *MockInterfaceMockRecorder) UnmarshalKey(key, rawVal interface{}, decoderOpts ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{key, rawVal}, decoderOpts...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnmarshalKey", reflect.TypeOf((*MockInterface)(nil).UnmarshalKey), varargs...) +} diff --git a/webapp/backend/pkg/models/db/device.go b/webapp/backend/pkg/models/db/device.go index de03401..ec2f875 100644 --- a/webapp/backend/pkg/models/db/device.go +++ b/webapp/backend/pkg/models/db/device.go @@ -25,20 +25,20 @@ type Device struct { WWN string `json:"wwn" gorm:"primary_key"` - DeviceName string `json:"device_name"` - Manufacturer string `json:"manufacturer"` - ModelName string `json:"model_name"` - InterfaceType string `json:"interface_type"` - InterfaceSpeed string `json:"interface_speed"` - SerialNumber string `json:"serial_number"` - Firmware string `json:"firmware"` - RotationSpeed int `json:"rotational_speed"` - Capacity int64 `json:"capacity"` - FormFactor string `json:"form_factor"` - SmartSupport bool `json:"smart_support"` - DeviceProtocol string `json:"device_protocol"` - - SmartResults []Smart `gorm:"foreignkey:DeviceWWN" json:"smart_results"` + DeviceName string `json:"device_name"` + Manufacturer string `json:"manufacturer"` + ModelName string `json:"model_name"` + InterfaceType string `json:"interface_type"` + InterfaceSpeed string `json:"interface_speed"` + SerialNumber string `json:"serial_number"` + Firmware string `json:"firmware"` + RotationSpeed int `json:"rotational_speed"` + Capacity int64 `json:"capacity"` + FormFactor string `json:"form_factor"` + SmartSupport bool `json:"smart_support"` + DeviceProtocol string `json:"device_protocol"` + DeviceType string `json:"device_type"` //device type is used for querying with -d/t flag + SmartResults []Smart `gorm:"foreignkey:DeviceWWN" json:"smart_results"` } func (dv *Device) IsAta() bool { @@ -169,6 +169,7 @@ func (dv *Device) UpdateFromCollectorSmartInfo(info collector.SmartInfo) error { dv.Capacity = info.UserCapacity.Bytes dv.FormFactor = info.FormFactor.Name dv.DeviceProtocol = info.Device.Protocol + dv.DeviceType = info.Device.Type if len(info.Vendor) > 0 { dv.Manufacturer = info.Vendor } diff --git a/webapp/backend/pkg/web/server.go b/webapp/backend/pkg/web/server.go index 7789db1..9d89dab 100644 --- a/webapp/backend/pkg/web/server.go +++ b/webapp/backend/pkg/web/server.go @@ -13,7 +13,7 @@ type AppEngine struct { Config config.Interface } -func (ae *AppEngine) Start() error { +func (ae *AppEngine) Setup() *gin.Engine { r := gin.Default() r.Use(database.DatabaseHandler(ae.Config.GetString("web.database.location"))) @@ -46,6 +46,11 @@ func (ae *AppEngine) Start() error { r.NoRoute(func(c *gin.Context) { c.File(fmt.Sprintf("%s/index.html", ae.Config.GetString("web.src.frontend.path"))) }) + return r +} + +func (ae *AppEngine) Start() error { + r := ae.Setup() return r.Run(fmt.Sprintf("%s:%s", ae.Config.GetString("web.listen.host"), ae.Config.GetString("web.listen.port"))) } diff --git a/webapp/backend/pkg/web/server_test.go b/webapp/backend/pkg/web/server_test.go new file mode 100644 index 0000000..1d6d205 --- /dev/null +++ b/webapp/backend/pkg/web/server_test.go @@ -0,0 +1,149 @@ +package web_test + +import ( + mock_config "github.com/analogj/scrutiny/webapp/backend/pkg/config/mock" + "github.com/analogj/scrutiny/webapp/backend/pkg/web" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" + "net/http" + "net/http/httptest" + "os" + "testing" +) + +func TestHealthRoute(t *testing.T) { + //setup + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + fakeConfig := mock_config.NewMockInterface(mockCtrl) + fakeConfig.EXPECT().GetString("web.database.location").Return("testdata/scrutiny_test.db") + fakeConfig.EXPECT().GetString("web.src.frontend.path").Return("testdata") + + ae := web.AppEngine{ + Config: fakeConfig, + } + + router := ae.Setup() + + //test + w := httptest.NewRecorder() + req, _ := http.NewRequest("GET", "/api/health", nil) + router.ServeHTTP(w, req) + + //assert + require.Equal(t, 200, w.Code) + require.Equal(t, "{\"success\":true}", w.Body.String()) +} + +func TestRegisterDevicesRoute(t *testing.T) { + //setup + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + fakeConfig := mock_config.NewMockInterface(mockCtrl) + fakeConfig.EXPECT().GetString("web.database.location").Return("testdata/scrutiny_test.db") + fakeConfig.EXPECT().GetString("web.src.frontend.path").Return("testdata") + ae := web.AppEngine{ + Config: fakeConfig, + } + router := ae.Setup() + file, err := os.Open("testdata/register-devices-req.json") + require.NoError(t, err) + + //test + w := httptest.NewRecorder() + req, _ := http.NewRequest("POST", "/api/devices/register", file) + router.ServeHTTP(w, req) + + //assert + require.Equal(t, 200, w.Code) +} + +func TestUploadDeviceMetricsRoute(t *testing.T) { + //setup + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + fakeConfig := mock_config.NewMockInterface(mockCtrl) + fakeConfig.EXPECT().GetString("web.database.location").AnyTimes().Return("testdata/scrutiny_test.db") + fakeConfig.EXPECT().GetString("web.src.frontend.path").AnyTimes().Return("testdata") + ae := web.AppEngine{ + Config: fakeConfig, + } + router := ae.Setup() + devicesfile, err := os.Open("testdata/register-devices-single-req.json") + require.NoError(t, err) + + metricsfile, err := os.Open("testdata/upload-device-metrics-req.json") + require.NoError(t, err) + + //test + wr := httptest.NewRecorder() + req, _ := http.NewRequest("POST", "/api/devices/register", devicesfile) + router.ServeHTTP(wr, req) + require.Equal(t, 200, wr.Code) + + mr := httptest.NewRecorder() + req, _ = http.NewRequest("POST", "/api/device/0x5000cca264eb01d7/smart", metricsfile) + router.ServeHTTP(mr, req) + require.Equal(t, 200, mr.Code) + + //assert +} + +func TestPopulateMultiple(t *testing.T) { + //setup + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + fakeConfig := mock_config.NewMockInterface(mockCtrl) + fakeConfig.EXPECT().GetString("web.database.location").AnyTimes().Return("testdata/scrutiny_test.db") + fakeConfig.EXPECT().GetString("web.src.frontend.path").AnyTimes().Return("testdata") + ae := web.AppEngine{ + Config: fakeConfig, + } + router := ae.Setup() + devicesfile, err := os.Open("testdata/register-devices-req.json") + require.NoError(t, err) + + metricsfile, err := os.Open("../models/testdata/smart-ata.json") + require.NoError(t, err) + failfile, err := os.Open("../models/testdata/smart-fail2.json") + require.NoError(t, err) + nvmefile, err := os.Open("../models/testdata/smart-nvme.json") + require.NoError(t, err) + scsifile, err := os.Open("../models/testdata/smart-scsi.json") + require.NoError(t, err) + scsi2file, err := os.Open("../models/testdata/smart-scsi2.json") + require.NoError(t, err) + + //test + wr := httptest.NewRecorder() + req, _ := http.NewRequest("POST", "/api/devices/register", devicesfile) + router.ServeHTTP(wr, req) + require.Equal(t, 200, wr.Code) + + mr := httptest.NewRecorder() + req, _ = http.NewRequest("POST", "/api/device/0x5000cca264eb01d7/smart", metricsfile) + router.ServeHTTP(mr, req) + require.Equal(t, 200, mr.Code) + + fr := httptest.NewRecorder() + req, _ = http.NewRequest("POST", "/api/device/0x5000cca264ec3183/smart", failfile) + router.ServeHTTP(fr, req) + require.Equal(t, 200, fr.Code) + + nr := httptest.NewRecorder() + req, _ = http.NewRequest("POST", "/api/device/0x5002538e40a22954/smart", nvmefile) + router.ServeHTTP(nr, req) + require.Equal(t, 200, nr.Code) + + sr := httptest.NewRecorder() + req, _ = http.NewRequest("POST", "/api/device/0x5000cca252c859cc/smart", scsifile) + router.ServeHTTP(sr, req) + require.Equal(t, 200, sr.Code) + + s2r := httptest.NewRecorder() + req, _ = http.NewRequest("POST", "/api/device/0x5000cca264ebc248/smart", scsi2file) + router.ServeHTTP(s2r, req) + require.Equal(t, 200, s2r.Code) + + //assert +} diff --git a/webapp/backend/pkg/web/testdata/register-devices-req.json b/webapp/backend/pkg/web/testdata/register-devices-req.json new file mode 100644 index 0000000..34d4b45 --- /dev/null +++ b/webapp/backend/pkg/web/testdata/register-devices-req.json @@ -0,0 +1,102 @@ +{ + "data": [ + { + "wwn": "0x5002538e40a22954", + "device_name": "sda", + "manufacturer": "ATA", + "model_name": "Samsung_SSD_860_EVO_500GB", + "interface_type": "SCSI", + "interface_speed": "", + "serial_number": "S3YZNB0KBXXXXXX", + "firmware": "", + "rotational_speed": 0, + "capacity": 500107862016, + "form_factor": "", + "smart_support": false + }, + { + "wwn": "0x5000cca264eb01d7", + "device_name": "sdb", + "manufacturer": "ATA", + "model_name": "WDC_WD140EDFZ-11A0VA0", + "interface_type": "SCSI", + "interface_speed": "", + "serial_number": "9RK1XXXXX", + "firmware": "", + "rotational_speed": 0, + "capacity": 14000519643136, + "form_factor": "", + "smart_support": false + }, + { + "wwn": "0x5000cca264ec3183", + "device_name": "sdc", + "manufacturer": "ATA", + "model_name": "WDC_WD140EDFZ-11A0VA0", + "interface_type": "SCSI", + "interface_speed": "", + "serial_number": "9RK4XXXXX", + "firmware": "", + "rotational_speed": 0, + "capacity": 14000519643136, + "form_factor": "", + "smart_support": false + }, + { + "wwn": "0x5000cca252c859cc", + "device_name": "sdd", + "manufacturer": "ATA", + "model_name": "WDC_WD80EFAX-68LHPN0", + "interface_type": "SCSI", + "interface_speed": "", + "serial_number": "7SGLXXXXX", + "firmware": "", + "rotational_speed": 0, + "capacity": 8001563222016, + "form_factor": "", + "smart_support": false + }, + { + "wwn": "0x5000cca264ebc248", + "device_name": "sde", + "manufacturer": "ATA", + "model_name": "WDC_WD140EDFZ-11A0VA0", + "interface_type": "SCSI", + "interface_speed": "", + "serial_number": "9RK3XXXXX", + "firmware": "", + "rotational_speed": 0, + "capacity": 14000519643136, + "form_factor": "", + "smart_support": false + }, + { + "wwn": "0x50014ee20b2a72a9", + "device_name": "sdf", + "manufacturer": "ATA", + "model_name": "WDC_WD60EFRX-68MYMN1", + "interface_type": "SCSI", + "interface_speed": "", + "serial_number": "WD-WXL1HXXXXX", + "firmware": "", + "rotational_speed": 0, + "capacity": 6001175126016, + "form_factor": "", + "smart_support": false + }, + { + "wwn": "0x5000c500673e6b5f", + "device_name": "sdg", + "manufacturer": "ATA", + "model_name": "ST6000DX000-1H217Z", + "interface_type": "SCSI", + "interface_speed": "", + "serial_number": "Z4DXXXXX", + "firmware": "", + "rotational_speed": 0, + "capacity": 6001175126016, + "form_factor": "", + "smart_support": false + } + ] +} diff --git a/webapp/backend/pkg/web/testdata/register-devices-single-req.json b/webapp/backend/pkg/web/testdata/register-devices-single-req.json new file mode 100644 index 0000000..84aac6b --- /dev/null +++ b/webapp/backend/pkg/web/testdata/register-devices-single-req.json @@ -0,0 +1,18 @@ +{ + "data": [ + { + "wwn": "0x5000cca264eb01d7", + "device_name": "sdb", + "manufacturer": "ATA", + "model_name": "WDC_WD140EDFZ-11A0VA0", + "interface_type": "SCSI", + "interface_speed": "", + "serial_number": "9RK1XXXXX", + "firmware": "", + "rotational_speed": 0, + "capacity": 14000519643136, + "form_factor": "", + "smart_support": false + } + ] +} diff --git a/webapp/backend/pkg/web/testdata/upload-device-metrics-req.json b/webapp/backend/pkg/web/testdata/upload-device-metrics-req.json new file mode 100644 index 0000000..36ac36b --- /dev/null +++ b/webapp/backend/pkg/web/testdata/upload-device-metrics-req.json @@ -0,0 +1,846 @@ +{ + "json_format_version": [ + 1, + 0 + ], + "smartctl": { + "version": [ + 7, + 0 + ], + "svn_revision": "4883", + "platform_info": "x86_64-linux-4.19.128-flatcar", + "build_info": "(local build)", + "argv": [ + "smartctl", + "-j", + "-a", + "/dev/sdb" + ], + "exit_status": 0 + }, + "device": { + "name": "/dev/sdb", + "info_name": "/dev/sdb [SAT]", + "type": "sat", + "protocol": "ATA" + }, + "model_name": "WDC WD140EDFZ-11A0VA0", + "serial_number": "9RK1XXXX", + "wwn": { + "naa": 5, + "oui": 3274, + "id": 10283057623 + }, + "firmware_version": "81.00A81", + "user_capacity": { + "blocks": 27344764928, + "bytes": 14000519643136 + }, + "logical_block_size": 512, + "physical_block_size": 4096, + "rotation_rate": 5400, + "form_factor": { + "ata_value": 2, + "name": "3.5 inches" + }, + "in_smartctl_database": false, + "ata_version": { + "string": "ACS-2, ATA8-ACS T13/1699-D revision 4", + "major_value": 1020, + "minor_value": 41 + }, + "sata_version": { + "string": "SATA 3.2", + "value": 255 + }, + "interface_speed": { + "max": { + "sata_value": 14, + "string": "6.0 Gb/s", + "units_per_second": 60, + "bits_per_unit": 100000000 + }, + "current": { + "sata_value": 3, + "string": "6.0 Gb/s", + "units_per_second": 60, + "bits_per_unit": 100000000 + } + }, + "local_time": { + "time_t": 1592697810, + "asctime": "Sun Jun 21 00:03:30 2020 UTC" + }, + "smart_status": { + "passed": true + }, + "ata_smart_data": { + "offline_data_collection": { + "status": { + "value": 130, + "string": "was completed without error", + "passed": true + }, + "completion_seconds": 101 + }, + "self_test": { + "status": { + "value": 241, + "string": "in progress, 10% remaining", + "remaining_percent": 10 + }, + "polling_minutes": { + "short": 2, + "extended": 1479 + } + }, + "capabilities": { + "values": [ + 91, + 3 + ], + "exec_offline_immediate_supported": true, + "offline_is_aborted_upon_new_cmd": false, + "offline_surface_scan_supported": true, + "self_tests_supported": true, + "conveyance_self_test_supported": false, + "selective_self_test_supported": true, + "attribute_autosave_enabled": true, + "error_logging_supported": true, + "gp_logging_supported": true + } + }, + "ata_sct_capabilities": { + "value": 61, + "error_recovery_control_supported": true, + "feature_control_supported": true, + "data_table_supported": true + }, + "ata_smart_attributes": { + "revision": 16, + "table": [ + { + "id": 1, + "name": "Raw_Read_Error_Rate", + "value": 100, + "worst": 100, + "thresh": 1, + "when_failed": "", + "flags": { + "value": 11, + "string": "PO-R-- ", + "prefailure": true, + "updated_online": true, + "performance": false, + "error_rate": true, + "event_count": false, + "auto_keep": false + }, + "raw": { + "value": 0, + "string": "0" + } + }, + { + "id": 2, + "name": "Throughput_Performance", + "value": 135, + "worst": 135, + "thresh": 54, + "when_failed": "", + "flags": { + "value": 4, + "string": "--S--- ", + "prefailure": false, + "updated_online": false, + "performance": true, + "error_rate": false, + "event_count": false, + "auto_keep": false + }, + "raw": { + "value": 108, + "string": "108" + } + }, + { + "id": 3, + "name": "Spin_Up_Time", + "value": 81, + "worst": 81, + "thresh": 1, + "when_failed": "", + "flags": { + "value": 7, + "string": "POS--- ", + "prefailure": true, + "updated_online": true, + "performance": true, + "error_rate": false, + "event_count": false, + "auto_keep": false + }, + "raw": { + "value": 30089675132, + "string": "380 (Average 380)" + } + }, + { + "id": 4, + "name": "Start_Stop_Count", + "value": 100, + "worst": 100, + "thresh": 0, + "when_failed": "", + "flags": { + "value": 18, + "string": "-O--C- ", + "prefailure": false, + "updated_online": true, + "performance": false, + "error_rate": false, + "event_count": true, + "auto_keep": false + }, + "raw": { + "value": 9, + "string": "9" + } + }, + { + "id": 5, + "name": "Reallocated_Sector_Ct", + "value": 100, + "worst": 100, + "thresh": 1, + "when_failed": "", + "flags": { + "value": 51, + "string": "PO--CK ", + "prefailure": true, + "updated_online": true, + "performance": false, + "error_rate": false, + "event_count": true, + "auto_keep": true + }, + "raw": { + "value": 0, + "string": "0" + } + }, + { + "id": 7, + "name": "Seek_Error_Rate", + "value": 100, + "worst": 100, + "thresh": 1, + "when_failed": "", + "flags": { + "value": 10, + "string": "-O-R-- ", + "prefailure": false, + "updated_online": true, + "performance": false, + "error_rate": true, + "event_count": false, + "auto_keep": false + }, + "raw": { + "value": 0, + "string": "0" + } + }, + { + "id": 8, + "name": "Seek_Time_Performance", + "value": 133, + "worst": 133, + "thresh": 20, + "when_failed": "", + "flags": { + "value": 4, + "string": "--S--- ", + "prefailure": false, + "updated_online": false, + "performance": true, + "error_rate": false, + "event_count": false, + "auto_keep": false + }, + "raw": { + "value": 18, + "string": "18" + } + }, + { + "id": 9, + "name": "Power_On_Hours", + "value": 100, + "worst": 100, + "thresh": 0, + "when_failed": "", + "flags": { + "value": 18, + "string": "-O--C- ", + "prefailure": false, + "updated_online": true, + "performance": false, + "error_rate": false, + "event_count": true, + "auto_keep": false + }, + "raw": { + "value": 1730, + "string": "1730" + } + }, + { + "id": 10, + "name": "Spin_Retry_Count", + "value": 100, + "worst": 100, + "thresh": 1, + "when_failed": "", + "flags": { + "value": 18, + "string": "-O--C- ", + "prefailure": false, + "updated_online": true, + "performance": false, + "error_rate": false, + "event_count": true, + "auto_keep": false + }, + "raw": { + "value": 0, + "string": "0" + } + }, + { + "id": 12, + "name": "Power_Cycle_Count", + "value": 100, + "worst": 100, + "thresh": 0, + "when_failed": "", + "flags": { + "value": 50, + "string": "-O--CK ", + "prefailure": false, + "updated_online": true, + "performance": false, + "error_rate": false, + "event_count": true, + "auto_keep": true + }, + "raw": { + "value": 9, + "string": "9" + } + }, + { + "id": 22, + "name": "Unknown_Attribute", + "value": 100, + "worst": 100, + "thresh": 25, + "when_failed": "", + "flags": { + "value": 35, + "string": "PO---K ", + "prefailure": true, + "updated_online": true, + "performance": false, + "error_rate": false, + "event_count": false, + "auto_keep": true + }, + "raw": { + "value": 100, + "string": "100" + } + }, + { + "id": 192, + "name": "Power-Off_Retract_Count", + "value": 100, + "worst": 100, + "thresh": 0, + "when_failed": "", + "flags": { + "value": 50, + "string": "-O--CK ", + "prefailure": false, + "updated_online": true, + "performance": false, + "error_rate": false, + "event_count": true, + "auto_keep": true + }, + "raw": { + "value": 329, + "string": "329" + } + }, + { + "id": 193, + "name": "Load_Cycle_Count", + "value": 100, + "worst": 100, + "thresh": 0, + "when_failed": "", + "flags": { + "value": 18, + "string": "-O--C- ", + "prefailure": false, + "updated_online": true, + "performance": false, + "error_rate": false, + "event_count": true, + "auto_keep": false + }, + "raw": { + "value": 329, + "string": "329" + } + }, + { + "id": 194, + "name": "Temperature_Celsius", + "value": 51, + "worst": 51, + "thresh": 0, + "when_failed": "", + "flags": { + "value": 2, + "string": "-O---- ", + "prefailure": false, + "updated_online": true, + "performance": false, + "error_rate": false, + "event_count": false, + "auto_keep": false + }, + "raw": { + "value": 163210330144, + "string": "32 (Min/Max 24/38)" + } + }, + { + "id": 196, + "name": "Reallocated_Event_Count", + "value": 100, + "worst": 100, + "thresh": 0, + "when_failed": "", + "flags": { + "value": 50, + "string": "-O--CK ", + "prefailure": false, + "updated_online": true, + "performance": false, + "error_rate": false, + "event_count": true, + "auto_keep": true + }, + "raw": { + "value": 0, + "string": "0" + } + }, + { + "id": 197, + "name": "Current_Pending_Sector", + "value": 100, + "worst": 100, + "thresh": 0, + "when_failed": "", + "flags": { + "value": 34, + "string": "-O---K ", + "prefailure": false, + "updated_online": true, + "performance": false, + "error_rate": false, + "event_count": false, + "auto_keep": true + }, + "raw": { + "value": 0, + "string": "0" + } + }, + { + "id": 198, + "name": "Offline_Uncorrectable", + "value": 100, + "worst": 100, + "thresh": 0, + "when_failed": "", + "flags": { + "value": 8, + "string": "---R-- ", + "prefailure": false, + "updated_online": false, + "performance": false, + "error_rate": true, + "event_count": false, + "auto_keep": false + }, + "raw": { + "value": 0, + "string": "0" + } + }, + { + "id": 199, + "name": "UDMA_CRC_Error_Count", + "value": 100, + "worst": 100, + "thresh": 0, + "when_failed": "", + "flags": { + "value": 10, + "string": "-O-R-- ", + "prefailure": false, + "updated_online": true, + "performance": false, + "error_rate": true, + "event_count": false, + "auto_keep": false + }, + "raw": { + "value": 0, + "string": "0" + } + } + ] + }, + "power_on_time": { + "hours": 1730 + }, + "power_cycle_count": 9, + "temperature": { + "current": 32 + }, + "ata_smart_error_log": { + "summary": { + "revision": 1, + "count": 0 + } + }, + "ata_smart_self_test_log": { + "standard": { + "revision": 1, + "table": [ + { + "type": { + "value": 1, + "string": "Short offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1708 + }, + { + "type": { + "value": 1, + "string": "Short offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1684 + }, + { + "type": { + "value": 1, + "string": "Short offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1661 + }, + { + "type": { + "value": 1, + "string": "Short offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1636 + }, + { + "type": { + "value": 2, + "string": "Extended offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1624 + }, + { + "type": { + "value": 1, + "string": "Short offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1541 + }, + { + "type": { + "value": 1, + "string": "Short offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1517 + }, + { + "type": { + "value": 1, + "string": "Short offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1493 + }, + { + "type": { + "value": 1, + "string": "Short offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1469 + }, + { + "type": { + "value": 1, + "string": "Short offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1445 + }, + { + "type": { + "value": 2, + "string": "Extended offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1439 + }, + { + "type": { + "value": 1, + "string": "Short offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1373 + }, + { + "type": { + "value": 1, + "string": "Short offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1349 + }, + { + "type": { + "value": 1, + "string": "Short offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1325 + }, + { + "type": { + "value": 1, + "string": "Short offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1301 + }, + { + "type": { + "value": 1, + "string": "Short offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1277 + }, + { + "type": { + "value": 1, + "string": "Short offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1253 + }, + { + "type": { + "value": 2, + "string": "Extended offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1252 + }, + { + "type": { + "value": 1, + "string": "Short offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1205 + }, + { + "type": { + "value": 1, + "string": "Short offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1181 + }, + { + "type": { + "value": 1, + "string": "Short offline" + }, + "status": { + "value": 0, + "string": "Completed without error", + "passed": true + }, + "lifetime_hours": 1157 + } + ], + "count": 21, + "error_count_total": 0, + "error_count_outdated": 0 + } + }, + "ata_smart_selective_self_test_log": { + "revision": 1, + "table": [ + { + "lba_min": 0, + "lba_max": 0, + "status": { + "value": 241, + "string": "Not_testing" + } + }, + { + "lba_min": 0, + "lba_max": 0, + "status": { + "value": 241, + "string": "Not_testing" + } + }, + { + "lba_min": 0, + "lba_max": 0, + "status": { + "value": 241, + "string": "Not_testing" + } + }, + { + "lba_min": 0, + "lba_max": 0, + "status": { + "value": 241, + "string": "Not_testing" + } + }, + { + "lba_min": 0, + "lba_max": 0, + "status": { + "value": 241, + "string": "Not_testing" + } + } + ], + "flags": { + "value": 0, + "remainder_scan_enabled": false + }, + "power_up_scan_resume_minutes": 0 + } +} diff --git a/webapp/frontend/src/app/data/mock/device/details/data.ts b/webapp/frontend/src/app/data/mock/device/details/data.ts index 6100b34..afd47e5 100644 --- a/webapp/frontend/src/app/data/mock/device/details/data.ts +++ b/webapp/frontend/src/app/data/mock/device/details/data.ts @@ -31,7 +31,7 @@ export const details = { "temp": 35, "power_on_hours": 48706, "power_cycle_count": 69, - "smart_attributes": [ + "ata_attributes": [ { "ID": 2632, "CreatedAt": "2020-08-14T03:41:00.763627397Z", diff --git a/webapp/frontend/src/app/data/mock/summary/data.ts b/webapp/frontend/src/app/data/mock/summary/data.ts index 09d11c0..3a064ed 100644 --- a/webapp/frontend/src/app/data/mock/summary/data.ts +++ b/webapp/frontend/src/app/data/mock/summary/data.ts @@ -51,7 +51,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null }, { "ID": 137, @@ -64,7 +64,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null }, { "ID": 129, @@ -77,7 +77,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null }, { "ID": 123, @@ -90,7 +90,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null }, { "ID": 119, @@ -103,7 +103,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null }, { "ID": 106, @@ -116,7 +116,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null }, { "ID": 99, @@ -129,7 +129,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null }, { "ID": 92, @@ -142,7 +142,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null }, { "ID": 85, @@ -155,7 +155,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null }, { "ID": 78, @@ -168,7 +168,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null }, { "ID": 71, @@ -181,7 +181,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null }, { "ID": 64, @@ -194,7 +194,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null }, { "ID": 57, @@ -207,7 +207,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null }, { "ID": 50, @@ -220,7 +220,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null }, { "ID": 43, @@ -233,7 +233,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null }, { "ID": 36, @@ -246,7 +246,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null }, { "ID": 29, @@ -259,7 +259,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null }, { "ID": 27, @@ -272,7 +272,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null }, { "ID": 15, @@ -285,7 +285,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null }, { "ID": 12, @@ -298,7 +298,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null }, { "ID": 1, @@ -311,7 +311,7 @@ export const summary = { "temp": 36, "power_on_hours": 13818, "power_cycle_count": 13, - "smart_attributes": null + "ata_attributes": null } ] }, @@ -344,7 +344,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 138, @@ -357,7 +357,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 128, @@ -370,7 +370,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 120, @@ -383,7 +383,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 114, @@ -396,7 +396,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 110, @@ -409,7 +409,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 103, @@ -422,7 +422,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 97, @@ -435,7 +435,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 90, @@ -448,7 +448,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 80, @@ -461,7 +461,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 73, @@ -474,7 +474,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 69, @@ -487,7 +487,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 61, @@ -500,7 +500,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 54, @@ -513,7 +513,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 48, @@ -526,7 +526,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 39, @@ -539,7 +539,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 32, @@ -552,7 +552,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 26, @@ -565,7 +565,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 18, @@ -578,7 +578,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 10, @@ -591,7 +591,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 3, @@ -604,7 +604,7 @@ export const summary = { "temp": 34, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null } ] }, @@ -637,7 +637,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 139, @@ -650,7 +650,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 131, @@ -663,7 +663,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 124, @@ -676,7 +676,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 116, @@ -689,7 +689,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 109, @@ -702,7 +702,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 100, @@ -715,7 +715,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 95, @@ -728,7 +728,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 87, @@ -741,7 +741,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 79, @@ -754,7 +754,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 74, @@ -767,7 +767,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 65, @@ -780,7 +780,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 60, @@ -793,7 +793,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 51, @@ -806,7 +806,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 47, @@ -819,7 +819,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 38, @@ -832,7 +832,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 34, @@ -845,7 +845,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 24, @@ -858,7 +858,7 @@ export const summary = { "temp": 33, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 16, @@ -871,7 +871,7 @@ export const summary = { "temp": 33, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 8, @@ -884,7 +884,7 @@ export const summary = { "temp": 33, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 2, @@ -897,7 +897,7 @@ export const summary = { "temp": 33, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null } ] }, @@ -930,7 +930,7 @@ export const summary = { "temp": 30, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null }, { "ID": 135, @@ -943,7 +943,7 @@ export const summary = { "temp": 30, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null }, { "ID": 130, @@ -956,7 +956,7 @@ export const summary = { "temp": 30, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null }, { "ID": 125, @@ -969,7 +969,7 @@ export const summary = { "temp": 30, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null }, { "ID": 113, @@ -982,7 +982,7 @@ export const summary = { "temp": 30, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null }, { "ID": 111, @@ -995,7 +995,7 @@ export const summary = { "temp": 30, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null }, { "ID": 102, @@ -1008,7 +1008,7 @@ export const summary = { "temp": 30, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null }, { "ID": 94, @@ -1021,7 +1021,7 @@ export const summary = { "temp": 30, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null }, { "ID": 88, @@ -1034,7 +1034,7 @@ export const summary = { "temp": 30, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null }, { "ID": 83, @@ -1047,7 +1047,7 @@ export const summary = { "temp": 30, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null }, { "ID": 72, @@ -1060,7 +1060,7 @@ export const summary = { "temp": 29, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null }, { "ID": 66, @@ -1073,7 +1073,7 @@ export const summary = { "temp": 29, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null }, { "ID": 59, @@ -1086,7 +1086,7 @@ export const summary = { "temp": 29, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null }, { "ID": 55, @@ -1099,7 +1099,7 @@ export const summary = { "temp": 29, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null }, { "ID": 45, @@ -1112,7 +1112,7 @@ export const summary = { "temp": 29, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null }, { "ID": 40, @@ -1125,7 +1125,7 @@ export const summary = { "temp": 29, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null }, { "ID": 30, @@ -1138,7 +1138,7 @@ export const summary = { "temp": 29, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null }, { "ID": 23, @@ -1151,7 +1151,7 @@ export const summary = { "temp": 29, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null }, { "ID": 20, @@ -1164,7 +1164,7 @@ export const summary = { "temp": 29, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null }, { "ID": 11, @@ -1177,7 +1177,7 @@ export const summary = { "temp": 29, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null }, { "ID": 7, @@ -1190,7 +1190,7 @@ export const summary = { "temp": 29, "power_on_hours": 24996, "power_cycle_count": 42, - "smart_attributes": null + "ata_attributes": null } ] }, @@ -1223,7 +1223,7 @@ export const summary = { "temp": 33, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 136, @@ -1236,7 +1236,7 @@ export const summary = { "temp": 33, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 132, @@ -1249,7 +1249,7 @@ export const summary = { "temp": 33, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 122, @@ -1262,7 +1262,7 @@ export const summary = { "temp": 33, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 118, @@ -1275,7 +1275,7 @@ export const summary = { "temp": 33, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 108, @@ -1288,7 +1288,7 @@ export const summary = { "temp": 33, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 101, @@ -1301,7 +1301,7 @@ export const summary = { "temp": 33, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 96, @@ -1314,7 +1314,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 86, @@ -1327,7 +1327,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 81, @@ -1340,7 +1340,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 75, @@ -1353,7 +1353,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 67, @@ -1366,7 +1366,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 62, @@ -1379,7 +1379,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 53, @@ -1392,7 +1392,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 46, @@ -1405,7 +1405,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 41, @@ -1418,7 +1418,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 31, @@ -1431,7 +1431,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 22, @@ -1444,7 +1444,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 17, @@ -1457,7 +1457,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 9, @@ -1470,7 +1470,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null }, { "ID": 4, @@ -1483,7 +1483,7 @@ export const summary = { "temp": 32, "power_on_hours": 3030, "power_cycle_count": 9, - "smart_attributes": null + "ata_attributes": null } ] }, @@ -1516,7 +1516,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null }, { "ID": 134, @@ -1529,7 +1529,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null }, { "ID": 127, @@ -1542,7 +1542,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null }, { "ID": 121, @@ -1555,7 +1555,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null }, { "ID": 115, @@ -1568,7 +1568,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null }, { "ID": 107, @@ -1581,7 +1581,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null }, { "ID": 104, @@ -1594,7 +1594,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null }, { "ID": 93, @@ -1607,7 +1607,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null }, { "ID": 89, @@ -1620,7 +1620,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null }, { "ID": 82, @@ -1633,7 +1633,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null }, { "ID": 76, @@ -1646,7 +1646,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null }, { "ID": 68, @@ -1659,7 +1659,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null }, { "ID": 58, @@ -1672,7 +1672,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null }, { "ID": 52, @@ -1685,7 +1685,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null }, { "ID": 44, @@ -1698,7 +1698,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null }, { "ID": 37, @@ -1711,7 +1711,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null }, { "ID": 33, @@ -1724,7 +1724,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null }, { "ID": 25, @@ -1737,7 +1737,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null }, { "ID": 19, @@ -1750,7 +1750,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null }, { "ID": 13, @@ -1763,7 +1763,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null }, { "ID": 5, @@ -1776,7 +1776,7 @@ export const summary = { "temp": 30, "power_on_hours": 46949, "power_cycle_count": 54, - "smart_attributes": null + "ata_attributes": null } ] }, @@ -1809,7 +1809,7 @@ export const summary = { "temp": 35, "power_on_hours": 48706, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null }, { "ID": 140, @@ -1822,7 +1822,7 @@ export const summary = { "temp": 35, "power_on_hours": 48706, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null }, { "ID": 133, @@ -1835,7 +1835,7 @@ export const summary = { "temp": 35, "power_on_hours": 48706, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null }, { "ID": 126, @@ -1848,7 +1848,7 @@ export const summary = { "temp": 35, "power_on_hours": 48706, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null }, { "ID": 117, @@ -1861,7 +1861,7 @@ export const summary = { "temp": 35, "power_on_hours": 48706, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null }, { "ID": 112, @@ -1874,7 +1874,7 @@ export const summary = { "temp": 35, "power_on_hours": 48706, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null }, { "ID": 105, @@ -1887,7 +1887,7 @@ export const summary = { "temp": 35, "power_on_hours": 48706, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null }, { "ID": 98, @@ -1900,7 +1900,7 @@ export const summary = { "temp": 35, "power_on_hours": 48706, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null }, { "ID": 91, @@ -1913,7 +1913,7 @@ export const summary = { "temp": 35, "power_on_hours": 48706, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null }, { "ID": 84, @@ -1926,7 +1926,7 @@ export const summary = { "temp": 35, "power_on_hours": 48706, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null }, { "ID": 77, @@ -1939,7 +1939,7 @@ export const summary = { "temp": 35, "power_on_hours": 48706, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null }, { "ID": 70, @@ -1952,7 +1952,7 @@ export const summary = { "temp": 35, "power_on_hours": 48706, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null }, { "ID": 63, @@ -1965,7 +1965,7 @@ export const summary = { "temp": 35, "power_on_hours": 48706, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null }, { "ID": 56, @@ -1978,7 +1978,7 @@ export const summary = { "temp": 35, "power_on_hours": 48706, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null }, { "ID": 49, @@ -1991,7 +1991,7 @@ export const summary = { "temp": 35, "power_on_hours": 48706, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null }, { "ID": 42, @@ -2004,7 +2004,7 @@ export const summary = { "temp": 35, "power_on_hours": 48706, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null }, { "ID": 35, @@ -2017,7 +2017,7 @@ export const summary = { "temp": 35, "power_on_hours": 48706, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null }, { "ID": 28, @@ -2030,7 +2030,7 @@ export const summary = { "temp": 35, "power_on_hours": 48706, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null }, { "ID": 21, @@ -2043,7 +2043,7 @@ export const summary = { "temp": 35, "power_on_hours": 48706, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null }, { "ID": 14, @@ -2056,7 +2056,7 @@ export const summary = { "temp": 35, "power_on_hours": 48705, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null }, { "ID": 6, @@ -2069,7 +2069,7 @@ export const summary = { "temp": 35, "power_on_hours": 48705, "power_cycle_count": 69, - "smart_attributes": null + "ata_attributes": null } ] } diff --git a/webapp/frontend/src/app/modules/admin/dashboard/dashboard.component.html b/webapp/frontend/src/app/modules/admin/dashboard/dashboard.component.html index 4817b6a..09212ac 100644 --- a/webapp/frontend/src/app/modules/admin/dashboard/dashboard.component.html +++ b/webapp/frontend/src/app/modules/admin/dashboard/dashboard.component.html @@ -51,8 +51,9 @@
-
-
+
+
/dev/{{disk.device_name}} - {{disk.model_name}} -
+
Last Updated on {{disk.smart_results[0]?.date | date:'MMMM dd, yyyy' }}
@@ -89,11 +94,13 @@
S.M.A.R.T
-
{{ disk.smart_results[0]?.smart_status | titlecase}}
+
{{ disk.smart_results[0]?.smart_status | titlecase}}
+
No Data
Temperature
-
{{ disk.smart_results[0]?.temp }}°C
+
{{ disk.smart_results[0]?.temp }}°C
+
--
Capacity
diff --git a/webapp/frontend/src/app/modules/admin/detail/detail.component.html b/webapp/frontend/src/app/modules/admin/detail/detail.component.html index 65f29e2..a5bc4ad 100644 --- a/webapp/frontend/src/app/modules/admin/detail/detail.component.html +++ b/webapp/frontend/src/app/modules/admin/detail/detail.component.html @@ -83,6 +83,10 @@
{{data.data.rotational_speed}} RPM
Rotation Rate
+
+
{{data.data.device_protocol}}
+
Protocol
+
{{data.data.smart_results[0]?.power_cycle_count}}
Power Cycle Count
@@ -103,7 +107,7 @@
S.M.A.R.T Attributes
-
{{this.smartAttributeDataSource.data.length}} visible, {{this.data.data.smart_results[0]?.smart_attributes.length - this.smartAttributeDataSource.data.length}} hidden
+
{{this.smartAttributeDataSource.data.length}} visible, {{this.data.data.smart_results[0]?.ata_attributes.length - this.smartAttributeDataSource.data.length}} hidden
@@ -187,8 +191,8 @@ @@ -206,7 +210,7 @@ @@ -224,7 +228,7 @@ @@ -242,7 +246,7 @@ diff --git a/webapp/frontend/src/app/modules/admin/detail/detail.component.ts b/webapp/frontend/src/app/modules/admin/detail/detail.component.ts index d2220ab..987ca8c 100644 --- a/webapp/frontend/src/app/modules/admin/detail/detail.component.ts +++ b/webapp/frontend/src/app/modules/admin/detail/detail.component.ts @@ -93,8 +93,12 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy { // ----------------------------------------------------------------------------------------------------- // @ Private methods // ----------------------------------------------------------------------------------------------------- + getAttributeDescription(attribute_data){ + return this.data.lookup[attribute_data.attribute_id]?.description + } - extractAttributeValue(attribute_metadata, attribute_data){ + getAttributeValue(attribute_data){ + let attribute_metadata = this.data.lookup[attribute_data.attribute_id] if(attribute_metadata.display_type == "raw"){ return attribute_data.raw_value } @@ -105,6 +109,22 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy { } } + getAttributeValueType(attribute_data){ + let attribute_metadata = this.data.lookup[attribute_data.attribute_id] + return this.data.lookup[attribute_data.attribute_id].display_type + } + + getAttributeIdeal(attribute_data){ + return this.data.lookup[attribute_data.attribute_id]?.display_type == "raw" ? this.data.lookup[attribute_data.attribute_id]?.ideal : '' + } + + getAttributeWorst(attribute_data){ + return attribute_data.worst + } + getAttributeThreshold(attribute_data){ + return attribute_data.thresh + } + private _generateSmartAttributeTableDataSource(smart_results){ var smartAttributeDataSource = []; @@ -113,14 +133,11 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy { } var latest_smart_result = smart_results[0]; - for(let attr of latest_smart_result.smart_attributes){ - - - + for(let attr of latest_smart_result.ata_attributes){ //chart history data if (!attr.chartData) { - var rawHistory = (attr.history || []).map(hist_attr => this.extractAttributeValue(this.data.lookup[attr.attribute_id], hist_attr)).reverse() - rawHistory.push(this.extractAttributeValue(this.data.lookup[attr.attribute_id], attr)) + var rawHistory = (attr.history || []).map(hist_attr => this.getAttributeValue(hist_attr)).reverse() + rawHistory.push(this.getAttributeValue(attr)) attr.chartData = [ { name: "chart-line-sparkline", @@ -128,23 +145,6 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy { data: rawHistory } ] - - // //add the reference line showing the threshold - // attr.chartDataReferenceLine = { - // yaxis: [ - // { - // y: attr.thresh, - // borderColor: '#f05252', - // label: { - // borderColor: '#f05252', - // style: { - // color: '#fff', - // background: '#f05252' - // }, - // } - // } - // ] - // } } //determine when to include the attributes in table. if(!this.onlyCritical || this.onlyCritical && this.data.lookup[attr.attribute_id]?.critical || attr.value <= attr.thresh){ diff --git a/webapp/frontend/src/app/shared/device-sort.pipe.spec.ts b/webapp/frontend/src/app/shared/device-sort.pipe.spec.ts new file mode 100644 index 0000000..3f9eb0f --- /dev/null +++ b/webapp/frontend/src/app/shared/device-sort.pipe.spec.ts @@ -0,0 +1,8 @@ +import { DeviceSortPipe } from './device-sort.pipe'; + +describe('DeviceSortPipe', () => { + it('create an instance', () => { + const pipe = new DeviceSortPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/webapp/frontend/src/app/shared/device-sort.pipe.ts b/webapp/frontend/src/app/shared/device-sort.pipe.ts new file mode 100644 index 0000000..6f115f1 --- /dev/null +++ b/webapp/frontend/src/app/shared/device-sort.pipe.ts @@ -0,0 +1,33 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'deviceSort' +}) +export class DeviceSortPipe implements PipeTransform { + + numericalStatus(device): number { + if(!device.smart_results[0]){ + return 0 + } else if (device.smart_results[0].smart_status == 'passed'){ + return 1 + } else { + return -1 + } + } + + + transform(devices: Array, ...args: unknown[]): Array { + //failed, unknown/empty, passed + devices.sort((a: any, b: any) => { + + let left = this.numericalStatus(a) + let right = this.numericalStatus(b) + + return left - right; + }); + + + return devices; + } + +} diff --git a/webapp/frontend/src/app/shared/shared.module.ts b/webapp/frontend/src/app/shared/shared.module.ts index ef5abf4..64ef282 100644 --- a/webapp/frontend/src/app/shared/shared.module.ts +++ b/webapp/frontend/src/app/shared/shared.module.ts @@ -2,10 +2,12 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import {FileSizePipe} from "./file-size.pipe"; +import { DeviceSortPipe } from './device-sort.pipe'; @NgModule({ declarations: [ - FileSizePipe + FileSizePipe, + DeviceSortPipe ], imports: [ CommonModule, @@ -16,7 +18,8 @@ import {FileSizePipe} from "./file-size.pipe"; CommonModule, FormsModule, ReactiveFormsModule, - FileSizePipe + FileSizePipe, + DeviceSortPipe ] }) export class SharedModule diff --git a/webapp/frontend/src/assets/images/logo/scrutiny-logo-dark-social.png b/webapp/frontend/src/assets/images/logo/scrutiny-logo-dark-social.png new file mode 100644 index 0000000..7e2474e Binary files /dev/null and b/webapp/frontend/src/assets/images/logo/scrutiny-logo-dark-social.png differ diff --git a/webapp/frontend/src/assets/images/logo/scrutiny-logo-dark-social.psd b/webapp/frontend/src/assets/images/logo/scrutiny-logo-dark-social.psd new file mode 100644 index 0000000..2bddf02 Binary files /dev/null and b/webapp/frontend/src/assets/images/logo/scrutiny-logo-dark-social.psd differ
- + {{attribute.name}} - - {{extractAttributeValue(data.lookup[attribute.attribute_id], attribute)}} + + {{getAttributeValue(attribute)}} - {{attribute.worst}} + {{getAttributeWorst(attribute)}} - {{attribute.thresh}} + {{getAttributeThreshold(attribute)}} - {{data.lookup[attribute.attribute_id]?.display_type == "raw" ? data.lookup[attribute.attribute_id]?.ideal : '' }} + {{getAttributeIdeal(attribute) }}