diff --git a/.editorconfig b/.editorconfig index 95f10d1..23d0200 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,9 +10,6 @@ max_line_length = 88 [*.py] indent_style = space -[*.{jsx,tsx}] -indent_size = 2 - [*.{json,md,rst,ini,yml,yaml}] indent_style = space indent_size = 2 diff --git a/Makefile b/Makefile index a9d473f..6557106 100644 --- a/Makefile +++ b/Makefile @@ -25,11 +25,10 @@ build-server: build: build-ui build-server # Protobuf-API-Definition herunterladen und Code generieren -download-proto: +protoc: wget "https://code.thetadev.de/TSGRain/Controller/raw/branch/main/proto/tsgrain.proto" -O ${PROTO_FILE} echo 'option go_package = "code.thetadev.de/TSGRain/WebUI/src/tsgrain_rpc";' >> ${PROTO_FILE} -protoc: protoc --go_out ${SRC_DIR}/tsgrain_rpc --go_opt=paths=source_relative \ --go-grpc_out ${SRC_DIR}/tsgrain_rpc --go-grpc_opt=paths=source_relative \ ${PROTO_FILE} diff --git a/proto/tsgrain.proto b/proto/tsgrain.proto index a7bc75b..f9c7fdf 100644 --- a/proto/tsgrain.proto +++ b/proto/tsgrain.proto @@ -6,13 +6,7 @@ import "google/protobuf/wrappers.proto"; service TSGRain { // Starte eine neue Bewässerungsaufgabe (oder stoppe eine laufende, wenn // diese bereits läuft). - rpc RequestTask(TaskRequest) returns (TaskRequestResult) {} - - // Starte eine Bewässerungsaufgabe - rpc StartTask(TaskStart) returns (google.protobuf.BoolValue) {} - - // Stoppe eine Bewässerungsaufgabe - rpc StopTask(TaskStop) returns (google.protobuf.BoolValue) {} + rpc StartTask(TaskRequest) returns (TaskRequestResult) {} // Gibt sämtliche in der Warteschlange befindlichen Bewässerungsaufgaben zurück. rpc GetTasks(google.protobuf.Empty) returns (TaskList) {} @@ -36,12 +30,6 @@ service TSGRain { // Lösche den Bewässerungsjob mit der gegebenen ID. rpc DeleteJob(JobID) returns (google.protobuf.Empty) {} - // Aktiviere Bewässerungsjob - rpc EnableJob(JobID) returns (google.protobuf.Empty) {} - - // Deaktiviere Bewässerungsjob - rpc DisableJob(JobID) returns (google.protobuf.Empty) {} - // Gibt zurück, ob der Automatikmodus aktiviert ist. rpc GetAutoMode(google.protobuf.Empty) returns (google.protobuf.BoolValue) {} @@ -49,13 +37,10 @@ service TSGRain { rpc SetAutoMode(google.protobuf.BoolValue) returns (google.protobuf.Empty) {} // Datum/Uhrzeit/Zeitzone abrufen - rpc GetSystemTime(google.protobuf.Empty) returns (SystemTime) {} + rpc GetConfigTime(google.protobuf.Empty) returns (ConfigTime) {} - // Datum/Uhrzeit einstellen - rpc SetSystemTime(Timestamp) returns (google.protobuf.Empty) {} - - // Zeitzone einstellen - rpc SetSystemTimezone(google.protobuf.StringValue) returns (google.protobuf.Empty) {} + // Datum/Uhrzeit/Zeitzone einstellen + rpc SetConfigTime(ConfigTime) returns (google.protobuf.Empty) {} // Standardzeit bei manueller Bewässerung abrufen rpc GetDefaultIrrigationTime(google.protobuf.Empty) returns (google.protobuf.Int32Value) {} @@ -91,18 +76,6 @@ message TaskRequestResult { bool stopped = 2; } -message TaskStart { - TaskSource source = 1; - int32 zone_id = 2; - int32 duration = 3; - bool queuing = 4; -} - -message TaskStop { - TaskSource source = 1; - int32 zone_id = 2; -} - message Task { TaskSource source = 1; int32 zone_id = 2; @@ -134,7 +107,7 @@ message JobList { repeated Job jobs = 1; } -message SystemTime { +message ConfigTime { Timestamp datetime = 1; string timezone = 2; } diff --git a/src/model/options.go b/src/model/options.go index 0d931ac..a2fb2db 100644 --- a/src/model/options.go +++ b/src/model/options.go @@ -7,7 +7,7 @@ package model //swagger:model AutoMode type AutoMode struct { // required: true - State bool `json:"state"` + State bool `json:"state" binding:"required"` } // DefaultIrrigationTime model @@ -20,32 +20,12 @@ type DefaultIrrigationTime struct { Time int32 `json:"time" binding:"required"` } -// Timestamp model -// -// Zeitstempel -// -//swagger:model Timestamp -type Timestamp struct { - // required: true - Time int64 `json:"time" binding:"required"` -} - -// Timezone model -// -// Systemzeitzone -// -//swagger:model Timezone -type Timezone struct { - // required: true - Timezone string `json:"timezone" binding:"required"` -} - -// SystemTime model +// ConfigTime model // // Aktuelle Systemzeit/Zeitzone // -//swagger:model SystemTime -type SystemTime struct { +//swagger:model ConfigTime +type ConfigTime struct { // Aktuelle Systemzeit // // required: true diff --git a/src/model/task.go b/src/model/task.go index a2a272f..bb398e5 100644 --- a/src/model/task.go +++ b/src/model/task.go @@ -54,7 +54,12 @@ type TaskList struct { AutoMode bool `json:"auto_mode"` } -//swagger:model ZoneID -type ZoneID struct { - Id int32 `json:"id" binding:"required"` +// TaskRequestResult model +// +// TaskRequestResult wird beim Starten eines Tasks zurückgegeben +// +//swagger:model TaskRequestResult +type TaskRequestResult struct { + Started bool + Stopped bool } diff --git a/src/server/server.go b/src/server/server.go index 0ac84a8..bec8cf5 100644 --- a/src/server/server.go +++ b/src/server/server.go @@ -14,7 +14,6 @@ import ( "errors" "fmt" "net/http" - "strconv" "time" "code.thetadev.de/TSGRain/WebUI/src/config" @@ -85,27 +84,19 @@ func (srv *WebUIServer) getRouter() *gin.Engine { api.GET("/panic", srv.controllerPanic) } - api.POST("/task/start", srv.controllerStartTask) - api.POST("/task/stop", srv.controllerStopTask) - - api.GET("/tasks", srv.controllerGetTasks) + api.POST("/task/manual", srv.controllerStartTask) api.GET("/jobs", srv.controllerGetJobs) - - api.GET("/job", srv.controllerGetJob) api.POST("/job", srv.controllerCreateJob) api.PUT("/job", srv.controllerUpdateJob) api.DELETE("/job", srv.controllerDeleteJob) api.GET("config/auto", srv.controllerGetAutoMode) api.POST("config/auto", srv.controllerSetAutoMode) - api.GET("config/defaultIrrigationTime", srv.controllerGetDefaultIrrigationTime) api.POST("config/defaultIrrigationTime", srv.controllerSetDefaultIrrigationTime) - - api.GET("config/time", srv.controllerGetSystemTime) - api.POST("config/time", srv.controllerSetSystemTime) - api.POST("config/timezone", srv.controllerSetSystemTimezone) + api.GET("config/time", srv.controllerGetConfigTime) + api.POST("config/time", srv.controllerSetConfigTime) // UI uiGroup := router.Group("/", middleware.Compression( @@ -143,122 +134,85 @@ func (srv *WebUIServer) Run() error { return err } -// swagger:operation POST /task/start startTask +// swagger:operation POST /task/manual startManualTask // -// Starte eine neue manuelle Bewässerungsaufgabe -// mit der eingestellten Standardzeit. +// Starte/stoppe manuell eine neue Bewässerungsaufgabe // // --- // consumes: [application/json] // produces: [application/json] // parameters: -// - name: zoneId -// in: body -// description: ZoneID +// - in: body +// name: taskRequest // schema: -// $ref: '#/definitions/ZoneID' +// type: object +// properties: +// zone_id: +// description: Nummer der Bewässerungszone +// type: integer +// duration: +// description: "Bewässerungsdauer in Sekunden (0: Standarddauer)" +// type: integer +// queuing: +// description: | +// Aufgabe in die Warteschlange einreihen, +// wenn sie nicht sofort ausgeführt werden kann. +// type: boolean +// cancelling: +// description: | +// Aufgabe stoppen/aus der Warteschlange entfernen, +// wenn sie bereits läuft oder sich in der Warteschlange befindet. +// type: boolean +// required: +// - zone_id +// - duration +// - queuing +// - cancelling // responses: // 200: -// description: OK +// description: Bewässerungsaufgabe erfolgreich gestarted/gestoppt // schema: // $ref: "#/definitions/StatusMessage" +// 400: +// description: Bewässerungsaufgabe läuft schon und kann nicht gestoppt werden. +// schema: +// $ref: "#/definitions/Error" // 500: // description: Serverfehler // schema: // $ref: "#/definitions/Error" func (srv *WebUIServer) controllerStartTask(c *gin.Context) { - var zoneId model.ZoneID - if err := c.ShouldBindJSON(&zoneId); err != nil { + var params struct { + ZoneID int32 `json:"zone_id"` + Duration int32 `json:"duration"` + Queuing bool `json:"queuing"` + Cancelling bool `json:"cancelling"` + } + + if err := c.ShouldBindJSON(¶ms); err != nil { log.Error().Err(err).Msg("StartTask input error") writeStatus(c, http.StatusBadRequest, "invalid input data") return } + if !srv.validateZoneID(params.ZoneID) { + writeStatus(c, http.StatusBadRequest, "invalid zone_id") + return + } - ok, err := srv.rpc.StartManualTask(zoneId.Id, 0) + res, err := srv.rpc.StartManualTask( + params.ZoneID, params.Duration, params.Queuing, params.Cancelling) if err != nil { - log.Error().Err(err).Msg("StartTask") + log.Error().Err(err).Msg("StartManualTask") writeStatus(c, http.StatusInternalServerError, "error starting task") return } - if !ok { - log.Error().Msg("StartTask: alrady running") - writeStatus(c, http.StatusBadRequest, "task already running") - return + statusCode := 200 + if !res.Started && !res.Stopped { + statusCode = 400 } - writeStatus(c, http.StatusOK, "task started") -} - -// swagger:operation POST /task/stop stopTask -// -// Stoppe eine manuelle Bewässerungsaufgabe. -// -// --- -// consumes: [application/json] -// produces: [application/json] -// parameters: -// - name: zoneId -// in: body -// description: ZoneID -// schema: -// $ref: '#/definitions/ZoneID' -// responses: -// 200: -// description: OK -// schema: -// $ref: "#/definitions/StatusMessage" -// 500: -// description: Serverfehler -// schema: -// $ref: "#/definitions/Error" -func (srv *WebUIServer) controllerStopTask(c *gin.Context) { - var zoneId model.ZoneID - if err := c.ShouldBindJSON(&zoneId); err != nil { - log.Error().Err(err).Msg("StopTask input error") - writeStatus(c, http.StatusBadRequest, "invalid input data") - return - } - - ok, err := srv.rpc.StopManualTask(zoneId.Id) - if err != nil { - log.Error().Err(err).Msg("StopTask") - writeStatus(c, http.StatusInternalServerError, "error stopping task") - return - } - if !ok { - log.Error().Msg("StopTask: no task to stop") - writeStatus(c, http.StatusBadRequest, "no task to stop") - return - } - - writeStatus(c, http.StatusOK, "task stopped") -} - -// swagger:operation GET /tasks getTasks -// -// Rufe alle momentan laufenden Bewässerungsaufgaben ab. -// -// --- -// produces: [application/json] -// responses: -// 200: -// description: Liste der Bewässerungsaufgaben -// schema: -// "$ref": "#/definitions/TaskList" -// 500: -// description: Serverfehler -// schema: -// "$ref": "#/definitions/Error" -func (srv *WebUIServer) controllerGetTasks(c *gin.Context) { - tasks, err := srv.rpc.GetTasks() - if err != nil { - log.Error().Err(err).Msg("GetTasks") - writeStatus(c, http.StatusInternalServerError, "error getting tasks") - return - } - - c.JSON(200, tasks) + c.JSON(statusCode, res) } // swagger:operation GET /jobs getJobs @@ -309,16 +263,17 @@ func (srv *WebUIServer) controllerGetJobs(c *gin.Context) { // schema: // $ref: "#/definitions/Error" func (srv *WebUIServer) controllerGetJob(c *gin.Context) { - idStr := c.Query("id") + var params struct { + Id int32 `uri:"id" binding:"required"` + } - id, err := strconv.ParseInt(idStr, 10, 32) - if err != nil { + if err := c.ShouldBindUri(¶ms); err != nil { log.Error().Err(err).Msg("GetJob input error") writeStatus(c, http.StatusBadRequest, "invalid input data") return } - job, err := srv.rpc.GetJob(int32(id)) + job, err := srv.rpc.GetJob(params.Id) if err != nil { log.Error().Err(err).Msg("GetJob") writeStatus(c, http.StatusInternalServerError, "error getting job") @@ -418,11 +373,10 @@ func (srv *WebUIServer) controllerUpdateJob(c *gin.Context) { // consumes: [application/json] // produces: [application/json] // parameters: -// - name: jobId +// - name: id // in: body -// description: JobID // schema: -// $ref: '#/definitions/JobID' +// type: integer // responses: // 200: // description: OK @@ -488,7 +442,12 @@ func (srv *WebUIServer) controllerGetAutoMode(c *gin.Context) { // name: state // description: Zustand des Automatikmodus // schema: -// $ref: '#/definitions/AutoMode' +// type: object +// properties: +// state: +// type: boolean +// required: +// - state // responses: // 200: // description: OK @@ -516,7 +475,7 @@ func (srv *WebUIServer) controllerSetAutoMode(c *gin.Context) { writeStatus(c, http.StatusOK, "set autoMode") } -// swagger:operation GET /config/time getSystemTime +// swagger:operation GET /config/time getConfigTime // // Rufe die aktuelle Systemzeit/Zeitzone ab // @@ -526,34 +485,34 @@ func (srv *WebUIServer) controllerSetAutoMode(c *gin.Context) { // 200: // description: Aktuelle Systemzeit/Zeitzone // schema: -// $ref: "#/definitions/SystemTime" +// $ref: "#/definitions/ConfigTime" // 500: // description: Serverfehler // schema: // $ref: "#/definitions/Error" -func (srv *WebUIServer) controllerGetSystemTime(c *gin.Context) { - systemTime, err := srv.rpc.GetSystemTime() +func (srv *WebUIServer) controllerGetConfigTime(c *gin.Context) { + configTime, err := srv.rpc.GetConfigTime() if err != nil { - log.Error().Err(err).Msg("GetSystemTime") - writeStatus(c, http.StatusInternalServerError, "error getting system time") + log.Error().Err(err).Msg("GetConfigTime") + writeStatus(c, http.StatusInternalServerError, "error setting configTime") return } - c.JSON(200, systemTime) + c.JSON(200, configTime) } -// swagger:operation POST /config/time setSystemTime +// swagger:operation POST /config/time setConfigTime // -// Systemzeit einstellen +// Automatikmodus aktivieren/deaktivieren // // --- // consumes: [application/json] // produces: [application/json] // parameters: // - in: body -// name: timestamp +// name: configTime // schema: -// $ref: "#/definitions/Timestamp" +// $ref: "#/definitions/ConfigTime" // responses: // 200: // description: OK @@ -563,61 +522,22 @@ func (srv *WebUIServer) controllerGetSystemTime(c *gin.Context) { // description: Serverfehler // schema: // $ref: "#/definitions/Error" -func (srv *WebUIServer) controllerSetSystemTime(c *gin.Context) { - var systemTime model.Timestamp - if err := c.ShouldBindJSON(&systemTime); err != nil { - log.Error().Err(err).Msg("SetSystemTime input error") +func (srv *WebUIServer) controllerSetConfigTime(c *gin.Context) { + var configTime model.ConfigTime + if err := c.ShouldBindJSON(&configTime); err != nil { + log.Error().Err(err).Msg("SetConfigTime input error") writeStatus(c, http.StatusBadRequest, "invalid input data") return } - err := srv.rpc.SetSystemTime(systemTime.Time) + err := srv.rpc.SetConfigTime(configTime) if err != nil { - log.Error().Err(err).Msg("SetSystemTime") - writeStatus(c, http.StatusInternalServerError, "error setting systemTime") + log.Error().Err(err).Msg("SetConfigTime") + writeStatus(c, http.StatusInternalServerError, "error setting configTime") return } - writeStatus(c, http.StatusOK, "set systemTime") -} - -// swagger:operation POST /config/timezone setSystemTimezone -// -// Systemzeitzone einstellen -// -// --- -// consumes: [application/json] -// produces: [application/json] -// parameters: -// - in: body -// name: timezone -// schema: -// $ref: "#/definitions/Timezone" -// responses: -// 200: -// description: OK -// schema: -// $ref: "#/definitions/StatusMessage" -// 500: -// description: Serverfehler -// schema: -// $ref: "#/definitions/Error" -func (srv *WebUIServer) controllerSetSystemTimezone(c *gin.Context) { - var timezone model.Timezone - if err := c.ShouldBindJSON(&timezone); err != nil { - log.Error().Err(err).Msg("SetSystemTimezone input error") - writeStatus(c, http.StatusBadRequest, "invalid input data") - return - } - - err := srv.rpc.SetSystemTimezone(timezone.Timezone) - if err != nil { - log.Error().Err(err).Msg("SetSystemTimezone") - writeStatus(c, http.StatusInternalServerError, "error setting systemTimezone") - return - } - - writeStatus(c, http.StatusOK, "set systemTimezone") + writeStatus(c, http.StatusOK, "set configTime") } // swagger:operation GET /config/defaultIrrigationTime getDefaultIrrigationTime @@ -644,7 +564,7 @@ func (srv *WebUIServer) controllerGetDefaultIrrigationTime(c *gin.Context) { return } - c.JSON(200, model.DefaultIrrigationTime{Time: defaultIrrigationTime}) + c.JSON(200, defaultIrrigationTime) } // swagger:operation POST /config/defaultIrrigationTime setDefaultIrrigationTime diff --git a/src/server/swagger/swagger.yaml b/src/server/swagger/swagger.yaml index a0bd762..a5d2036 100644 --- a/src/server/swagger/swagger.yaml +++ b/src/server/swagger/swagger.yaml @@ -8,6 +8,21 @@ definitions: - state title: AutoMode model type: object + ConfigTime: + description: Aktuelle Systemzeit/Zeitzone + properties: + time: + description: Aktuelle Systemzeit + format: int64 + type: integer + timezone: + description: Aktuelle Zeitzone + type: string + required: + - time + - timezone + title: ConfigTime model + type: object DefaultIrrigationTime: description: Manuelle Bewässerungszeit in Sekunden properties: @@ -143,21 +158,6 @@ definitions: - msg title: StatusMessage model type: object - SystemTime: - description: Aktuelle Systemzeit/Zeitzone - properties: - time: - description: Aktuelle Systemzeit - format: int64 - type: integer - timezone: - description: Aktuelle Zeitzone - type: string - required: - - time - - timezone - title: SystemTime model - type: object Task: description: Task stellt eine Bewässerungsaufgabe dar. properties: @@ -216,30 +216,14 @@ definitions: - auto_mode title: TaskList model type: object - Timestamp: - description: Zeitstempel + TaskRequestResult: + description: TaskRequestResult wird beim Starten eines Tasks zurückgegeben properties: - time: - format: int64 - type: integer - required: - - time - title: Timestamp model - type: object - Timezone: - description: Systemzeitzone - properties: - timezone: - type: string - required: - - timezone - title: Timezone model - type: object - ZoneID: - properties: - id: - format: int32 - type: integer + Started: + type: boolean + Stopped: + type: boolean + title: TaskRequestResult model type: object info: description: REST API for the TSGRain WebUI @@ -273,7 +257,12 @@ paths: in: body name: state schema: - $ref: "#/definitions/AutoMode" + properties: + state: + type: boolean + required: + - state + type: object produces: - application/json responses: @@ -324,14 +313,14 @@ paths: /config/time: get: description: Rufe die aktuelle Systemzeit/Zeitzone ab - operationId: getSystemTime + operationId: getConfigTime produces: - application/json responses: "200": description: Aktuelle Systemzeit/Zeitzone schema: - $ref: "#/definitions/SystemTime" + $ref: "#/definitions/ConfigTime" "500": description: Serverfehler schema: @@ -339,35 +328,13 @@ paths: post: consumes: - application/json - description: Systemzeit einstellen - operationId: setSystemTime + description: Automatikmodus aktivieren/deaktivieren + operationId: setConfigTime parameters: - in: body - name: timestamp + name: configTime schema: - $ref: "#/definitions/Timestamp" - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: "#/definitions/StatusMessage" - "500": - description: Serverfehler - schema: - $ref: "#/definitions/Error" - /config/timezone: - post: - consumes: - - application/json - description: Systemzeitzone einstellen - operationId: setSystemTimezone - parameters: - - in: body - name: timezone - schema: - $ref: "#/definitions/Timezone" + $ref: "#/definitions/ConfigTime" produces: - application/json responses: @@ -385,11 +352,10 @@ paths: - application/json operationId: deleteJob parameters: - - description: JobID - in: body - name: jobId + - in: body + name: id schema: - $ref: "#/definitions/JobID" + type: integer produces: - application/json responses: @@ -483,69 +449,54 @@ paths: schema: $ref: "#/definitions/Error" summary: Rufe alle gespeicherten Zeitpläne ab. - /task/start: + /task/manual: post: consumes: - application/json - description: |- - Starte eine neue manuelle Bewässerungsaufgabe - mit der eingestellten Standardzeit. - operationId: startTask + description: Starte/stoppe manuell eine neue Bewässerungsaufgabe + operationId: startManualTask parameters: - - description: ZoneID - in: body - name: zoneId + - in: body + name: taskRequest schema: - $ref: "#/definitions/ZoneID" + properties: + cancelling: + description: | + Aufgabe stoppen/aus der Warteschlange entfernen, + wenn sie bereits läuft oder sich in der Warteschlange befindet. + type: boolean + duration: + description: "Bewässerungsdauer in Sekunden (0: Standarddauer)" + type: integer + queuing: + description: | + Aufgabe in die Warteschlange einreihen, + wenn sie nicht sofort ausgeführt werden kann. + type: boolean + zone_id: + description: Nummer der Bewässerungszone + type: integer + required: + - zone_id + - duration + - queuing + - cancelling + type: object produces: - application/json responses: "200": - description: OK + description: Bewässerungsaufgabe erfolgreich gestarted/gestoppt schema: $ref: "#/definitions/StatusMessage" + "400": + description: Bewässerungsaufgabe läuft schon und kann nicht gestoppt werden. + schema: + $ref: "#/definitions/Error" "500": description: Serverfehler schema: $ref: "#/definitions/Error" - /task/stop: - post: - consumes: - - application/json - operationId: stopTask - parameters: - - description: ZoneID - in: body - name: zoneId - schema: - $ref: "#/definitions/ZoneID" - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: "#/definitions/StatusMessage" - "500": - description: Serverfehler - schema: - $ref: "#/definitions/Error" - summary: Stoppe eine manuelle Bewässerungsaufgabe. - /tasks: - get: - operationId: getTasks - produces: - - application/json - responses: - "200": - description: Liste der Bewässerungsaufgaben - schema: - $ref: "#/definitions/TaskList" - "500": - description: Serverfehler - schema: - $ref: "#/definitions/Error" - summary: Rufe alle momentan laufenden Bewässerungsaufgaben ab. schemes: - http - https diff --git a/src/tsgrain_rpc/proto/tsgrain.pb.go b/src/tsgrain_rpc/proto/tsgrain.pb.go index 8d9459f..923581a 100644 --- a/src/tsgrain_rpc/proto/tsgrain.pb.go +++ b/src/tsgrain_rpc/proto/tsgrain.pb.go @@ -251,132 +251,6 @@ func (x *TaskRequestResult) GetStopped() bool { return false } -type TaskStart struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Source TaskSource `protobuf:"varint,1,opt,name=source,proto3,enum=TaskSource" json:"source,omitempty"` - ZoneId int32 `protobuf:"varint,2,opt,name=zone_id,json=zoneId,proto3" json:"zone_id,omitempty"` - Duration int32 `protobuf:"varint,3,opt,name=duration,proto3" json:"duration,omitempty"` - Queuing bool `protobuf:"varint,4,opt,name=queuing,proto3" json:"queuing,omitempty"` -} - -func (x *TaskStart) Reset() { - *x = TaskStart{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_tsgrain_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TaskStart) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TaskStart) ProtoMessage() {} - -func (x *TaskStart) ProtoReflect() protoreflect.Message { - mi := &file_proto_tsgrain_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TaskStart.ProtoReflect.Descriptor instead. -func (*TaskStart) Descriptor() ([]byte, []int) { - return file_proto_tsgrain_proto_rawDescGZIP(), []int{3} -} - -func (x *TaskStart) GetSource() TaskSource { - if x != nil { - return x.Source - } - return TaskSource_MANUAL -} - -func (x *TaskStart) GetZoneId() int32 { - if x != nil { - return x.ZoneId - } - return 0 -} - -func (x *TaskStart) GetDuration() int32 { - if x != nil { - return x.Duration - } - return 0 -} - -func (x *TaskStart) GetQueuing() bool { - if x != nil { - return x.Queuing - } - return false -} - -type TaskStop struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Source TaskSource `protobuf:"varint,1,opt,name=source,proto3,enum=TaskSource" json:"source,omitempty"` - ZoneId int32 `protobuf:"varint,2,opt,name=zone_id,json=zoneId,proto3" json:"zone_id,omitempty"` -} - -func (x *TaskStop) Reset() { - *x = TaskStop{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_tsgrain_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TaskStop) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TaskStop) ProtoMessage() {} - -func (x *TaskStop) ProtoReflect() protoreflect.Message { - mi := &file_proto_tsgrain_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TaskStop.ProtoReflect.Descriptor instead. -func (*TaskStop) Descriptor() ([]byte, []int) { - return file_proto_tsgrain_proto_rawDescGZIP(), []int{4} -} - -func (x *TaskStop) GetSource() TaskSource { - if x != nil { - return x.Source - } - return TaskSource_MANUAL -} - -func (x *TaskStop) GetZoneId() int32 { - if x != nil { - return x.ZoneId - } - return 0 -} - type Task struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -392,7 +266,7 @@ type Task struct { func (x *Task) Reset() { *x = Task{} if protoimpl.UnsafeEnabled { - mi := &file_proto_tsgrain_proto_msgTypes[5] + mi := &file_proto_tsgrain_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -405,7 +279,7 @@ func (x *Task) String() string { func (*Task) ProtoMessage() {} func (x *Task) ProtoReflect() protoreflect.Message { - mi := &file_proto_tsgrain_proto_msgTypes[5] + mi := &file_proto_tsgrain_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -418,7 +292,7 @@ func (x *Task) ProtoReflect() protoreflect.Message { // Deprecated: Use Task.ProtoReflect.Descriptor instead. func (*Task) Descriptor() ([]byte, []int) { - return file_proto_tsgrain_proto_rawDescGZIP(), []int{5} + return file_proto_tsgrain_proto_rawDescGZIP(), []int{3} } func (x *Task) GetSource() TaskSource { @@ -469,7 +343,7 @@ type TaskList struct { func (x *TaskList) Reset() { *x = TaskList{} if protoimpl.UnsafeEnabled { - mi := &file_proto_tsgrain_proto_msgTypes[6] + mi := &file_proto_tsgrain_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -482,7 +356,7 @@ func (x *TaskList) String() string { func (*TaskList) ProtoMessage() {} func (x *TaskList) ProtoReflect() protoreflect.Message { - mi := &file_proto_tsgrain_proto_msgTypes[6] + mi := &file_proto_tsgrain_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -495,7 +369,7 @@ func (x *TaskList) ProtoReflect() protoreflect.Message { // Deprecated: Use TaskList.ProtoReflect.Descriptor instead. func (*TaskList) Descriptor() ([]byte, []int) { - return file_proto_tsgrain_proto_rawDescGZIP(), []int{6} + return file_proto_tsgrain_proto_rawDescGZIP(), []int{4} } func (x *TaskList) GetTasks() []*Task { @@ -535,7 +409,7 @@ type Job struct { func (x *Job) Reset() { *x = Job{} if protoimpl.UnsafeEnabled { - mi := &file_proto_tsgrain_proto_msgTypes[7] + mi := &file_proto_tsgrain_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -548,7 +422,7 @@ func (x *Job) String() string { func (*Job) ProtoMessage() {} func (x *Job) ProtoReflect() protoreflect.Message { - mi := &file_proto_tsgrain_proto_msgTypes[7] + mi := &file_proto_tsgrain_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -561,7 +435,7 @@ func (x *Job) ProtoReflect() protoreflect.Message { // Deprecated: Use Job.ProtoReflect.Descriptor instead. func (*Job) Descriptor() ([]byte, []int) { - return file_proto_tsgrain_proto_rawDescGZIP(), []int{7} + return file_proto_tsgrain_proto_rawDescGZIP(), []int{5} } func (x *Job) GetId() int32 { @@ -617,7 +491,7 @@ type JobID struct { func (x *JobID) Reset() { *x = JobID{} if protoimpl.UnsafeEnabled { - mi := &file_proto_tsgrain_proto_msgTypes[8] + mi := &file_proto_tsgrain_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -630,7 +504,7 @@ func (x *JobID) String() string { func (*JobID) ProtoMessage() {} func (x *JobID) ProtoReflect() protoreflect.Message { - mi := &file_proto_tsgrain_proto_msgTypes[8] + mi := &file_proto_tsgrain_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -643,7 +517,7 @@ func (x *JobID) ProtoReflect() protoreflect.Message { // Deprecated: Use JobID.ProtoReflect.Descriptor instead. func (*JobID) Descriptor() ([]byte, []int) { - return file_proto_tsgrain_proto_rawDescGZIP(), []int{8} + return file_proto_tsgrain_proto_rawDescGZIP(), []int{6} } func (x *JobID) GetId() int32 { @@ -664,7 +538,7 @@ type JobList struct { func (x *JobList) Reset() { *x = JobList{} if protoimpl.UnsafeEnabled { - mi := &file_proto_tsgrain_proto_msgTypes[9] + mi := &file_proto_tsgrain_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -677,7 +551,7 @@ func (x *JobList) String() string { func (*JobList) ProtoMessage() {} func (x *JobList) ProtoReflect() protoreflect.Message { - mi := &file_proto_tsgrain_proto_msgTypes[9] + mi := &file_proto_tsgrain_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -690,7 +564,7 @@ func (x *JobList) ProtoReflect() protoreflect.Message { // Deprecated: Use JobList.ProtoReflect.Descriptor instead. func (*JobList) Descriptor() ([]byte, []int) { - return file_proto_tsgrain_proto_rawDescGZIP(), []int{9} + return file_proto_tsgrain_proto_rawDescGZIP(), []int{7} } func (x *JobList) GetJobs() []*Job { @@ -700,7 +574,7 @@ func (x *JobList) GetJobs() []*Job { return nil } -type SystemTime struct { +type ConfigTime struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -709,23 +583,23 @@ type SystemTime struct { Timezone string `protobuf:"bytes,2,opt,name=timezone,proto3" json:"timezone,omitempty"` } -func (x *SystemTime) Reset() { - *x = SystemTime{} +func (x *ConfigTime) Reset() { + *x = ConfigTime{} if protoimpl.UnsafeEnabled { - mi := &file_proto_tsgrain_proto_msgTypes[10] + mi := &file_proto_tsgrain_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *SystemTime) String() string { +func (x *ConfigTime) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SystemTime) ProtoMessage() {} +func (*ConfigTime) ProtoMessage() {} -func (x *SystemTime) ProtoReflect() protoreflect.Message { - mi := &file_proto_tsgrain_proto_msgTypes[10] +func (x *ConfigTime) ProtoReflect() protoreflect.Message { + mi := &file_proto_tsgrain_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -736,19 +610,19 @@ func (x *SystemTime) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SystemTime.ProtoReflect.Descriptor instead. -func (*SystemTime) Descriptor() ([]byte, []int) { - return file_proto_tsgrain_proto_rawDescGZIP(), []int{10} +// Deprecated: Use ConfigTime.ProtoReflect.Descriptor instead. +func (*ConfigTime) Descriptor() ([]byte, []int) { + return file_proto_tsgrain_proto_rawDescGZIP(), []int{8} } -func (x *SystemTime) GetDatetime() *Timestamp { +func (x *ConfigTime) GetDatetime() *Timestamp { if x != nil { return x.Datetime } return nil } -func (x *SystemTime) GetTimezone() string { +func (x *ConfigTime) GetTimezone() string { if x != nil { return x.Timezone } @@ -780,134 +654,104 @@ var file_proto_tsgrain_proto_rawDesc = []byte{ 0x6c, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, - 0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x22, 0x7f, 0x0a, 0x09, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x74, - 0x61, 0x72, 0x74, 0x12, 0x23, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x0b, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x7a, 0x6f, 0x6e, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x7a, 0x6f, 0x6e, 0x65, 0x49, - 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, - 0x07, 0x71, 0x75, 0x65, 0x75, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, - 0x71, 0x75, 0x65, 0x75, 0x69, 0x6e, 0x67, 0x22, 0x48, 0x0a, 0x08, 0x54, 0x61, 0x73, 0x6b, 0x53, - 0x74, 0x6f, 0x70, 0x12, 0x23, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x0b, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x7a, 0x6f, 0x6e, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x7a, 0x6f, 0x6e, 0x65, 0x49, - 0x64, 0x22, 0xd0, 0x01, 0x0a, 0x04, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x23, 0x0a, 0x06, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0b, 0x2e, 0x54, 0x61, 0x73, - 0x6b, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, - 0x17, 0x0a, 0x07, 0x7a, 0x6f, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x06, 0x7a, 0x6f, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x0a, 0x10, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, - 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0f, 0x64, 0x61, 0x74, 0x65, - 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x37, 0x0a, 0x11, 0x64, - 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x10, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x46, 0x69, 0x6e, 0x69, - 0x73, 0x68, 0x65, 0x64, 0x22, 0x62, 0x0a, 0x08, 0x54, 0x61, 0x73, 0x6b, 0x4c, 0x69, 0x73, 0x74, - 0x12, 0x1b, 0x0a, 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x05, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x12, 0x1c, 0x0a, - 0x03, 0x6e, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x03, 0x6e, 0x6f, 0x77, 0x12, 0x1b, 0x0a, 0x09, 0x61, - 0x75, 0x74, 0x6f, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, - 0x61, 0x75, 0x74, 0x6f, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0x97, 0x01, 0x0a, 0x03, 0x4a, 0x6f, 0x62, + 0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x22, 0xd0, 0x01, 0x0a, 0x04, 0x54, 0x61, 0x73, 0x6b, 0x12, + 0x23, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x0b, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x7a, 0x6f, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x7a, 0x6f, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, + 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x0a, 0x10, 0x64, 0x61, 0x74, + 0x65, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x0f, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, + 0x12, 0x37, 0x0a, 0x11, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x66, 0x69, 0x6e, + 0x69, 0x73, 0x68, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, + 0x65, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x22, 0x62, 0x0a, 0x08, 0x54, 0x61, 0x73, + 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x05, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x05, 0x74, 0x61, 0x73, + 0x6b, 0x73, 0x12, 0x1c, 0x0a, 0x03, 0x6e, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0a, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x03, 0x6e, 0x6f, 0x77, + 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x75, 0x74, 0x6f, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0x97, 0x01, + 0x0a, 0x03, 0x4a, 0x6f, 0x62, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1e, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x04, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x7a, 0x6f, 0x6e, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x05, + 0x52, 0x05, 0x7a, 0x6f, 0x6e, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x06, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x22, 0x17, 0x0a, 0x05, 0x4a, 0x6f, 0x62, 0x49, 0x44, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, - 0x12, 0x1e, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x64, 0x61, 0x74, 0x65, - 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, - 0x7a, 0x6f, 0x6e, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x05, 0x52, 0x05, 0x7a, 0x6f, 0x6e, - 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, - 0x70, 0x65, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x70, 0x65, - 0x61, 0x74, 0x22, 0x17, 0x0a, 0x05, 0x4a, 0x6f, 0x62, 0x49, 0x44, 0x12, 0x0e, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x22, 0x23, 0x0a, 0x07, 0x4a, - 0x6f, 0x62, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x04, 0x6a, 0x6f, 0x62, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x04, 0x2e, 0x4a, 0x6f, 0x62, 0x52, 0x04, 0x6a, 0x6f, 0x62, 0x73, - 0x22, 0x50, 0x0a, 0x0a, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x26, - 0x0a, 0x08, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0a, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x64, 0x61, - 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x7a, 0x6f, - 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x7a, 0x6f, - 0x6e, 0x65, 0x2a, 0x26, 0x0a, 0x0a, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x41, 0x4e, 0x55, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, - 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x10, 0x01, 0x32, 0xe0, 0x08, 0x0a, 0x07, 0x54, - 0x53, 0x47, 0x52, 0x61, 0x69, 0x6e, 0x12, 0x31, 0x0a, 0x0b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x0c, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, 0x35, 0x0a, 0x09, 0x53, 0x74, 0x61, - 0x72, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x0a, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x74, 0x61, - 0x72, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x00, - 0x12, 0x33, 0x0a, 0x08, 0x53, 0x74, 0x6f, 0x70, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x09, 0x2e, 0x54, - 0x61, 0x73, 0x6b, 0x53, 0x74, 0x6f, 0x70, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x22, 0x00, 0x12, 0x2f, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, - 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x09, 0x2e, 0x54, 0x61, 0x73, 0x6b, - 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x12, 0x34, 0x0a, 0x0b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x54, 0x61, 0x73, 0x6b, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x09, 0x2e, - 0x54, 0x61, 0x73, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x30, 0x01, 0x12, 0x1b, 0x0a, 0x09, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x04, 0x2e, 0x4a, 0x6f, 0x62, 0x1a, - 0x06, 0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x44, 0x22, 0x00, 0x12, 0x18, 0x0a, 0x06, 0x47, 0x65, 0x74, - 0x4a, 0x6f, 0x62, 0x12, 0x06, 0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x44, 0x1a, 0x04, 0x2e, 0x4a, 0x6f, - 0x62, 0x22, 0x00, 0x12, 0x2d, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x12, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x08, 0x2e, 0x4a, 0x6f, 0x62, 0x4c, 0x69, 0x73, 0x74, - 0x22, 0x00, 0x12, 0x2b, 0x0a, 0x09, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, - 0x04, 0x2e, 0x4a, 0x6f, 0x62, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, - 0x2d, 0x0a, 0x09, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x06, 0x2e, 0x4a, - 0x6f, 0x62, 0x49, 0x44, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x2d, - 0x0a, 0x09, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x06, 0x2e, 0x4a, 0x6f, - 0x62, 0x49, 0x44, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x2e, 0x0a, - 0x0a, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x06, 0x2e, 0x4a, 0x6f, - 0x62, 0x49, 0x44, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x43, 0x0a, - 0x0b, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x6f, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x41, 0x75, 0x74, 0x6f, 0x4d, 0x6f, 0x64, - 0x65, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x53, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x22, 0x23, 0x0a, 0x07, 0x4a, 0x6f, 0x62, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x04, 0x6a, + 0x6f, 0x62, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x04, 0x2e, 0x4a, 0x6f, 0x62, 0x52, + 0x04, 0x6a, 0x6f, 0x62, 0x73, 0x22, 0x50, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x54, + 0x69, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x08, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x52, 0x08, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x74, + 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, + 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x2a, 0x26, 0x0a, 0x0a, 0x54, 0x61, 0x73, 0x6b, 0x53, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x41, 0x4e, 0x55, 0x41, 0x4c, 0x10, + 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x10, 0x01, 0x32, + 0xc7, 0x06, 0x0a, 0x07, 0x54, 0x53, 0x47, 0x52, 0x61, 0x69, 0x6e, 0x12, 0x2f, 0x0a, 0x09, 0x53, + 0x74, 0x61, 0x72, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x0c, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, 0x2f, 0x0a, 0x08, + 0x47, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x1a, 0x0b, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x00, 0x12, - 0x35, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, - 0x12, 0x0a, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x1a, 0x16, 0x2e, 0x67, + 0x1a, 0x09, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x12, 0x34, 0x0a, + 0x0b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x53, 0x79, 0x73, - 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x49, 0x72, 0x72, 0x69, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x18, 0x53, 0x65, 0x74, 0x44, 0x65, 0x66, - 0x61, 0x75, 0x6c, 0x74, 0x49, 0x72, 0x72, 0x69, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, - 0x6d, 0x65, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x09, 0x47, 0x65, 0x74, - 0x4e, 0x5a, 0x6f, 0x6e, 0x65, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1b, + 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x09, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x22, + 0x00, 0x30, 0x01, 0x12, 0x1b, 0x0a, 0x09, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, + 0x12, 0x04, 0x2e, 0x4a, 0x6f, 0x62, 0x1a, 0x06, 0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x44, 0x22, 0x00, + 0x12, 0x18, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x4a, 0x6f, 0x62, 0x12, 0x06, 0x2e, 0x4a, 0x6f, 0x62, + 0x49, 0x44, 0x1a, 0x04, 0x2e, 0x4a, 0x6f, 0x62, 0x22, 0x00, 0x12, 0x2d, 0x0a, 0x07, 0x47, 0x65, + 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x08, 0x2e, + 0x4a, 0x6f, 0x62, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x12, 0x2b, 0x0a, 0x09, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x04, 0x2e, 0x4a, 0x6f, 0x62, 0x1a, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x2d, 0x0a, 0x09, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x4a, 0x6f, 0x62, 0x12, 0x06, 0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x44, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x6f, + 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, + 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0b, 0x53, 0x65, + 0x74, 0x41, 0x75, 0x74, 0x6f, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, + 0x36, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x54, 0x69, 0x6d, 0x65, + 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0b, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x0b, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x54, 0x69, 0x6d, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, + 0x51, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x49, 0x72, 0x72, + 0x69, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x22, 0x00, 0x12, 0x51, 0x0a, 0x18, 0x53, 0x65, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, + 0x49, 0x72, 0x72, 0x69, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x00, 0x42, 0x30, 0x5a, - 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x74, 0x68, 0x65, 0x74, 0x61, 0x64, 0x65, 0x76, 0x2e, 0x64, - 0x65, 0x2f, 0x54, 0x53, 0x47, 0x52, 0x61, 0x69, 0x6e, 0x2f, 0x57, 0x65, 0x62, 0x55, 0x49, 0x2f, - 0x73, 0x72, 0x63, 0x2f, 0x74, 0x73, 0x67, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x72, 0x70, 0x63, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x4e, 0x5a, 0x6f, 0x6e, + 0x65, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74, + 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x00, 0x42, 0x30, 0x5a, 0x2e, 0x63, 0x6f, 0x64, + 0x65, 0x2e, 0x74, 0x68, 0x65, 0x74, 0x61, 0x64, 0x65, 0x76, 0x2e, 0x64, 0x65, 0x2f, 0x54, 0x53, + 0x47, 0x52, 0x61, 0x69, 0x6e, 0x2f, 0x57, 0x65, 0x62, 0x55, 0x49, 0x2f, 0x73, 0x72, 0x63, 0x2f, + 0x74, 0x73, 0x67, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -923,82 +767,67 @@ func file_proto_tsgrain_proto_rawDescGZIP() []byte { } var file_proto_tsgrain_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_proto_tsgrain_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_proto_tsgrain_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_proto_tsgrain_proto_goTypes = []interface{}{ - (TaskSource)(0), // 0: TaskSource - (*Timestamp)(nil), // 1: Timestamp - (*TaskRequest)(nil), // 2: TaskRequest - (*TaskRequestResult)(nil), // 3: TaskRequestResult - (*TaskStart)(nil), // 4: TaskStart - (*TaskStop)(nil), // 5: TaskStop - (*Task)(nil), // 6: Task - (*TaskList)(nil), // 7: TaskList - (*Job)(nil), // 8: Job - (*JobID)(nil), // 9: JobID - (*JobList)(nil), // 10: JobList - (*SystemTime)(nil), // 11: SystemTime - (*emptypb.Empty)(nil), // 12: google.protobuf.Empty - (*wrapperspb.BoolValue)(nil), // 13: google.protobuf.BoolValue - (*wrapperspb.StringValue)(nil), // 14: google.protobuf.StringValue - (*wrapperspb.Int32Value)(nil), // 15: google.protobuf.Int32Value + (TaskSource)(0), // 0: TaskSource + (*Timestamp)(nil), // 1: Timestamp + (*TaskRequest)(nil), // 2: TaskRequest + (*TaskRequestResult)(nil), // 3: TaskRequestResult + (*Task)(nil), // 4: Task + (*TaskList)(nil), // 5: TaskList + (*Job)(nil), // 6: Job + (*JobID)(nil), // 7: JobID + (*JobList)(nil), // 8: JobList + (*ConfigTime)(nil), // 9: ConfigTime + (*emptypb.Empty)(nil), // 10: google.protobuf.Empty + (*wrapperspb.BoolValue)(nil), // 11: google.protobuf.BoolValue + (*wrapperspb.Int32Value)(nil), // 12: google.protobuf.Int32Value } var file_proto_tsgrain_proto_depIdxs = []int32{ 0, // 0: TaskRequest.source:type_name -> TaskSource - 0, // 1: TaskStart.source:type_name -> TaskSource - 0, // 2: TaskStop.source:type_name -> TaskSource - 0, // 3: Task.source:type_name -> TaskSource - 1, // 4: Task.datetime_started:type_name -> Timestamp - 1, // 5: Task.datetime_finished:type_name -> Timestamp - 6, // 6: TaskList.tasks:type_name -> Task - 1, // 7: TaskList.now:type_name -> Timestamp - 1, // 8: Job.date:type_name -> Timestamp - 8, // 9: JobList.jobs:type_name -> Job - 1, // 10: SystemTime.datetime:type_name -> Timestamp - 2, // 11: TSGRain.RequestTask:input_type -> TaskRequest - 4, // 12: TSGRain.StartTask:input_type -> TaskStart - 5, // 13: TSGRain.StopTask:input_type -> TaskStop - 12, // 14: TSGRain.GetTasks:input_type -> google.protobuf.Empty - 12, // 15: TSGRain.StreamTasks:input_type -> google.protobuf.Empty - 8, // 16: TSGRain.CreateJob:input_type -> Job - 9, // 17: TSGRain.GetJob:input_type -> JobID - 12, // 18: TSGRain.GetJobs:input_type -> google.protobuf.Empty - 8, // 19: TSGRain.UpdateJob:input_type -> Job - 9, // 20: TSGRain.DeleteJob:input_type -> JobID - 9, // 21: TSGRain.EnableJob:input_type -> JobID - 9, // 22: TSGRain.DisableJob:input_type -> JobID - 12, // 23: TSGRain.GetAutoMode:input_type -> google.protobuf.Empty - 13, // 24: TSGRain.SetAutoMode:input_type -> google.protobuf.BoolValue - 12, // 25: TSGRain.GetSystemTime:input_type -> google.protobuf.Empty - 1, // 26: TSGRain.SetSystemTime:input_type -> Timestamp - 14, // 27: TSGRain.SetSystemTimezone:input_type -> google.protobuf.StringValue - 12, // 28: TSGRain.GetDefaultIrrigationTime:input_type -> google.protobuf.Empty - 15, // 29: TSGRain.SetDefaultIrrigationTime:input_type -> google.protobuf.Int32Value - 12, // 30: TSGRain.GetNZones:input_type -> google.protobuf.Empty - 3, // 31: TSGRain.RequestTask:output_type -> TaskRequestResult - 13, // 32: TSGRain.StartTask:output_type -> google.protobuf.BoolValue - 13, // 33: TSGRain.StopTask:output_type -> google.protobuf.BoolValue - 7, // 34: TSGRain.GetTasks:output_type -> TaskList - 7, // 35: TSGRain.StreamTasks:output_type -> TaskList - 9, // 36: TSGRain.CreateJob:output_type -> JobID - 8, // 37: TSGRain.GetJob:output_type -> Job - 10, // 38: TSGRain.GetJobs:output_type -> JobList - 12, // 39: TSGRain.UpdateJob:output_type -> google.protobuf.Empty - 12, // 40: TSGRain.DeleteJob:output_type -> google.protobuf.Empty - 12, // 41: TSGRain.EnableJob:output_type -> google.protobuf.Empty - 12, // 42: TSGRain.DisableJob:output_type -> google.protobuf.Empty - 13, // 43: TSGRain.GetAutoMode:output_type -> google.protobuf.BoolValue - 12, // 44: TSGRain.SetAutoMode:output_type -> google.protobuf.Empty - 11, // 45: TSGRain.GetSystemTime:output_type -> SystemTime - 12, // 46: TSGRain.SetSystemTime:output_type -> google.protobuf.Empty - 12, // 47: TSGRain.SetSystemTimezone:output_type -> google.protobuf.Empty - 15, // 48: TSGRain.GetDefaultIrrigationTime:output_type -> google.protobuf.Int32Value - 12, // 49: TSGRain.SetDefaultIrrigationTime:output_type -> google.protobuf.Empty - 15, // 50: TSGRain.GetNZones:output_type -> google.protobuf.Int32Value - 31, // [31:51] is the sub-list for method output_type - 11, // [11:31] is the sub-list for method input_type - 11, // [11:11] is the sub-list for extension type_name - 11, // [11:11] is the sub-list for extension extendee - 0, // [0:11] is the sub-list for field type_name + 0, // 1: Task.source:type_name -> TaskSource + 1, // 2: Task.datetime_started:type_name -> Timestamp + 1, // 3: Task.datetime_finished:type_name -> Timestamp + 4, // 4: TaskList.tasks:type_name -> Task + 1, // 5: TaskList.now:type_name -> Timestamp + 1, // 6: Job.date:type_name -> Timestamp + 6, // 7: JobList.jobs:type_name -> Job + 1, // 8: ConfigTime.datetime:type_name -> Timestamp + 2, // 9: TSGRain.StartTask:input_type -> TaskRequest + 10, // 10: TSGRain.GetTasks:input_type -> google.protobuf.Empty + 10, // 11: TSGRain.StreamTasks:input_type -> google.protobuf.Empty + 6, // 12: TSGRain.CreateJob:input_type -> Job + 7, // 13: TSGRain.GetJob:input_type -> JobID + 10, // 14: TSGRain.GetJobs:input_type -> google.protobuf.Empty + 6, // 15: TSGRain.UpdateJob:input_type -> Job + 7, // 16: TSGRain.DeleteJob:input_type -> JobID + 10, // 17: TSGRain.GetAutoMode:input_type -> google.protobuf.Empty + 11, // 18: TSGRain.SetAutoMode:input_type -> google.protobuf.BoolValue + 10, // 19: TSGRain.GetConfigTime:input_type -> google.protobuf.Empty + 9, // 20: TSGRain.SetConfigTime:input_type -> ConfigTime + 10, // 21: TSGRain.GetDefaultIrrigationTime:input_type -> google.protobuf.Empty + 12, // 22: TSGRain.SetDefaultIrrigationTime:input_type -> google.protobuf.Int32Value + 10, // 23: TSGRain.GetNZones:input_type -> google.protobuf.Empty + 3, // 24: TSGRain.StartTask:output_type -> TaskRequestResult + 5, // 25: TSGRain.GetTasks:output_type -> TaskList + 5, // 26: TSGRain.StreamTasks:output_type -> TaskList + 7, // 27: TSGRain.CreateJob:output_type -> JobID + 6, // 28: TSGRain.GetJob:output_type -> Job + 8, // 29: TSGRain.GetJobs:output_type -> JobList + 10, // 30: TSGRain.UpdateJob:output_type -> google.protobuf.Empty + 10, // 31: TSGRain.DeleteJob:output_type -> google.protobuf.Empty + 11, // 32: TSGRain.GetAutoMode:output_type -> google.protobuf.BoolValue + 10, // 33: TSGRain.SetAutoMode:output_type -> google.protobuf.Empty + 9, // 34: TSGRain.GetConfigTime:output_type -> ConfigTime + 10, // 35: TSGRain.SetConfigTime:output_type -> google.protobuf.Empty + 12, // 36: TSGRain.GetDefaultIrrigationTime:output_type -> google.protobuf.Int32Value + 10, // 37: TSGRain.SetDefaultIrrigationTime:output_type -> google.protobuf.Empty + 12, // 38: TSGRain.GetNZones:output_type -> google.protobuf.Int32Value + 24, // [24:39] is the sub-list for method output_type + 9, // [9:24] is the sub-list for method input_type + 9, // [9:9] is the sub-list for extension type_name + 9, // [9:9] is the sub-list for extension extendee + 0, // [0:9] is the sub-list for field type_name } func init() { file_proto_tsgrain_proto_init() } @@ -1044,30 +873,6 @@ func file_proto_tsgrain_proto_init() { } } file_proto_tsgrain_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TaskStart); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_tsgrain_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TaskStop); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_tsgrain_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Task); i { case 0: return &v.state @@ -1079,7 +884,7 @@ func file_proto_tsgrain_proto_init() { return nil } } - file_proto_tsgrain_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_proto_tsgrain_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*TaskList); i { case 0: return &v.state @@ -1091,7 +896,7 @@ func file_proto_tsgrain_proto_init() { return nil } } - file_proto_tsgrain_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + file_proto_tsgrain_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Job); i { case 0: return &v.state @@ -1103,7 +908,7 @@ func file_proto_tsgrain_proto_init() { return nil } } - file_proto_tsgrain_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + file_proto_tsgrain_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JobID); i { case 0: return &v.state @@ -1115,7 +920,7 @@ func file_proto_tsgrain_proto_init() { return nil } } - file_proto_tsgrain_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + file_proto_tsgrain_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*JobList); i { case 0: return &v.state @@ -1127,8 +932,8 @@ func file_proto_tsgrain_proto_init() { return nil } } - file_proto_tsgrain_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SystemTime); i { + file_proto_tsgrain_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ConfigTime); i { case 0: return &v.state case 1: @@ -1146,7 +951,7 @@ func file_proto_tsgrain_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_tsgrain_proto_rawDesc, NumEnums: 1, - NumMessages: 11, + NumMessages: 9, NumExtensions: 0, NumServices: 1, }, diff --git a/src/tsgrain_rpc/proto/tsgrain_grpc.pb.go b/src/tsgrain_rpc/proto/tsgrain_grpc.pb.go index a429ef6..294d3bc 100644 --- a/src/tsgrain_rpc/proto/tsgrain_grpc.pb.go +++ b/src/tsgrain_rpc/proto/tsgrain_grpc.pb.go @@ -26,11 +26,7 @@ const _ = grpc.SupportPackageIsVersion7 type TSGRainClient interface { // Starte eine neue Bewässerungsaufgabe (oder stoppe eine laufende, wenn // diese bereits läuft). - RequestTask(ctx context.Context, in *TaskRequest, opts ...grpc.CallOption) (*TaskRequestResult, error) - // Starte eine Bewässerungsaufgabe - StartTask(ctx context.Context, in *TaskStart, opts ...grpc.CallOption) (*wrapperspb.BoolValue, error) - // Stoppe eine Bewässerungsaufgabe - StopTask(ctx context.Context, in *TaskStop, opts ...grpc.CallOption) (*wrapperspb.BoolValue, error) + StartTask(ctx context.Context, in *TaskRequest, opts ...grpc.CallOption) (*TaskRequestResult, error) // Gibt sämtliche in der Warteschlange befindlichen Bewässerungsaufgaben zurück. GetTasks(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*TaskList, error) // Streamt die aktuelle Warteschlange mit ihren Bewässerungsaufgaben, @@ -46,20 +42,14 @@ type TSGRainClient interface { UpdateJob(ctx context.Context, in *Job, opts ...grpc.CallOption) (*emptypb.Empty, error) // Lösche den Bewässerungsjob mit der gegebenen ID. DeleteJob(ctx context.Context, in *JobID, opts ...grpc.CallOption) (*emptypb.Empty, error) - // Aktiviere Bewässerungsjob - EnableJob(ctx context.Context, in *JobID, opts ...grpc.CallOption) (*emptypb.Empty, error) - // Deaktiviere Bewässerungsjob - DisableJob(ctx context.Context, in *JobID, opts ...grpc.CallOption) (*emptypb.Empty, error) // Gibt zurück, ob der Automatikmodus aktiviert ist. GetAutoMode(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*wrapperspb.BoolValue, error) // Aktiviert/deaktiviert den Automatikmodus. SetAutoMode(ctx context.Context, in *wrapperspb.BoolValue, opts ...grpc.CallOption) (*emptypb.Empty, error) // Datum/Uhrzeit/Zeitzone abrufen - GetSystemTime(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*SystemTime, error) - // Datum/Uhrzeit einstellen - SetSystemTime(ctx context.Context, in *Timestamp, opts ...grpc.CallOption) (*emptypb.Empty, error) - // Zeitzone einstellen - SetSystemTimezone(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (*emptypb.Empty, error) + GetConfigTime(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ConfigTime, error) + // Datum/Uhrzeit/Zeitzone einstellen + SetConfigTime(ctx context.Context, in *ConfigTime, opts ...grpc.CallOption) (*emptypb.Empty, error) // Standardzeit bei manueller Bewässerung abrufen GetDefaultIrrigationTime(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*wrapperspb.Int32Value, error) // Standardzeit bei manueller Bewässerung einstellen @@ -76,17 +66,8 @@ func NewTSGRainClient(cc grpc.ClientConnInterface) TSGRainClient { return &tSGRainClient{cc} } -func (c *tSGRainClient) RequestTask(ctx context.Context, in *TaskRequest, opts ...grpc.CallOption) (*TaskRequestResult, error) { +func (c *tSGRainClient) StartTask(ctx context.Context, in *TaskRequest, opts ...grpc.CallOption) (*TaskRequestResult, error) { out := new(TaskRequestResult) - err := c.cc.Invoke(ctx, "/TSGRain/RequestTask", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *tSGRainClient) StartTask(ctx context.Context, in *TaskStart, opts ...grpc.CallOption) (*wrapperspb.BoolValue, error) { - out := new(wrapperspb.BoolValue) err := c.cc.Invoke(ctx, "/TSGRain/StartTask", in, out, opts...) if err != nil { return nil, err @@ -94,15 +75,6 @@ func (c *tSGRainClient) StartTask(ctx context.Context, in *TaskStart, opts ...gr return out, nil } -func (c *tSGRainClient) StopTask(ctx context.Context, in *TaskStop, opts ...grpc.CallOption) (*wrapperspb.BoolValue, error) { - out := new(wrapperspb.BoolValue) - err := c.cc.Invoke(ctx, "/TSGRain/StopTask", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *tSGRainClient) GetTasks(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*TaskList, error) { out := new(TaskList) err := c.cc.Invoke(ctx, "/TSGRain/GetTasks", in, out, opts...) @@ -189,24 +161,6 @@ func (c *tSGRainClient) DeleteJob(ctx context.Context, in *JobID, opts ...grpc.C return out, nil } -func (c *tSGRainClient) EnableJob(ctx context.Context, in *JobID, opts ...grpc.CallOption) (*emptypb.Empty, error) { - out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/TSGRain/EnableJob", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *tSGRainClient) DisableJob(ctx context.Context, in *JobID, opts ...grpc.CallOption) (*emptypb.Empty, error) { - out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/TSGRain/DisableJob", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *tSGRainClient) GetAutoMode(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*wrapperspb.BoolValue, error) { out := new(wrapperspb.BoolValue) err := c.cc.Invoke(ctx, "/TSGRain/GetAutoMode", in, out, opts...) @@ -225,27 +179,18 @@ func (c *tSGRainClient) SetAutoMode(ctx context.Context, in *wrapperspb.BoolValu return out, nil } -func (c *tSGRainClient) GetSystemTime(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*SystemTime, error) { - out := new(SystemTime) - err := c.cc.Invoke(ctx, "/TSGRain/GetSystemTime", in, out, opts...) +func (c *tSGRainClient) GetConfigTime(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ConfigTime, error) { + out := new(ConfigTime) + err := c.cc.Invoke(ctx, "/TSGRain/GetConfigTime", in, out, opts...) if err != nil { return nil, err } return out, nil } -func (c *tSGRainClient) SetSystemTime(ctx context.Context, in *Timestamp, opts ...grpc.CallOption) (*emptypb.Empty, error) { +func (c *tSGRainClient) SetConfigTime(ctx context.Context, in *ConfigTime, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/TSGRain/SetSystemTime", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *tSGRainClient) SetSystemTimezone(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (*emptypb.Empty, error) { - out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/TSGRain/SetSystemTimezone", in, out, opts...) + err := c.cc.Invoke(ctx, "/TSGRain/SetConfigTime", in, out, opts...) if err != nil { return nil, err } @@ -285,11 +230,7 @@ func (c *tSGRainClient) GetNZones(ctx context.Context, in *emptypb.Empty, opts . type TSGRainServer interface { // Starte eine neue Bewässerungsaufgabe (oder stoppe eine laufende, wenn // diese bereits läuft). - RequestTask(context.Context, *TaskRequest) (*TaskRequestResult, error) - // Starte eine Bewässerungsaufgabe - StartTask(context.Context, *TaskStart) (*wrapperspb.BoolValue, error) - // Stoppe eine Bewässerungsaufgabe - StopTask(context.Context, *TaskStop) (*wrapperspb.BoolValue, error) + StartTask(context.Context, *TaskRequest) (*TaskRequestResult, error) // Gibt sämtliche in der Warteschlange befindlichen Bewässerungsaufgaben zurück. GetTasks(context.Context, *emptypb.Empty) (*TaskList, error) // Streamt die aktuelle Warteschlange mit ihren Bewässerungsaufgaben, @@ -305,20 +246,14 @@ type TSGRainServer interface { UpdateJob(context.Context, *Job) (*emptypb.Empty, error) // Lösche den Bewässerungsjob mit der gegebenen ID. DeleteJob(context.Context, *JobID) (*emptypb.Empty, error) - // Aktiviere Bewässerungsjob - EnableJob(context.Context, *JobID) (*emptypb.Empty, error) - // Deaktiviere Bewässerungsjob - DisableJob(context.Context, *JobID) (*emptypb.Empty, error) // Gibt zurück, ob der Automatikmodus aktiviert ist. GetAutoMode(context.Context, *emptypb.Empty) (*wrapperspb.BoolValue, error) // Aktiviert/deaktiviert den Automatikmodus. SetAutoMode(context.Context, *wrapperspb.BoolValue) (*emptypb.Empty, error) // Datum/Uhrzeit/Zeitzone abrufen - GetSystemTime(context.Context, *emptypb.Empty) (*SystemTime, error) - // Datum/Uhrzeit einstellen - SetSystemTime(context.Context, *Timestamp) (*emptypb.Empty, error) - // Zeitzone einstellen - SetSystemTimezone(context.Context, *wrapperspb.StringValue) (*emptypb.Empty, error) + GetConfigTime(context.Context, *emptypb.Empty) (*ConfigTime, error) + // Datum/Uhrzeit/Zeitzone einstellen + SetConfigTime(context.Context, *ConfigTime) (*emptypb.Empty, error) // Standardzeit bei manueller Bewässerung abrufen GetDefaultIrrigationTime(context.Context, *emptypb.Empty) (*wrapperspb.Int32Value, error) // Standardzeit bei manueller Bewässerung einstellen @@ -332,15 +267,9 @@ type TSGRainServer interface { type UnimplementedTSGRainServer struct { } -func (UnimplementedTSGRainServer) RequestTask(context.Context, *TaskRequest) (*TaskRequestResult, error) { - return nil, status.Errorf(codes.Unimplemented, "method RequestTask not implemented") -} -func (UnimplementedTSGRainServer) StartTask(context.Context, *TaskStart) (*wrapperspb.BoolValue, error) { +func (UnimplementedTSGRainServer) StartTask(context.Context, *TaskRequest) (*TaskRequestResult, error) { return nil, status.Errorf(codes.Unimplemented, "method StartTask not implemented") } -func (UnimplementedTSGRainServer) StopTask(context.Context, *TaskStop) (*wrapperspb.BoolValue, error) { - return nil, status.Errorf(codes.Unimplemented, "method StopTask not implemented") -} func (UnimplementedTSGRainServer) GetTasks(context.Context, *emptypb.Empty) (*TaskList, error) { return nil, status.Errorf(codes.Unimplemented, "method GetTasks not implemented") } @@ -362,26 +291,17 @@ func (UnimplementedTSGRainServer) UpdateJob(context.Context, *Job) (*emptypb.Emp func (UnimplementedTSGRainServer) DeleteJob(context.Context, *JobID) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method DeleteJob not implemented") } -func (UnimplementedTSGRainServer) EnableJob(context.Context, *JobID) (*emptypb.Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method EnableJob not implemented") -} -func (UnimplementedTSGRainServer) DisableJob(context.Context, *JobID) (*emptypb.Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method DisableJob not implemented") -} func (UnimplementedTSGRainServer) GetAutoMode(context.Context, *emptypb.Empty) (*wrapperspb.BoolValue, error) { return nil, status.Errorf(codes.Unimplemented, "method GetAutoMode not implemented") } func (UnimplementedTSGRainServer) SetAutoMode(context.Context, *wrapperspb.BoolValue) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method SetAutoMode not implemented") } -func (UnimplementedTSGRainServer) GetSystemTime(context.Context, *emptypb.Empty) (*SystemTime, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetSystemTime not implemented") +func (UnimplementedTSGRainServer) GetConfigTime(context.Context, *emptypb.Empty) (*ConfigTime, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetConfigTime not implemented") } -func (UnimplementedTSGRainServer) SetSystemTime(context.Context, *Timestamp) (*emptypb.Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method SetSystemTime not implemented") -} -func (UnimplementedTSGRainServer) SetSystemTimezone(context.Context, *wrapperspb.StringValue) (*emptypb.Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method SetSystemTimezone not implemented") +func (UnimplementedTSGRainServer) SetConfigTime(context.Context, *ConfigTime) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetConfigTime not implemented") } func (UnimplementedTSGRainServer) GetDefaultIrrigationTime(context.Context, *emptypb.Empty) (*wrapperspb.Int32Value, error) { return nil, status.Errorf(codes.Unimplemented, "method GetDefaultIrrigationTime not implemented") @@ -405,26 +325,8 @@ func RegisterTSGRainServer(s grpc.ServiceRegistrar, srv TSGRainServer) { s.RegisterService(&TSGRain_ServiceDesc, srv) } -func _TSGRain_RequestTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(TaskRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(TSGRainServer).RequestTask(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/TSGRain/RequestTask", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TSGRainServer).RequestTask(ctx, req.(*TaskRequest)) - } - return interceptor(ctx, in, info, handler) -} - func _TSGRain_StartTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(TaskStart) + in := new(TaskRequest) if err := dec(in); err != nil { return nil, err } @@ -436,25 +338,7 @@ func _TSGRain_StartTask_Handler(srv interface{}, ctx context.Context, dec func(i FullMethod: "/TSGRain/StartTask", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TSGRainServer).StartTask(ctx, req.(*TaskStart)) - } - return interceptor(ctx, in, info, handler) -} - -func _TSGRain_StopTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(TaskStop) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(TSGRainServer).StopTask(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/TSGRain/StopTask", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TSGRainServer).StopTask(ctx, req.(*TaskStop)) + return srv.(TSGRainServer).StartTask(ctx, req.(*TaskRequest)) } return interceptor(ctx, in, info, handler) } @@ -588,42 +472,6 @@ func _TSGRain_DeleteJob_Handler(srv interface{}, ctx context.Context, dec func(i return interceptor(ctx, in, info, handler) } -func _TSGRain_EnableJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(JobID) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(TSGRainServer).EnableJob(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/TSGRain/EnableJob", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TSGRainServer).EnableJob(ctx, req.(*JobID)) - } - return interceptor(ctx, in, info, handler) -} - -func _TSGRain_DisableJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(JobID) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(TSGRainServer).DisableJob(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/TSGRain/DisableJob", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TSGRainServer).DisableJob(ctx, req.(*JobID)) - } - return interceptor(ctx, in, info, handler) -} - func _TSGRain_GetAutoMode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(emptypb.Empty) if err := dec(in); err != nil { @@ -660,56 +508,38 @@ func _TSGRain_SetAutoMode_Handler(srv interface{}, ctx context.Context, dec func return interceptor(ctx, in, info, handler) } -func _TSGRain_GetSystemTime_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { +func _TSGRain_GetConfigTime_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(emptypb.Empty) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(TSGRainServer).GetSystemTime(ctx, in) + return srv.(TSGRainServer).GetConfigTime(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/TSGRain/GetSystemTime", + FullMethod: "/TSGRain/GetConfigTime", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TSGRainServer).GetSystemTime(ctx, req.(*emptypb.Empty)) + return srv.(TSGRainServer).GetConfigTime(ctx, req.(*emptypb.Empty)) } return interceptor(ctx, in, info, handler) } -func _TSGRain_SetSystemTime_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Timestamp) +func _TSGRain_SetConfigTime_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ConfigTime) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(TSGRainServer).SetSystemTime(ctx, in) + return srv.(TSGRainServer).SetConfigTime(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/TSGRain/SetSystemTime", + FullMethod: "/TSGRain/SetConfigTime", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TSGRainServer).SetSystemTime(ctx, req.(*Timestamp)) - } - return interceptor(ctx, in, info, handler) -} - -func _TSGRain_SetSystemTimezone_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(wrapperspb.StringValue) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(TSGRainServer).SetSystemTimezone(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/TSGRain/SetSystemTimezone", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(TSGRainServer).SetSystemTimezone(ctx, req.(*wrapperspb.StringValue)) + return srv.(TSGRainServer).SetConfigTime(ctx, req.(*ConfigTime)) } return interceptor(ctx, in, info, handler) } @@ -775,18 +605,10 @@ var TSGRain_ServiceDesc = grpc.ServiceDesc{ ServiceName: "TSGRain", HandlerType: (*TSGRainServer)(nil), Methods: []grpc.MethodDesc{ - { - MethodName: "RequestTask", - Handler: _TSGRain_RequestTask_Handler, - }, { MethodName: "StartTask", Handler: _TSGRain_StartTask_Handler, }, - { - MethodName: "StopTask", - Handler: _TSGRain_StopTask_Handler, - }, { MethodName: "GetTasks", Handler: _TSGRain_GetTasks_Handler, @@ -811,14 +633,6 @@ var TSGRain_ServiceDesc = grpc.ServiceDesc{ MethodName: "DeleteJob", Handler: _TSGRain_DeleteJob_Handler, }, - { - MethodName: "EnableJob", - Handler: _TSGRain_EnableJob_Handler, - }, - { - MethodName: "DisableJob", - Handler: _TSGRain_DisableJob_Handler, - }, { MethodName: "GetAutoMode", Handler: _TSGRain_GetAutoMode_Handler, @@ -828,16 +642,12 @@ var TSGRain_ServiceDesc = grpc.ServiceDesc{ Handler: _TSGRain_SetAutoMode_Handler, }, { - MethodName: "GetSystemTime", - Handler: _TSGRain_GetSystemTime_Handler, + MethodName: "GetConfigTime", + Handler: _TSGRain_GetConfigTime_Handler, }, { - MethodName: "SetSystemTime", - Handler: _TSGRain_SetSystemTime_Handler, - }, - { - MethodName: "SetSystemTimezone", - Handler: _TSGRain_SetSystemTimezone_Handler, + MethodName: "SetConfigTime", + Handler: _TSGRain_SetConfigTime_Handler, }, { MethodName: "GetDefaultIrrigationTime", diff --git a/src/tsgrain_rpc/tsgrain_rpc.go b/src/tsgrain_rpc/tsgrain_rpc.go index 69a93d5..46202e3 100644 --- a/src/tsgrain_rpc/tsgrain_rpc.go +++ b/src/tsgrain_rpc/tsgrain_rpc.go @@ -83,30 +83,24 @@ func mapTaskList(pbTaskList *tsgrain_grpc.TaskList) model.TaskList { return taskList } -func (c *RPCClient) StartManualTask(zone_id int32, duration int32) (bool, error) { - res, err := c.tsgrain.StartTask(c.ctx, &tsgrain_grpc.TaskStart{ - Source: tsgrain_grpc.TaskSource_MANUAL, - ZoneId: zone_id, - Duration: duration, - Queuing: true, +func (c *RPCClient) StartManualTask( + zone_id int32, duration int32, queuing bool, cancelling bool) ( + model.TaskRequestResult, error) { + res, err := c.tsgrain.StartTask(c.ctx, &tsgrain_grpc.TaskRequest{ + Source: tsgrain_grpc.TaskSource_MANUAL, + ZoneId: zone_id, + Duration: duration, + Queuing: queuing, + Cancelling: cancelling, }) if err != nil { - return false, err + return model.TaskRequestResult{}, err } - return res.Value, nil -} - -func (c *RPCClient) StopManualTask(zone_id int32) (bool, error) { - res, err := c.tsgrain.StopTask(c.ctx, &tsgrain_grpc.TaskStop{ - Source: tsgrain_grpc.TaskSource_MANUAL, - ZoneId: zone_id, - }) - if err != nil { - return false, err - } - - return res.Value, nil + return model.TaskRequestResult{ + Started: res.Started, + Stopped: res.Stopped, + }, nil } func (c *RPCClient) GetTasks() (model.TaskList, error) { @@ -261,27 +255,30 @@ func (c *RPCClient) SetAutoMode(state bool) error { return err } -func (c *RPCClient) GetSystemTime() (model.SystemTime, error) { - configTime, err := c.tsgrain.GetSystemTime(c.ctx, &emptypb.Empty{}) +func (c *RPCClient) GetConfigTime() (model.ConfigTime, error) { + configTime, err := c.tsgrain.GetConfigTime(c.ctx, &emptypb.Empty{}) if err != nil { - return model.SystemTime{}, err + return model.ConfigTime{}, err } - return model.SystemTime{ + return model.ConfigTime{ Time: configTime.Datetime.Seconds, Timezone: configTime.Timezone, }, nil } -func (c *RPCClient) SetSystemTime(timestamp int64) error { - _, err := c.tsgrain.SetSystemTime(c.ctx, - &tsgrain_grpc.Timestamp{Seconds: timestamp}) +func (c *RPCClient) SetConfigTime(configTime model.ConfigTime) error { + _, err := c.tsgrain.SetConfigTime(c.ctx, &tsgrain_grpc.ConfigTime{ + Datetime: &tsgrain_grpc.Timestamp{Seconds: configTime.Time}, + Timezone: configTime.Timezone, + }) return err } func (c *RPCClient) SetSystemTimezone(timezone string) error { - _, err := c.tsgrain.SetSystemTimezone(c.ctx, - &wrapperspb.StringValue{Value: timezone}) + _, err := c.tsgrain.SetConfigTime(c.ctx, &tsgrain_grpc.ConfigTime{ + Timezone: timezone, + }) return err } diff --git a/ui/package.json b/ui/package.json index f7be729..c27f082 100644 --- a/ui/package.json +++ b/ui/package.json @@ -9,22 +9,16 @@ "format": "prettier --write ../" }, "dependencies": { - "@emotion/react": "^11.7.1", - "@emotion/styled": "^11.6.0", - "@mui/icons-material": "^5.3.1", - "@mui/lab": "^5.0.0-alpha.67", - "@mui/material": "^5.4.0", - "axios": "^0.25.0", - "date-fns": "^2.28.0", - "react": "^17.0.2", - "react-dom": "^17.0.2", - "wouter": "^2.8.0-alpha.2" + "@mdi/js": "^6.5.95", + "axios": "^0.24.0", + "preact": "^10.5.15" }, "devDependencies": { - "@babel/core": "^7.17.0", - "@types/react-dom": "^17.0.11", - "@vitejs/plugin-react-refresh": "latest", + "@preact/preset-vite": "^2.1.5", + "prettier": "^2.4.1", + "sass": "^1.43.4", "typescript": "^4.5.2", - "vite": "latest" + "vite": "^2.6.14", + "@babel/core": ">=7.12.10 <8.0.0" } } diff --git a/ui/pnpm-lock.yaml b/ui/pnpm-lock.yaml index 0e57569..a0e06fe 100644 --- a/ui/pnpm-lock.yaml +++ b/ui/pnpm-lock.yaml @@ -1,40 +1,28 @@ lockfileVersion: 5.3 specifiers: - "@babel/core": ^7.17.0 - "@emotion/react": ^11.7.1 - "@emotion/styled": ^11.6.0 - "@mui/icons-material": ^5.3.1 - "@mui/lab": ^5.0.0-alpha.67 - "@mui/material": ^5.4.0 - "@types/react-dom": ^17.0.11 - "@vitejs/plugin-react-refresh": latest - axios: ^0.25.0 - date-fns: ^2.28.0 - react: ^17.0.2 - react-dom: ^17.0.2 + "@babel/core": ">=7.12.10 <8.0.0" + "@mdi/js": ^6.5.95 + "@preact/preset-vite": ^2.1.5 + axios: ^0.24.0 + preact: ^10.5.15 + prettier: ^2.4.1 + sass: ^1.43.4 typescript: ^4.5.2 - vite: latest - wouter: ^2.8.0-alpha.2 + vite: ^2.6.14 dependencies: - "@emotion/react": 11.7.1_@babel+core@7.17.0+react@17.0.2 - "@emotion/styled": 11.6.0_f7d5c6639f7c2cb185a33953e29a971a - "@mui/icons-material": 5.3.1_@mui+material@5.4.0+react@17.0.2 - "@mui/lab": 5.0.0-alpha.67_7b8cfd313d74777d565ad5f64226489b - "@mui/material": 5.4.0_c84e354a724f4213aa6539fdea9d08aa - axios: 0.25.0 - date-fns: 2.28.0 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - wouter: 2.8.0-alpha.2_react@17.0.2 + "@mdi/js": 6.5.95 + axios: 0.24.0 + preact: 10.6.5 devDependencies: "@babel/core": 7.17.0 - "@types/react-dom": 17.0.11 - "@vitejs/plugin-react-refresh": 1.3.6 + "@preact/preset-vite": 2.1.7_8bad03c14e079d36b71a4a5e3cd3eb6f + prettier: 2.5.1 + sass: 1.49.7 typescript: 4.5.5 - vite: 2.7.13 + vite: 2.7.13_sass@1.49.7 packages: /@ampproject/remapping/2.0.2: @@ -56,6 +44,7 @@ packages: engines: {node: ">=6.9.0"} dependencies: "@babel/highlight": 7.16.10 + dev: true /@babel/compat-data/7.17.0: resolution: @@ -103,6 +92,16 @@ packages: source-map: 0.5.7 dev: true + /@babel/helper-annotate-as-pure/7.16.7: + resolution: + { + integrity: sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==, + } + engines: {node: ">=6.9.0"} + dependencies: + "@babel/types": 7.17.0 + dev: true + /@babel/helper-compilation-targets/7.16.7_@babel+core@7.17.0: resolution: { @@ -169,6 +168,7 @@ packages: engines: {node: ">=6.9.0"} dependencies: "@babel/types": 7.17.0 + dev: true /@babel/helper-module-transforms/7.16.7: resolution: @@ -195,6 +195,7 @@ packages: integrity: sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==, } engines: {node: ">=6.9.0"} + dev: true /@babel/helper-simple-access/7.16.7: resolution: @@ -222,6 +223,7 @@ packages: integrity: sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==, } engines: {node: ">=6.9.0"} + dev: true /@babel/helper-validator-option/7.16.7: resolution: @@ -255,6 +257,7 @@ packages: "@babel/helper-validator-identifier": 7.16.7 chalk: 2.4.2 js-tokens: 4.0.0 + dev: true /@babel/parser/7.17.0: resolution: @@ -276,44 +279,25 @@ packages: dependencies: "@babel/core": 7.17.0 "@babel/helper-plugin-utils": 7.16.7 - dev: false + dev: true - /@babel/plugin-transform-react-jsx-self/7.16.7_@babel+core@7.17.0: + /@babel/plugin-transform-react-jsx/7.16.7_@babel+core@7.17.0: resolution: { - integrity: sha512-oe5VuWs7J9ilH3BCCApGoYjHoSO48vkjX2CbA5bFVhIuO2HKxA3vyF7rleA4o6/4rTDbk6r8hBW7Ul8E+UZrpA==, + integrity: sha512-8D16ye66fxiE8m890w0BpPpngG9o9OVBBy0gH2E+2AR7qMR2ZpTYJEqLxAsoroenMId0p/wMW+Blc0meDgu0Ag==, } engines: {node: ">=6.9.0"} peerDependencies: "@babel/core": ^7.0.0-0 dependencies: "@babel/core": 7.17.0 + "@babel/helper-annotate-as-pure": 7.16.7 + "@babel/helper-module-imports": 7.16.7 "@babel/helper-plugin-utils": 7.16.7 + "@babel/plugin-syntax-jsx": 7.16.7_@babel+core@7.17.0 + "@babel/types": 7.17.0 dev: true - /@babel/plugin-transform-react-jsx-source/7.16.7_@babel+core@7.17.0: - resolution: - { - integrity: sha512-rONFiQz9vgbsnaMtQlZCjIRwhJvlrPET8TabIUK2hzlXw9B9s2Ieaxte1SCOOXMbWRHodbKixNf3BLcWVOQ8Bw==, - } - engines: {node: ">=6.9.0"} - peerDependencies: - "@babel/core": ^7.0.0-0 - dependencies: - "@babel/core": 7.17.0 - "@babel/helper-plugin-utils": 7.16.7 - dev: true - - /@babel/runtime/7.17.0: - resolution: - { - integrity: sha512-etcO/ohMNaNA2UBdaXBBSX/3aEzFMRrVfaPv8Ptc0k+cWpWW0QFiGZ2XnVqQZI1Cf734LbPGmqBKWESfW4x/dQ==, - } - engines: {node: ">=6.9.0"} - dependencies: - regenerator-runtime: 0.13.9 - dev: false - /@babel/template/7.16.7: resolution: { @@ -356,222 +340,7 @@ packages: dependencies: "@babel/helper-validator-identifier": 7.16.7 to-fast-properties: 2.0.0 - - /@date-io/core/2.13.1: - resolution: - { - integrity: sha512-pVI9nfkf2qClb2Cxdq0Q4zJhdawMG4ybWZUVGifT78FDwzRMX2SwXBb55s5NRJk0HcIicDuxktmCtemZqMH1Zg==, - } - dev: false - - /@date-io/date-fns/2.13.1_date-fns@2.28.0: - resolution: - { - integrity: sha512-8fmfwjiLMpFLD+t4NBwDx0eblWnNcgt4NgfT/uiiQTGI81fnPu9tpBMYdAcuWxaV7LLpXgzLBx1SYWAMDVUDQQ==, - } - peerDependencies: - date-fns: ^2.0.0 - peerDependenciesMeta: - date-fns: - optional: true - dependencies: - "@date-io/core": 2.13.1 - date-fns: 2.28.0 - dev: false - - /@date-io/dayjs/2.13.1: - resolution: - { - integrity: sha512-5bL4WWWmlI4uGZVScANhHJV7Mjp93ec2gNeUHDqqLaMZhp51S0NgD25oqj/k0LqBn1cdU2MvzNpk/ObMmVv5cQ==, - } - peerDependencies: - dayjs: ^1.8.17 - peerDependenciesMeta: - dayjs: - optional: true - dependencies: - "@date-io/core": 2.13.1 - dev: false - - /@date-io/luxon/2.13.1: - resolution: - { - integrity: sha512-yG+uM7lXfwLyKKEwjvP8oZ7qblpmfl9gxQYae55ifbwiTs0CoCTkYkxEaQHGkYtTqGTzLqcb0O9Pzx6vgWg+yg==, - } - peerDependencies: - luxon: ^1.21.3 || ^2.x - peerDependenciesMeta: - luxon: - optional: true - dependencies: - "@date-io/core": 2.13.1 - dev: false - - /@date-io/moment/2.13.1: - resolution: - { - integrity: sha512-XX1X/Tlvl3TdqQy2j0ZUtEJV6Rl8tOyc5WOS3ki52He28Uzme4Ro/JuPWTMBDH63weSWIZDlbR7zBgp3ZA2y1A==, - } - peerDependencies: - moment: ^2.24.0 - peerDependenciesMeta: - moment: - optional: true - dependencies: - "@date-io/core": 2.13.1 - dev: false - - /@emotion/babel-plugin/11.7.2_@babel+core@7.17.0: - resolution: - { - integrity: sha512-6mGSCWi9UzXut/ZAN6lGFu33wGR3SJisNl3c0tvlmb8XChH1b2SUvxvnOh7hvLpqyRdHHU9AiazV3Cwbk5SXKQ==, - } - peerDependencies: - "@babel/core": ^7.0.0 - dependencies: - "@babel/core": 7.17.0 - "@babel/helper-module-imports": 7.16.7 - "@babel/plugin-syntax-jsx": 7.16.7_@babel+core@7.17.0 - "@babel/runtime": 7.17.0 - "@emotion/hash": 0.8.0 - "@emotion/memoize": 0.7.5 - "@emotion/serialize": 1.0.2 - babel-plugin-macros: 2.8.0 - convert-source-map: 1.8.0 - escape-string-regexp: 4.0.0 - find-root: 1.1.0 - source-map: 0.5.7 - stylis: 4.0.13 - dev: false - - /@emotion/cache/11.7.1: - resolution: - { - integrity: sha512-r65Zy4Iljb8oyjtLeCuBH8Qjiy107dOYC6SJq7g7GV5UCQWMObY4SJDPGFjiiVpPrOJ2hmJOoBiYTC7hwx9E2A==, - } - dependencies: - "@emotion/memoize": 0.7.5 - "@emotion/sheet": 1.1.0 - "@emotion/utils": 1.0.0 - "@emotion/weak-memoize": 0.2.5 - stylis: 4.0.13 - dev: false - - /@emotion/hash/0.8.0: - resolution: - { - integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==, - } - dev: false - - /@emotion/is-prop-valid/1.1.1: - resolution: - { - integrity: sha512-bW1Tos67CZkOURLc0OalnfxtSXQJMrAMV0jZTVGJUPSOd4qgjF3+tTD5CwJM13PHA8cltGW1WGbbvV9NpvUZPw==, - } - dependencies: - "@emotion/memoize": 0.7.5 - dev: false - - /@emotion/memoize/0.7.5: - resolution: - { - integrity: sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ==, - } - dev: false - - /@emotion/react/11.7.1_@babel+core@7.17.0+react@17.0.2: - resolution: - { - integrity: sha512-DV2Xe3yhkF1yT4uAUoJcYL1AmrnO5SVsdfvu+fBuS7IbByDeTVx9+wFmvx9Idzv7/78+9Mgx2Hcmr7Fex3tIyw==, - } - peerDependencies: - "@babel/core": ^7.0.0 - "@types/react": "*" - react: ">=16.8.0" - peerDependenciesMeta: - "@babel/core": - optional: true - "@types/react": - optional: true - dependencies: - "@babel/core": 7.17.0 - "@babel/runtime": 7.17.0 - "@emotion/cache": 11.7.1 - "@emotion/serialize": 1.0.2 - "@emotion/sheet": 1.1.0 - "@emotion/utils": 1.0.0 - "@emotion/weak-memoize": 0.2.5 - hoist-non-react-statics: 3.3.2 - react: 17.0.2 - dev: false - - /@emotion/serialize/1.0.2: - resolution: - { - integrity: sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A==, - } - dependencies: - "@emotion/hash": 0.8.0 - "@emotion/memoize": 0.7.5 - "@emotion/unitless": 0.7.5 - "@emotion/utils": 1.0.0 - csstype: 3.0.10 - dev: false - - /@emotion/sheet/1.1.0: - resolution: - { - integrity: sha512-u0AX4aSo25sMAygCuQTzS+HsImZFuS8llY8O7b9MDRzbJM0kVJlAz6KNDqcG7pOuQZJmj/8X/rAW+66kMnMW+g==, - } - dev: false - - /@emotion/styled/11.6.0_f7d5c6639f7c2cb185a33953e29a971a: - resolution: - { - integrity: sha512-mxVtVyIOTmCAkFbwIp+nCjTXJNgcz4VWkOYQro87jE2QBTydnkiYusMrRGFtzuruiGK4dDaNORk4gH049iiQuw==, - } - peerDependencies: - "@babel/core": ^7.0.0 - "@emotion/react": ^11.0.0-rc.0 - "@types/react": "*" - react: ">=16.8.0" - peerDependenciesMeta: - "@babel/core": - optional: true - "@types/react": - optional: true - dependencies: - "@babel/core": 7.17.0 - "@babel/runtime": 7.17.0 - "@emotion/babel-plugin": 11.7.2_@babel+core@7.17.0 - "@emotion/is-prop-valid": 1.1.1 - "@emotion/react": 11.7.1_@babel+core@7.17.0+react@17.0.2 - "@emotion/serialize": 1.0.2 - "@emotion/utils": 1.0.0 - react: 17.0.2 - dev: false - - /@emotion/unitless/0.7.5: - resolution: - { - integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==, - } - dev: false - - /@emotion/utils/1.0.0: - resolution: - { - integrity: sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA==, - } - dev: false - - /@emotion/weak-memoize/0.2.5: - resolution: - { - integrity: sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==, - } - dev: false + dev: true /@jridgewell/resolve-uri/3.0.4: resolution: @@ -591,247 +360,80 @@ packages: sourcemap-codec: 1.4.8 dev: true - /@mui/base/5.0.0-alpha.67_react-dom@17.0.2+react@17.0.2: + /@mdi/js/6.5.95: resolution: { - integrity: sha512-yK2++NivZUitAVpheMc5QVuwrVCphrTw85L6qjKcvnSpB8wmVYne58CY2vzMCNEuHkuHG2jccq9/JlRZFGAanw==, + integrity: sha512-x/bwEoAGP+Mo10Dfk5audNIPi7Yz8ZBrILcbXLW3ShOI/njpgodzpgpC2WYK3D2ZSC392peRRemIFb/JsyzzYQ==, } - engines: {node: ">=12.0.0"} - peerDependencies: - "@types/react": ^16.8.6 || ^17.0.0 - react: ^17.0.0 - react-dom: ^17.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - dependencies: - "@babel/runtime": 7.17.0 - "@emotion/is-prop-valid": 1.1.1 - "@mui/utils": 5.3.0_react@17.0.2 - "@popperjs/core": 2.11.2 - clsx: 1.1.1 - prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-is: 17.0.2 dev: false - /@mui/icons-material/5.3.1_@mui+material@5.4.0+react@17.0.2: + /@preact/preset-vite/2.1.7_8bad03c14e079d36b71a4a5e3cd3eb6f: resolution: { - integrity: sha512-8zBWCaE8DHjIGZhGgMod92p6Rm38EhXrS+cZtaV0+jOTMeWh7z+mvswXzb/rVKc0ZYqw6mQYBcn2uEs2yclI9w==, + integrity: sha512-/Ii+aN1Jm8TK5YzDVrj5UOVRZ91F2Nik1P3FbmZyQ5VJAg1ZCkOBBkmLrz9YhiMbbGl+U35yaZNUDMcO8Xlp2g==, } - engines: {node: ">=12.0.0"} peerDependencies: - "@mui/material": ^5.0.0 - "@types/react": ^16.8.6 || ^17.0.0 - react: ^17.0.0 - peerDependenciesMeta: - "@types/react": - optional: true + "@babel/core": 7.x + vite: 2.x dependencies: - "@babel/runtime": 7.17.0 - "@mui/material": 5.4.0_c84e354a724f4213aa6539fdea9d08aa - react: 17.0.2 - dev: false - - /@mui/lab/5.0.0-alpha.67_7b8cfd313d74777d565ad5f64226489b: - resolution: - { - integrity: sha512-pL6O2teso3tpAv38FXiFNWGcXjakgO66/Os5p2KX4QbkPKvzzeSxNU7hI02Ye8BIEYqTR5Oaz8njcdQgcNI7Cg==, - } - engines: {node: ">=12.0.0"} - peerDependencies: - "@mui/material": ^5.0.0 - "@types/react": ^16.8.6 || ^17.0.0 - date-fns: ^2.25.0 - dayjs: ^1.10.7 - luxon: ^1.28.0 || ^2.0.0 - moment: ^2.29.1 - react: ^17.0.0 - react-dom: ^17.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - date-fns: - optional: true - dayjs: - optional: true - luxon: - optional: true - moment: - optional: true - dependencies: - "@babel/runtime": 7.17.0 - "@date-io/date-fns": 2.13.1_date-fns@2.28.0 - "@date-io/dayjs": 2.13.1 - "@date-io/luxon": 2.13.1 - "@date-io/moment": 2.13.1 - "@mui/base": 5.0.0-alpha.67_react-dom@17.0.2+react@17.0.2 - "@mui/material": 5.4.0_c84e354a724f4213aa6539fdea9d08aa - "@mui/system": 5.4.0_922a85da57e3646a57465b7970b0de85 - "@mui/utils": 5.3.0_react@17.0.2 - clsx: 1.1.1 - date-fns: 2.28.0 - prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-is: 17.0.2 - react-transition-group: 4.4.2_react-dom@17.0.2+react@17.0.2 - rifm: 0.12.1_react@17.0.2 + "@babel/core": 7.17.0 + "@babel/plugin-transform-react-jsx": 7.16.7_@babel+core@7.17.0 + "@prefresh/vite": 2.2.6_preact@10.6.5+vite@2.7.13 + "@rollup/pluginutils": 4.1.2 + babel-plugin-transform-hook-names: 1.0.2_@babel+core@7.17.0 + debug: 4.3.3 + kolorist: 1.5.1 + resolve: 1.22.0 + vite: 2.7.13_sass@1.49.7 transitivePeerDependencies: - - "@emotion/react" - - "@emotion/styled" - dev: false + - preact + - supports-color + dev: true - /@mui/material/5.4.0_c84e354a724f4213aa6539fdea9d08aa: + /@prefresh/babel-plugin/0.4.1: resolution: { - integrity: sha512-vfBIAMsRNWI/A4p/eP01MjqhSACwxRGYp/2Yi7WAU64PpI/TXR4b9SRl+XJMMJXVC7+abu4E3hTdF3oqwMCSYA==, + integrity: sha512-gj3ekiYtHlZNz0zFI1z6a9mcYX80Qacw84+2++7V1skvO7kQoV2ux56r8bJkTBbKMVxwAgaYrxxIdUCYlclE7Q==, + } + dev: true + + /@prefresh/core/1.3.2_preact@10.6.5: + resolution: + { + integrity: sha512-Iv+uI698KDgWsrKpLvOgN3hmAMyvhVgn09mcnhZ98BUNdg/qrxE7tcUf5yFCImkgqED5/Dcn8G5hFy4IikEDvg==, } - engines: {node: ">=12.0.0"} peerDependencies: - "@emotion/react": ^11.5.0 - "@emotion/styled": ^11.3.0 - "@types/react": ^16.8.6 || ^17.0.0 - react: ^17.0.0 - react-dom: ^17.0.0 - peerDependenciesMeta: - "@emotion/react": - optional: true - "@emotion/styled": - optional: true - "@types/react": - optional: true + preact: ^10.0.0 dependencies: - "@babel/runtime": 7.17.0 - "@emotion/react": 11.7.1_@babel+core@7.17.0+react@17.0.2 - "@emotion/styled": 11.6.0_f7d5c6639f7c2cb185a33953e29a971a - "@mui/base": 5.0.0-alpha.67_react-dom@17.0.2+react@17.0.2 - "@mui/system": 5.4.0_922a85da57e3646a57465b7970b0de85 - "@mui/types": 7.1.0 - "@mui/utils": 5.3.0_react@17.0.2 - "@types/react-transition-group": 4.4.4 - clsx: 1.1.1 - csstype: 3.0.10 - hoist-non-react-statics: 3.3.2 - prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-is: 17.0.2 - react-transition-group: 4.4.2_react-dom@17.0.2+react@17.0.2 - dev: false + preact: 10.6.5 + dev: true - /@mui/private-theming/5.3.0_react@17.0.2: + /@prefresh/utils/1.1.1: resolution: { - integrity: sha512-EBobUEyM9fMnteKrVPp8pTMUh81xXakyfdpkoh7Y19q9JpD2eh7QGAQVJVj0JBFlcUJD60NIE4K8rdokrRmLwg==, + integrity: sha512-MUhT5m2XNN5NsZl4GnpuvlzLo6VSTa/+wBfBd3fiWUvHGhv0GF9hnA1pd//v0uJaKwUnVRQ1hYElxCV7DtYsCQ==, + } + dev: true + + /@prefresh/vite/2.2.6_preact@10.6.5+vite@2.7.13: + resolution: + { + integrity: sha512-Q5i15C27NanIPzimkvBuzImebCxeQS6p8OyyH2QpNKS/HGsm7WpnyCzgMkIsidnmMHY59qllKwF01TWpq9IeGA==, } - engines: {node: ">=12.0.0"} peerDependencies: - "@types/react": ^16.8.6 || ^17.0.0 - react: ^17.0.0 - peerDependenciesMeta: - "@types/react": - optional: true + preact: ^10.4.0 + vite: ">=2.0.0-beta.3" dependencies: - "@babel/runtime": 7.17.0 - "@mui/utils": 5.3.0_react@17.0.2 - prop-types: 15.8.1 - react: 17.0.2 - dev: false - - /@mui/styled-engine/5.3.0_922a85da57e3646a57465b7970b0de85: - resolution: - { - integrity: sha512-I4YemFy9WnCLUdZ5T+6egpzc8e7Jq/uh9AJ3QInZHbyNu/9I2SWvNn7vHjWOT/D8Y8LMzIOhu5WwZbzjez7YRw==, - } - engines: {node: ">=12.0.0"} - peerDependencies: - "@emotion/react": ^11.4.1 - "@emotion/styled": ^11.3.0 - react: ^17.0.0 - peerDependenciesMeta: - "@emotion/react": - optional: true - "@emotion/styled": - optional: true - dependencies: - "@babel/runtime": 7.17.0 - "@emotion/cache": 11.7.1 - "@emotion/react": 11.7.1_@babel+core@7.17.0+react@17.0.2 - "@emotion/styled": 11.6.0_f7d5c6639f7c2cb185a33953e29a971a - prop-types: 15.8.1 - react: 17.0.2 - dev: false - - /@mui/system/5.4.0_922a85da57e3646a57465b7970b0de85: - resolution: - { - integrity: sha512-LX7g5gK5yCwiueSUVG73uVNc0yeHjsWUIFLrnPjP3m+J7O38RkPqyao5nZahhaSL1PGNbR9+zfkxljXthO9QqA==, - } - engines: {node: ">=12.0.0"} - peerDependencies: - "@emotion/react": ^11.5.0 - "@emotion/styled": ^11.3.0 - "@types/react": ^16.8.6 || ^17.0.0 - react: ^17.0.0 - peerDependenciesMeta: - "@emotion/react": - optional: true - "@emotion/styled": - optional: true - "@types/react": - optional: true - dependencies: - "@babel/runtime": 7.17.0 - "@emotion/react": 11.7.1_@babel+core@7.17.0+react@17.0.2 - "@emotion/styled": 11.6.0_f7d5c6639f7c2cb185a33953e29a971a - "@mui/private-theming": 5.3.0_react@17.0.2 - "@mui/styled-engine": 5.3.0_922a85da57e3646a57465b7970b0de85 - "@mui/types": 7.1.0 - "@mui/utils": 5.3.0_react@17.0.2 - clsx: 1.1.1 - csstype: 3.0.10 - prop-types: 15.8.1 - react: 17.0.2 - dev: false - - /@mui/types/7.1.0: - resolution: - { - integrity: sha512-Hh7ALdq/GjfIwLvqH3XftuY3bcKhupktTm+S6qRIDGOtPtRuq2L21VWzOK4p7kblirK0XgGVH5BLwa6u8z/6QQ==, - } - peerDependencies: - "@types/react": "*" - peerDependenciesMeta: - "@types/react": - optional: true - dev: false - - /@mui/utils/5.3.0_react@17.0.2: - resolution: - { - integrity: sha512-O/E9IQKPMg0OrN7+gkn7Ga5o5WA2iXQGdyqNBFPNrYzxOvwzsEtM5K7MtTCGGYKFe8mhTRM0ZOjh5OM0dglw+Q==, - } - engines: {node: ">=12.0.0"} - peerDependencies: - react: ^17.0.0 - dependencies: - "@babel/runtime": 7.17.0 - "@types/prop-types": 15.7.4 - "@types/react-is": 17.0.3 - prop-types: 15.8.1 - react: 17.0.2 - react-is: 17.0.2 - dev: false - - /@popperjs/core/2.11.2: - resolution: - { - integrity: sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==, - } - dev: false + "@babel/core": 7.17.0 + "@prefresh/babel-plugin": 0.4.1 + "@prefresh/core": 1.3.2_preact@10.6.5 + "@prefresh/utils": 1.1.1 + "@rollup/pluginutils": 4.1.2 + preact: 10.6.5 + vite: 2.7.13_sass@1.49.7 + transitivePeerDependencies: + - supports-color + dev: true /@rollup/pluginutils/4.1.2: resolution: @@ -844,78 +446,6 @@ packages: picomatch: 2.3.1 dev: true - /@types/parse-json/4.0.0: - resolution: - { - integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==, - } - dev: false - - /@types/prop-types/15.7.4: - resolution: - { - integrity: sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==, - } - - /@types/react-dom/17.0.11: - resolution: - { - integrity: sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==, - } - dependencies: - "@types/react": 17.0.39 - dev: true - - /@types/react-is/17.0.3: - resolution: - { - integrity: sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==, - } - dependencies: - "@types/react": 17.0.39 - dev: false - - /@types/react-transition-group/4.4.4: - resolution: - { - integrity: sha512-7gAPz7anVK5xzbeQW9wFBDg7G++aPLAFY0QaSMOou9rJZpbuI58WAuJrgu+qR92l61grlnCUe7AFX8KGahAgug==, - } - dependencies: - "@types/react": 17.0.39 - dev: false - - /@types/react/17.0.39: - resolution: - { - integrity: sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==, - } - dependencies: - "@types/prop-types": 15.7.4 - "@types/scheduler": 0.16.2 - csstype: 3.0.10 - - /@types/scheduler/0.16.2: - resolution: - { - integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==, - } - - /@vitejs/plugin-react-refresh/1.3.6: - resolution: - { - integrity: sha512-iNR/UqhUOmFFxiezt0em9CgmiJBdWR+5jGxB2FihaoJfqGt76kiwaKoVOJVU5NYcDWMdN06LbyN2VIGIoYdsEA==, - } - engines: {node: ">=12.0.0"} - dependencies: - "@babel/core": 7.17.0 - "@babel/plugin-transform-react-jsx-self": 7.16.7_@babel+core@7.17.0 - "@babel/plugin-transform-react-jsx-source": 7.16.7_@babel+core@7.17.0 - "@rollup/pluginutils": 4.1.2 - react-refresh: 0.10.0 - transitivePeerDependencies: - - supports-color - dev: true - /ansi-styles/3.2.1: resolution: { @@ -924,11 +454,23 @@ packages: engines: {node: ">=4"} dependencies: color-convert: 1.9.3 + dev: true - /axios/0.25.0: + /anymatch/3.1.2: resolution: { - integrity: sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==, + integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==, + } + engines: {node: ">= 8"} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /axios/0.24.0: + resolution: + { + integrity: sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==, } dependencies: follow-redirects: 1.14.7 @@ -936,16 +478,34 @@ packages: - debug dev: false - /babel-plugin-macros/2.8.0: + /babel-plugin-transform-hook-names/1.0.2_@babel+core@7.17.0: resolution: { - integrity: sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==, + integrity: sha512-5gafyjyyBTTdX/tQQ0hRgu4AhNHG/hqWi0ZZmg2xvs2FgRkJXzDNKBZCyoYqgFkovfDrgM8OoKg8karoUvWeCw==, } + peerDependencies: + "@babel/core": ^7.12.10 dependencies: - "@babel/runtime": 7.17.0 - cosmiconfig: 6.0.0 - resolve: 1.22.0 - dev: false + "@babel/core": 7.17.0 + dev: true + + /binary-extensions/2.2.0: + resolution: + { + integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==, + } + engines: {node: ">=8"} + dev: true + + /braces/3.0.2: + resolution: + { + integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==, + } + engines: {node: ">=8"} + dependencies: + fill-range: 7.0.1 + dev: true /browserslist/4.19.1: resolution: @@ -956,20 +516,12 @@ packages: hasBin: true dependencies: caniuse-lite: 1.0.30001306 - electron-to-chromium: 1.4.64 + electron-to-chromium: 1.4.63 escalade: 3.1.1 node-releases: 2.0.1 picocolors: 1.0.0 dev: true - /callsites/3.1.0: - resolution: - { - integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==, - } - engines: {node: ">=6"} - dev: false - /caniuse-lite/1.0.30001306: resolution: { @@ -987,14 +539,25 @@ packages: ansi-styles: 3.2.1 escape-string-regexp: 1.0.5 supports-color: 5.5.0 + dev: true - /clsx/1.1.1: + /chokidar/3.5.3: resolution: { - integrity: sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==, + integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==, } - engines: {node: ">=6"} - dev: false + engines: {node: ">= 8.10.0"} + dependencies: + anymatch: 3.1.2 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.2 + dev: true /color-convert/1.9.3: resolution: @@ -1003,9 +566,11 @@ packages: } dependencies: color-name: 1.1.3 + dev: true /color-name/1.1.3: resolution: {integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=} + dev: true /convert-source-map/1.8.0: resolution: @@ -1014,34 +579,7 @@ packages: } dependencies: safe-buffer: 5.1.2 - - /cosmiconfig/6.0.0: - resolution: - { - integrity: sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==, - } - engines: {node: ">=8"} - dependencies: - "@types/parse-json": 4.0.0 - import-fresh: 3.3.0 - parse-json: 5.2.0 - path-type: 4.0.0 - yaml: 1.10.2 - dev: false - - /csstype/3.0.10: - resolution: - { - integrity: sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==, - } - - /date-fns/2.28.0: - resolution: - { - integrity: sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==, - } - engines: {node: ">=0.11"} - dev: false + dev: true /debug/4.3.3: resolution: @@ -1058,32 +596,13 @@ packages: ms: 2.1.2 dev: true - /dom-helpers/5.2.1: + /electron-to-chromium/1.4.63: resolution: { - integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==, - } - dependencies: - "@babel/runtime": 7.17.0 - csstype: 3.0.10 - dev: false - - /electron-to-chromium/1.4.64: - resolution: - { - integrity: sha512-8mec/99xgLUZCIZZq3wt61Tpxg55jnOSpxGYapE/1Ma9MpFEYYaz4QNYm0CM1rrnCo7i3FRHhbaWjeCLsveGjQ==, + integrity: sha512-e0PX/LRJPFRU4kzJKLvTobxyFdnANCvcoDCe8XcyTqP58nTWIwdsHvXLIl1RkB39X5yaosLaroMASWB0oIsgCA==, } dev: true - /error-ex/1.3.2: - resolution: - { - integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==, - } - dependencies: - is-arrayish: 0.2.1 - dev: false - /esbuild-android-arm64/0.13.15: resolution: { @@ -1309,14 +828,7 @@ packages: /escape-string-regexp/1.0.5: resolution: {integrity: sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=} engines: {node: ">=0.8.0"} - - /escape-string-regexp/4.0.0: - resolution: - { - integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==, - } - engines: {node: ">=10"} - dev: false + dev: true /estree-walker/2.0.2: resolution: @@ -1325,12 +837,15 @@ packages: } dev: true - /find-root/1.1.0: + /fill-range/7.0.1: resolution: { - integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==, + integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==, } - dev: false + engines: {node: ">=8"} + dependencies: + to-regex-range: 5.0.1 + dev: true /follow-redirects/1.14.7: resolution: @@ -1361,6 +876,7 @@ packages: { integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==, } + dev: true /gensync/1.0.0-beta.2: resolution: @@ -1370,6 +886,16 @@ packages: engines: {node: ">=6.9.0"} dev: true + /glob-parent/5.1.2: + resolution: + { + integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==, + } + engines: {node: ">= 6"} + dependencies: + is-glob: 4.0.3 + dev: true + /globals/11.12.0: resolution: { @@ -1381,6 +907,7 @@ packages: /has-flag/3.0.0: resolution: {integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0=} engines: {node: ">=4"} + dev: true /has/1.0.3: resolution: @@ -1390,30 +917,24 @@ packages: engines: {node: ">= 0.4.0"} dependencies: function-bind: 1.1.1 + dev: true - /hoist-non-react-statics/3.3.2: + /immutable/4.0.0: resolution: { - integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==, + integrity: sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==, } - dependencies: - react-is: 16.13.1 - dev: false + dev: true - /import-fresh/3.3.0: + /is-binary-path/2.1.0: resolution: { - integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==, + integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==, } - engines: {node: ">=6"} + engines: {node: ">=8"} dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - dev: false - - /is-arrayish/0.2.1: - resolution: {integrity: sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=} - dev: false + binary-extensions: 2.2.0 + dev: true /is-core-module/2.8.1: resolution: @@ -1422,12 +943,37 @@ packages: } dependencies: has: 1.0.3 + dev: true + + /is-extglob/2.1.1: + resolution: {integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=} + engines: {node: ">=0.10.0"} + dev: true + + /is-glob/4.0.3: + resolution: + { + integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==, + } + engines: {node: ">=0.10.0"} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-number/7.0.0: + resolution: + { + integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==, + } + engines: {node: ">=0.12.0"} + dev: true /js-tokens/4.0.0: resolution: { integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==, } + dev: true /jsesc/2.5.2: resolution: @@ -1438,13 +984,6 @@ packages: hasBin: true dev: true - /json-parse-even-better-errors/2.3.1: - resolution: - { - integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==, - } - dev: false - /json5/2.2.0: resolution: { @@ -1456,22 +995,12 @@ packages: minimist: 1.2.5 dev: true - /lines-and-columns/1.2.4: + /kolorist/1.5.1: resolution: { - integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==, + integrity: sha512-lxpCM3HTvquGxKGzHeknB/sUjuVoUElLlfYnXZT73K8geR9jQbroGlSCFBax9/0mpGoD3kzcMLnOlGQPJJNyqQ==, } - dev: false - - /loose-envify/1.4.0: - resolution: - { - integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==, - } - hasBin: true - dependencies: - js-tokens: 4.0.0 - dev: false + dev: true /minimist/1.2.5: resolution: @@ -1503,47 +1032,20 @@ packages: } dev: true - /object-assign/4.1.1: - resolution: {integrity: sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=} + /normalize-path/3.0.0: + resolution: + { + integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==, + } engines: {node: ">=0.10.0"} - dev: false - - /parent-module/1.0.1: - resolution: - { - integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==, - } - engines: {node: ">=6"} - dependencies: - callsites: 3.1.0 - dev: false - - /parse-json/5.2.0: - resolution: - { - integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==, - } - engines: {node: ">=8"} - dependencies: - "@babel/code-frame": 7.16.7 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - dev: false + dev: true /path-parse/1.0.7: resolution: { integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==, } - - /path-type/4.0.0: - resolution: - { - integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==, - } - engines: {node: ">=8"} - dev: false + dev: true /picocolors/1.0.0: resolution: @@ -1572,95 +1074,31 @@ packages: source-map-js: 1.0.2 dev: true - /prop-types/15.8.1: + /preact/10.6.5: resolution: { - integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==, - } - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - dev: false - - /react-dom/17.0.2_react@17.0.2: - resolution: - { - integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==, - } - peerDependencies: - react: 17.0.2 - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react: 17.0.2 - scheduler: 0.20.2 - dev: false - - /react-is/16.13.1: - resolution: - { - integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==, + integrity: sha512-i+LXM6JiVjQXSt2jG2vZZFapGpCuk1fl8o6ii3G84MA3xgj686FKjs4JFDkmUVhtxyq21+4ay74zqPykz9hU6w==, } dev: false - /react-is/17.0.2: + /prettier/2.5.1: resolution: { - integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==, + integrity: sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==, } - dev: false - - /react-refresh/0.10.0: - resolution: - { - integrity: sha512-PgidR3wST3dDYKr6b4pJoqQFpPGNKDSCDx4cZoshjXipw3LzO7mG1My2pwEzz2JVkF+inx3xRpDeQLFQGH/hsQ==, - } - engines: {node: ">=0.10.0"} + engines: {node: ">=10.13.0"} + hasBin: true dev: true - /react-transition-group/4.4.2_react-dom@17.0.2+react@17.0.2: + /readdirp/3.6.0: resolution: { - integrity: sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==, + integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==, } - peerDependencies: - react: ">=16.6.0" - react-dom: ">=16.6.0" + engines: {node: ">=8.10.0"} dependencies: - "@babel/runtime": 7.17.0 - dom-helpers: 5.2.1 - loose-envify: 1.4.0 - prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - dev: false - - /react/17.0.2: - resolution: - { - integrity: sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==, - } - engines: {node: ">=0.10.0"} - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - dev: false - - /regenerator-runtime/0.13.9: - resolution: - { - integrity: sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==, - } - dev: false - - /resolve-from/4.0.0: - resolution: - { - integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==, - } - engines: {node: ">=4"} - dev: false + picomatch: 2.3.1 + dev: true /resolve/1.22.0: resolution: @@ -1672,17 +1110,7 @@ packages: is-core-module: 2.8.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - - /rifm/0.12.1_react@17.0.2: - resolution: - { - integrity: sha512-OGA1Bitg/dSJtI/c4dh90svzaUPt228kzFsUkJbtA2c964IqEAwWXeL9ZJi86xWv3j5SMqRvGULl7bA6cK0Bvg==, - } - peerDependencies: - react: ">=16.8" - dependencies: - react: 17.0.2 - dev: false + dev: true /rollup/2.67.0: resolution: @@ -1700,16 +1128,20 @@ packages: { integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==, } + dev: true - /scheduler/0.20.2: + /sass/1.49.7: resolution: { - integrity: sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==, + integrity: sha512-13dml55EMIR2rS4d/RDHHP0sXMY3+30e1TKsyXaSz3iLWVoDWEoboY8WzJd5JMnxrRHffKO3wq2mpJ0jxRJiEQ==, } + engines: {node: ">=12.0.0"} + hasBin: true dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - dev: false + chokidar: 3.5.3 + immutable: 4.0.0 + source-map-js: 1.0.2 + dev: true /semver/6.3.0: resolution: @@ -1730,6 +1162,7 @@ packages: /source-map/0.5.7: resolution: {integrity: sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=} engines: {node: ">=0.10.0"} + dev: true /sourcemap-codec/1.4.8: resolution: @@ -1738,13 +1171,6 @@ packages: } dev: true - /stylis/4.0.13: - resolution: - { - integrity: sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag==, - } - dev: false - /supports-color/5.5.0: resolution: { @@ -1753,6 +1179,7 @@ packages: engines: {node: ">=4"} dependencies: has-flag: 3.0.0 + dev: true /supports-preserve-symlinks-flag/1.0.0: resolution: @@ -1760,10 +1187,22 @@ packages: integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==, } engines: {node: ">= 0.4"} + dev: true /to-fast-properties/2.0.0: resolution: {integrity: sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=} engines: {node: ">=4"} + dev: true + + /to-regex-range/5.0.1: + resolution: + { + integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==, + } + engines: {node: ">=8.0"} + dependencies: + is-number: 7.0.0 + dev: true /typescript/4.5.5: resolution: @@ -1774,7 +1213,7 @@ packages: hasBin: true dev: true - /vite/2.7.13: + /vite/2.7.13_sass@1.49.7: resolution: { integrity: sha512-Mq8et7f3aK0SgSxjDNfOAimZGW9XryfHRa/uV0jseQSilg+KhYDSoNb9h1rknOy6SuMkvNDLKCYAYYUMCE+IgQ==, @@ -1797,25 +1236,7 @@ packages: postcss: 8.4.6 resolve: 1.22.0 rollup: 2.67.0 + sass: 1.49.7 optionalDependencies: fsevents: 2.3.2 dev: true - - /wouter/2.8.0-alpha.2_react@17.0.2: - resolution: - { - integrity: sha512-aPsL5m5rW9RiceClOmGj6t5gn9Ut2TJVr98UDi1u9MIRNYiYVflg6vFIjdDYJ4IAyH0JdnkSgGwfo0LQS3k2zg==, - } - peerDependencies: - react: ">=16.8.0" - dependencies: - react: 17.0.2 - dev: false - - /yaml/1.10.2: - resolution: - { - integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==, - } - engines: {node: ">= 6"} - dev: false diff --git a/ui/src/App.tsx b/ui/src/App.tsx deleted file mode 100644 index 2171ffc..0000000 --- a/ui/src/App.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import * as React from "react" -import {Box, Typography} from "@mui/material" -import {Route} from "wouter" - -import Navbar from "./components/Navbar" -import Controls from "./components/Controls" -import Jobs from "./components/Jobs" -import Settings from "./components/Settings" -import NoConnectionBar from "./components/NoConnectionBar" - -export default function App() { - return ( - - - - - - - - - - - - - - - - - ) -} diff --git a/ui/src/components/AutoMode.tsx b/ui/src/components/AutoMode.tsx deleted file mode 100644 index 78405a6..0000000 --- a/ui/src/components/AutoMode.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import * as React from "react" -import {Switch, FormControlLabel} from "@mui/material" -import {WebsocketClient} from "../util/websocket" -import {TaskList} from "../tsgrain-client" -import {tsgrainApi} from "../util/apiUrls" -import {handleApiError} from "../util/functions" - -type Props = {} - -type State = { - wsConnected: boolean - auto: boolean -} - -export default class AutoModeSwitch extends React.Component { - private ws?: WebsocketClient - - constructor(props: Props) { - super(props) - - this.state = { - wsConnected: false, - auto: false, - } - } - - private onWsStatusUpdate = (wsConnected: boolean) => { - this.setState({wsConnected: wsConnected}) - } - - private onWsMessage = (msg: TaskList, date: Date) => { - this.setState({auto: msg.auto_mode}) - } - - componentDidMount() { - this.ws = new WebsocketClient(this.onWsStatusUpdate, this.onWsMessage) - this.setState({wsConnected: this.ws.api().isConnected()}) - } - - componentWillUnmount() { - if (this.ws !== undefined) { - this.ws.destroy() - } - } - - private handleChange = (event: React.ChangeEvent) => { - const newState = !this.state.auto - tsgrainApi.setAutoMode({state: newState}).catch(handleApiError) - } - - render() { - return ( - - } - label="Auto" - /> - ) - } -} diff --git a/ui/src/components/Controls.tsx b/ui/src/components/Controls.tsx deleted file mode 100644 index e79a78e..0000000 --- a/ui/src/components/Controls.tsx +++ /dev/null @@ -1,344 +0,0 @@ -import * as React from "react" -import { - Container, - Card, - CardContent, - Typography, - CardActions, - Button, - Box, - Grid, - LinearProgress, - LinearProgressProps, -} from "@mui/material" -import { - TimerOutlined as IconSchedule, - PowerSettingsNew as IconManual, -} from "@mui/icons-material" -import {Config, getConfig} from "../util/config" -import {WebsocketClient, WebsocketMessage} from "../util/websocket" -import {TaskList, Task} from "../tsgrain-client" -import {tsgrainApi} from "../util/apiUrls" -import { - dateToTimestamp, - getTimestamp, - handleApiError, - secondsToString, -} from "../util/functions" - -function startZone(id: number) { - tsgrainApi.startTask({id: id}).catch(handleApiError) -} - -function stopZone(id: number) { - tsgrainApi.stopTask({id: id}).catch(handleApiError) -} - -type LinearProgressWithLabelProps = LinearProgressProps & { - label?: string - icon?: React.ReactElement -} - -function LinearProgressWithLabel(props: LinearProgressWithLabelProps) { - return ( - - -
- {props.icon} - - {props.label} - -
-
- - - -
- ) -} - -type TaskProgressProps = { - task: Task - taskListCliTimestamp: number - taskListSrvTimestamp: number -} - -type TaskProgressState = { - timestamp: number -} - -class TaskProgress extends React.Component { - private timerID?: number - - constructor(props: TaskProgressProps) { - super(props) - this.state = {timestamp: getTimestamp()} - } - - componentDidMount() { - this.timerID = setInterval(() => this.tick(), 1000) - } - - componentWillUnmount() { - clearInterval(this.timerID) - } - - tick() { - this.setState({ - timestamp: getTimestamp(), - }) - } - - render() { - let icon - switch (this.props.task.source) { - case 0: - icon = - break - - case 1: - icon = - break - - default: - break - } - - let progSeconds = 0, - progPercent = 0 - - if (this.props.task.datetime_started !== null) { - // Calculate the current server time based on current client time, - // client time at last TaskList update and server time at last TaskList update - const srvTimestamp = - this.state.timestamp - - this.props.taskListCliTimestamp + - this.props.taskListSrvTimestamp - - const srvDuration = - this.props.task.datetime_finished - this.props.task.datetime_started - - // If a task is restored from the database (after a server restart), - // it will continue at the left-off position. - // The 'Headstart' is the amount of irrigation time already completed - // in the previous server run. It needs to be added to the progress time. - const headstart = this.props.task.duration - srvDuration - - progSeconds = srvTimestamp - this.props.task.datetime_started + headstart - - // Cap progress in case the client is out of sync - progSeconds = Math.min(Math.max(progSeconds, 0), this.props.task.duration) - - progPercent = (progSeconds / srvDuration) * 100 - } - - return ( - - ) - } -} - -type TaskProgressListProps = { - tasks: Task[] - taskListCliTimestamp: number - taskListSrvTimestamp: number -} - -const TaskProgressList = (props: TaskProgressListProps) => { - let items: React.ReactElement[] = [] - - props.tasks.forEach((task, i) => { - let icon - switch (task.source) { - case 0: - icon = - break - - case 1: - icon = - break - - default: - break - } - - if (task.datetime_started !== null) { - } - - items.push( - - ) - }) - - return {items} -} - -type ZoneButtonProps = { - start: boolean - disabled: boolean - zoneId: number -} - -const ZoneButton = (props: ZoneButtonProps) => { - const clickFun = props.start ? startZone : stopZone - - return ( - - ) -} - -type ZoneCardProps = { - zoneId: number - tasks?: Task[] - taskListCliTimestamp: number - taskListSrvTimestamp: number -} - -const ZoneCard = (props: ZoneCardProps) => { - const tasks = props.tasks === undefined ? [] : props.tasks - - let runningTask - let hasManualTask = false - - if (tasks.length > 0) { - if (tasks[0].datetime_started !== null) { - runningTask = tasks[0] - } - - tasks.forEach((task) => { - if (task.source === 0) { - hasManualTask = true - } - }) - } - - return ( - - - - Platz {props.zoneId} - - - - - - - - - - ) -} - -type Props = {} - -type State = { - wsConnected: boolean - taskList: TaskList - tasksByZone: {[key: number]: Task[]} - taskListTimestamp: number -} - -export default class Controls extends React.Component { - private cfg: Config - private ws?: WebsocketClient - - constructor(props: Props) { - super(props) - - this.cfg = getConfig() - - this.state = { - wsConnected: false, - taskList: new WebsocketMessage(), - tasksByZone: {}, - taskListTimestamp: getTimestamp(), - } - } - - private onWsStatusUpdate = (wsConnected: boolean) => { - this.setState({wsConnected: wsConnected}) - } - - private onWsMessage = (msg: TaskList, date: Date) => { - const tbz: {[key: number]: Task[]} = {} - msg.tasks.forEach((task) => { - if (tbz[task.zone_id] === undefined) { - tbz[task.zone_id] = [] - } - tbz[task.zone_id].push(task) - }) - - this.setState({ - taskList: msg, - tasksByZone: tbz, - taskListTimestamp: dateToTimestamp(date), - }) - } - - componentDidMount() { - this.ws = new WebsocketClient(this.onWsStatusUpdate, this.onWsMessage) - this.setState({wsConnected: this.ws.api().isConnected()}) - } - - componentWillUnmount() { - if (this.ws !== undefined) { - this.ws.destroy() - } - } - - render() { - let cards = [] - for (let i = 1; i <= this.cfg.n_zones; i++) { - cards.push( - - - - ) - } - - return ( - - - {cards} - - - ) - } -} diff --git a/ui/src/components/DurationInput.tsx b/ui/src/components/DurationInput.tsx deleted file mode 100644 index 928d771..0000000 --- a/ui/src/components/DurationInput.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import * as React from "react" -import {TextField, TextFieldProps} from "@mui/material" - -import {parseTimeString, secondsToString} from "../util/functions" - -type Props = { - value: number - onChange: (newValue: number) => void - textFieldProps: TextFieldProps -} - -const DurationInput = (props: Props) => { - const [textValue, setTextValue] = React.useState(secondsToString(props.value)) - - const handleDurationUpdate = (e: React.ChangeEvent) => { - setTextValue(e.target.value) - props.onChange(parseTimeString(e.target.value)) - } - - const handleDurationBlur = (e: React.FocusEvent) => { - setTextValue(secondsToString(props.value)) - } - - return ( - 0)} - /> - ) -} - -export default DurationInput diff --git a/ui/src/components/Jobs.tsx b/ui/src/components/Jobs.tsx deleted file mode 100644 index 89955af..0000000 --- a/ui/src/components/Jobs.tsx +++ /dev/null @@ -1,409 +0,0 @@ -import * as React from "react" -import { - Box, - Card, - Chip, - CircularProgress, - Container, - Paper, - Table, - TableBody, - TableCell, - TableContainer, - TableHead, - TableRow, - IconButton, - Fab, - Button, - Dialog, - DialogActions, - DialogContent, - DialogTitle, - TextField, - FormControlLabel, - Checkbox, - Typography, -} from "@mui/material" -import { - Add as AddIcon, - Edit as EditIcon, - Delete as DeleteIcon, - Timer as PowerOnIcon, - TimerOff as PowerOffIcon, -} from "@mui/icons-material" -import {DateTimePicker, LocalizationProvider} from "@mui/lab" -import AdapterDateFns from "@mui/lab/AdapterDateFns" -import {de} from "date-fns/locale" - -import {Job} from "../tsgrain-client" -import {tsgrainApi} from "../util/apiUrls" -import { - dateToTimestamp, - getTimestamp, - handleApiError, - secondsToString, - timestampToString, -} from "../util/functions" -import {getConfig} from "../util/config" -import DurationInput from "./DurationInput" - -type ZoneSelectorProps = { - defaultSelection?: Set - onChange?: (selection: Set) => void -} - -function ZoneSelector(props: ZoneSelectorProps) { - const [selection, setSelection] = React.useState( - props.defaultSelection || new Set([]) - ) - - const handleChange = (zoneId: number) => { - const newSelection = new Set(selection) - if (newSelection.has(zoneId)) { - newSelection.delete(zoneId) - } else { - newSelection.add(zoneId) - } - - setSelection(newSelection) - if (props.onChange) { - props.onChange(newSelection) - } - } - - const nZones = getConfig().n_zones - let items: React.ReactElement[] = [] - - for (let i = 1; i <= nZones; i++) { - items.push( - } - checkedIcon={} - checked={selection.has(i)} - onChange={() => handleChange(i)} - /> - ) - } - - return ( - - Plätze - {items} - - ) -} - -type JobEditorProps = { - job: Job - jobEdit: (job: Job) => void - getBtn: (handleClickOpen: () => void) => React.ReactElement -} - -function JobEditor(props: JobEditorProps) { - const [open, setOpen] = React.useState(false) - - const [zones, setZones] = React.useState(new Set(props.job.zones)) - const [timestamp, setTimestamp] = React.useState(props.job.date) - const [datetimeInput, setDatetimeInput] = React.useState( - new Date((timestamp || 0) * 1000) - ) - const [duration, setDuration] = React.useState(props.job.duration) - const [repeat, setRepeat] = React.useState(props.job.repeat) - - const handleClickOpen = () => { - setOpen(true) - } - - const handleClose = () => { - setOpen(false) - } - - const handleOK = () => { - // Validate - if (zones.size === 0) { - return - } - if (timestamp === null) { - return - } - if (!(duration > 0)) { - return - } - - const job = props.job - job.zones = Array.from(zones) - job.date = timestamp - job.duration = duration - job.repeat = repeat - - props.jobEdit(job) - handleClose() - } - - const handleDateUpdate = (newValue: Date | null) => { - setDatetimeInput(newValue) - - if (newValue === null || isNaN(newValue.getTime())) { - setTimestamp(null) - } else { - setTimestamp(dateToTimestamp(newValue)) - } - } - - return ( - - {props.getBtn(handleClickOpen)} - - - Zeitplan {props.job.id > 0 ? "bearbeiten" : "erstellen"} - - - setZones(selection)} - /> - - ( - - )} - label="Datum/Zeit" - value={datetimeInput} - onChange={handleDateUpdate} - mask="__.__.____ __:__" - /> - - - setDuration(v)} - /> - - setRepeat(!repeat)} - /> - } - label="Täglich wiederholen" - /> - - - - - - - - ) -} - -type JobTableProps = { - jobs: Job[] - jobEdit: (job: Job) => void - jobDelete: (jobId: number) => void -} - -const JobTable = (props: JobTableProps) => { - return ( - - - - - Ein/Aus - Plätze - Datum/Zeit - Dauer - Wiederholen - Bearbeiten - - - - {props.jobs.map((job) => { - return ( - - - { - job.enable = !job.enable - props.jobEdit(job) - }} - > - {job.enable ? ( - - ) : ( - - )} - - - {job.zones.join(", ")} - {timestampToString(job.date)} - {secondsToString(job.duration)} - - {job.repeat ? ( - - ) : ( - - )} - - - ( - - - - )} - /> - props.jobDelete(job.id)} - > - - - - - ) - })} - -
-
- ) -} - -type JobsProps = {} - -type JobsState = { - loaded: boolean - jobs: Job[] -} - -export default class Jobs extends React.Component { - private updateTimeout: number | undefined - - constructor(props: JobsProps) { - super(props) - - this.state = { - loaded: false, - jobs: [], - } - } - - private clearUpdateTimeout = () => { - if (this.updateTimeout !== undefined) { - window.clearTimeout(this.updateTimeout) - } - } - - private updateJobs = () => { - this.clearUpdateTimeout() - this.setState({loaded: false}) - tsgrainApi - .getJobs() - .then((response) => { - this.setState({loaded: true, jobs: response.data}) - }) - .catch((reason) => { - console.log("error fetching info", reason) - this.updateTimeout = window.setTimeout(this.updateJobs, 3000) - }) - } - - private jobEdit = (job: Job) => { - tsgrainApi - .updateJob(job) - .then((response) => { - this.updateJobs() - }) - .catch(handleApiError) - } - - private jobCreate = (job: Job) => { - tsgrainApi - .createJob(job) - .then((response) => { - this.updateJobs() - }) - .catch(handleApiError) - } - - private jobDelete = (jobId: number) => { - tsgrainApi - .deleteJob({id: jobId}) - .then((response) => { - this.updateJobs() - }) - .catch(handleApiError) - } - - componentDidMount() { - this.updateJobs() - } - - componentWillUnmount() { - this.clearUpdateTimeout() - } - - render() { - return ( - - {this.state.loaded ? ( - - ) : ( - - - - - - )} - ( - - - - )} - /> - - ) - } -} diff --git a/ui/src/components/Navbar.tsx b/ui/src/components/Navbar.tsx deleted file mode 100644 index 1423e03..0000000 --- a/ui/src/components/Navbar.tsx +++ /dev/null @@ -1,124 +0,0 @@ -import * as React from "react" -import { - AppBar, - Box, - Toolbar, - IconButton, - Typography, - Menu, - Container, - Button, - MenuItem, - Switch, - FormControlLabel, -} from "@mui/material" -import MenuIcon from "@mui/icons-material/Menu" -import {useLocation} from "wouter" -import {getConfig} from "../util/config" -import AutoModeSwitch from "./AutoMode" - -const pages: {[key: string]: string} = { - Steuerung: "/", - Zeitpläne: "/jobs", - Einstellungen: "/settings", -} - -const Navbar = () => { - const [anchorElNav, setAnchorElNav] = React.useState(null) - const [location, setLocation] = useLocation() - - const handleOpenNavMenu = (event: React.MouseEvent) => { - setAnchorElNav(event.currentTarget) - } - - const handleCloseNavMenu = () => { - setAnchorElNav(null) - } - - const handleTabClick = (page: string) => { - setLocation(pages[page]) - handleCloseNavMenu() - } - - return ( - - - - {/* Desktop title */} - - TSGRain - - - - - - - - {Object.keys(pages).map((page) => ( - handleTabClick(page)} - > - {page} - - ))} - - - {/* Mobile title */} - - TSGRain - - - {Object.keys(pages).map((page) => ( - - ))} - - - - - - - - ) -} -export default Navbar diff --git a/ui/src/components/NoConnectionBar.tsx b/ui/src/components/NoConnectionBar.tsx deleted file mode 100644 index 90aa37b..0000000 --- a/ui/src/components/NoConnectionBar.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import * as React from "react" -import {Box, Typography} from "@mui/material" -import {WebsocketClient} from "../util/websocket" - -type Props = {} - -type State = { - wsConnected: boolean -} - -export default class NoConnectionBar extends React.Component { - private ws?: WebsocketClient - - constructor(props: Props) { - super(props) - - this.state = { - wsConnected: false, - } - } - - private onWsStatusUpdate = (wsConnected: boolean) => { - this.setState({wsConnected: wsConnected}) - } - - componentDidMount() { - this.ws = new WebsocketClient(this.onWsStatusUpdate) - this.setState({wsConnected: this.ws.api().isConnected()}) - } - - componentWillUnmount() { - if (this.ws !== undefined) { - this.ws.destroy() - } - } - - render() { - if (!this.state.wsConnected) { - return ( - - Keine Verbindung - - ) - } - return null - } -} diff --git a/ui/src/components/Settings.tsx b/ui/src/components/Settings.tsx deleted file mode 100644 index 0b2569b..0000000 --- a/ui/src/components/Settings.tsx +++ /dev/null @@ -1,315 +0,0 @@ -import * as React from "react" -import { - Box, - Button, - Card, - CardActions, - CardContent, - CircularProgress, - Container, - TextField, - Typography, -} from "@mui/material" -import {tsgrainApi} from "../util/apiUrls" -import { - dateToInputString, - dateToTimestamp, - handleApiError, - inputStringToDate, - timestampToDate, -} from "../util/functions" -import {getConfig} from "../util/config" -import DurationInput from "./DurationInput" - -type IrrigationSettingsProps = {} - -type IrrigationSettingsState = { - loaded: boolean - irrigationTime: number -} - -class IrrigationSettings extends React.Component< - IrrigationSettingsProps, - IrrigationSettingsState -> { - private updateTimeout?: number - private initialIrrigationTime?: number - - constructor(props: IrrigationSettingsProps) { - super(props) - - this.state = { - loaded: false, - irrigationTime: 0, - } - } - - private clearUpdateTimeout = () => { - if (this.updateTimeout !== undefined) { - window.clearTimeout(this.updateTimeout) - } - } - - private updateSettings = () => { - this.clearUpdateTimeout() - this.setState({loaded: false}) - - tsgrainApi - .getDefaultIrrigationTime() - .then((response) => { - this.initialIrrigationTime = response.data.time - - this.setState({ - loaded: true, - irrigationTime: this.initialIrrigationTime, - }) - }) - .catch((reason) => { - console.log("error fetching irrigation settings", reason) - this.updateTimeout = window.setTimeout(this.updateSettings, 3000) - }) - } - - private showSubmit(): boolean { - return ( - this.state.irrigationTime !== this.initialIrrigationTime && - this.state.irrigationTime > 0 - ) - } - - private submitSettings = () => { - const irrigationTime = this.state.irrigationTime - tsgrainApi - .setDefaultIrrigationTime({time: irrigationTime}) - .then((response) => { - this.setState({irrigationTime: irrigationTime}) - }) - .catch(handleApiError) - } - - componentDidMount() { - this.updateSettings() - } - - componentWillUnmount() { - this.clearUpdateTimeout() - } - - renderSettings() { - return ( - - - - Bewässerungssteuerung - - this.setState({irrigationTime: v})} - /> - - {this.showSubmit() ? ( - - - - ) : null} - - - ) - } - - render() { - if (this.state.loaded) return this.renderSettings() - - return ( - - - - - - ) - } -} - -type TimeSettingsProps = {} - -type TimeSettingsState = { - loaded: boolean - date: Date - dateStr: string - timezone: string -} - -class TimeSettings extends React.Component { - private updateTimeout?: number - private timerID?: number - - private initialDate?: Date - private initialTimezone?: string - - constructor(props: TimeSettingsProps) { - super(props) - - const now = new Date() - this.state = { - loaded: false, - date: now, - dateStr: dateToInputString(now), - timezone: "", - } - } - - private clearUpdateTimeout = () => { - if (this.updateTimeout !== undefined) { - window.clearTimeout(this.updateTimeout) - } - } - - private updateSettings = () => { - this.clearUpdateTimeout() - this.setState({loaded: false}) - - tsgrainApi - .getSystemTime() - .then((response) => { - this.initialDate = timestampToDate(response.data.time) - this.initialTimezone = response.data.timezone - - this.setState({ - loaded: true, - dateStr: dateToInputString(this.initialDate), - timezone: this.initialTimezone, - }) - - this.timerID = setInterval(this.tick, 1000) - }) - .catch((reason) => { - console.log("error fetching time settings", reason) - this.updateTimeout = window.setTimeout(this.updateSettings, 3000) - }) - } - - private tick = () => { - if (this.state.date !== null) { - const newDate = new Date(this.state.date.getTime() + 1000) - this.setState({ - date: newDate, - dateStr: dateToInputString(newDate), - }) - } - } - - private showSubmit(): boolean { - return ( - this.state.date !== this.initialDate || - this.state.timezone !== this.initialTimezone - ) - } - - private submitSettings = () => { - const date = this.state.date - if (date !== this.initialDate) { - tsgrainApi - .setSystemTime({time: dateToTimestamp(date)}) - .then((response) => { - this.updateSettings() - }) - .catch(handleApiError) - } - - const tz = this.state.timezone - if (tz !== this.initialTimezone) { - tsgrainApi - .setSystemTimezone({timezone: this.state.timezone}) - .then((response) => { - this.initialTimezone = tz - this.setState({timezone: tz}) - }) - .catch(handleApiError) - } - } - - componentDidMount() { - this.updateSettings() - } - - componentWillUnmount() { - this.clearUpdateTimeout() - clearInterval(this.timerID) - } - - renderSettings() { - return ( - - - Datum/Uhrzeit - - { - clearInterval(this.timerID) - this.setState({ - dateStr: e.target.value, - date: inputStringToDate(e.target.value), - }) - }} - /> - - this.setState({timezone: e.target.value})} - /> - - {this.showSubmit() ? ( - - - - ) : null} - - ) - } - - render() { - if (this.state.loaded) return this.renderSettings() - - return ( - - - - - - ) - } -} - -const Settings = () => { - return ( - - - - - TSGRain WebUI Version: {getConfig().version} - - - ) -} - -export default Settings diff --git a/ui/src/components/app.tsx b/ui/src/components/app.tsx new file mode 100644 index 0000000..3e0efc5 --- /dev/null +++ b/ui/src/components/app.tsx @@ -0,0 +1,10 @@ +import {Component} from "preact" +// import UpdaterView from "./Updater/UpdaterView" +// import logo from "../assets/logo.svg" +import {getConfig} from "../util/config" + +export default class App extends Component { + render() { + return
{getConfig().version}
+ } +} diff --git a/ui/src/main.tsx b/ui/src/main.tsx index eae102b..66f7e6b 100644 --- a/ui/src/main.tsx +++ b/ui/src/main.tsx @@ -1,17 +1,5 @@ -import * as React from "react" -import ReactDOM from "react-dom" -import {CssBaseline} from "@mui/material" -import {ThemeProvider} from "@mui/material/styles" -import App from "./App" -import theme from "./theme" +import {render} from "preact" +import App from "./components/app" +import "./style/index.scss" -ReactDOM.render( - - - {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */} - - - - , - document.getElementById("app") -) +render(, document.getElementById("app")!) diff --git a/ui/src/preact.d.ts b/ui/src/preact.d.ts new file mode 100644 index 0000000..ac79d62 --- /dev/null +++ b/ui/src/preact.d.ts @@ -0,0 +1 @@ +import JSX = preact.JSX diff --git a/ui/src/style/index.scss b/ui/src/style/index.scss new file mode 100644 index 0000000..e69de29 diff --git a/ui/src/theme.ts b/ui/src/theme.ts deleted file mode 100644 index bc1aba6..0000000 --- a/ui/src/theme.ts +++ /dev/null @@ -1,19 +0,0 @@ -import {createTheme} from "@mui/material/styles" -import {red} from "@mui/material/colors" - -// Create a theme instance. -const theme = createTheme({ - palette: { - primary: { - main: "#357a38", - }, - secondary: { - main: "#ff3d00", - }, - error: { - main: red.A400, - }, - }, -}) - -export default theme diff --git a/ui/src/tsgrain-client/.openapi-generator/FILES b/ui/src/tsgrain-client/.openapi-generator/FILES index a80cd4f..16b445e 100644 --- a/ui/src/tsgrain-client/.openapi-generator/FILES +++ b/ui/src/tsgrain-client/.openapi-generator/FILES @@ -1,5 +1,6 @@ .gitignore .npmignore +.openapi-generator-ignore api.ts base.ts common.ts diff --git a/ui/src/tsgrain-client/.openapi-generator/VERSION b/ui/src/tsgrain-client/.openapi-generator/VERSION index 1e20ec3..7d3cdbf 100644 --- a/ui/src/tsgrain-client/.openapi-generator/VERSION +++ b/ui/src/tsgrain-client/.openapi-generator/VERSION @@ -1 +1 @@ -5.4.0 \ No newline at end of file +5.3.1 \ No newline at end of file diff --git a/ui/src/tsgrain-client/api.ts b/ui/src/tsgrain-client/api.ts index 0f680cb..75fba97 100644 --- a/ui/src/tsgrain-client/api.ts +++ b/ui/src/tsgrain-client/api.ts @@ -50,6 +50,25 @@ export interface AutoMode { */ state: boolean } +/** + * Aktuelle Systemzeit/Zeitzone + * @export + * @interface ConfigTime + */ +export interface ConfigTime { + /** + * Aktuelle Systemzeit + * @type {number} + * @memberof ConfigTime + */ + time: number + /** + * Aktuelle Zeitzone + * @type {string} + * @memberof ConfigTime + */ + timezone: string +} /** * Manuelle Bewässerungszeit in Sekunden * @export @@ -63,6 +82,50 @@ export interface DefaultIrrigationTime { */ time: number } +/** + * + * @export + * @interface InlineObject + */ +export interface InlineObject { + /** + * + * @type {boolean} + * @memberof InlineObject + */ + state: boolean +} +/** + * + * @export + * @interface InlineObject1 + */ +export interface InlineObject1 { + /** + * Aufgabe stoppen/aus der Warteschlange entfernen, wenn sie bereits läuft oder sich in der Warteschlange befindet. + * @type {boolean} + * @memberof InlineObject1 + */ + cancelling: boolean + /** + * Bewässerungsdauer in Sekunden (0: Standarddauer) + * @type {number} + * @memberof InlineObject1 + */ + duration: number + /** + * Aufgabe in die Warteschlange einreihen, wenn sie nicht sofort ausgeführt werden kann. + * @type {boolean} + * @memberof InlineObject1 + */ + queuing: boolean + /** + * Nummer der Bewässerungszone + * @type {number} + * @memberof InlineObject1 + */ + zone_id: number +} /** * Job stellt einen Bewässerungszeitplan dar. * @export @@ -200,25 +263,6 @@ export interface StatusMessage { */ success: boolean } -/** - * Aktuelle Systemzeit/Zeitzone - * @export - * @interface SystemTime - */ -export interface SystemTime { - /** - * Aktuelle Systemzeit - * @type {number} - * @memberof SystemTime - */ - time: number - /** - * Aktuelle Zeitzone - * @type {string} - * @memberof SystemTime - */ - timezone: string -} /** * Task stellt eine Bewässerungsaufgabe dar. * @export @@ -282,43 +326,23 @@ export interface TaskList { tasks: Array } /** - * Zeitstempel + * TaskRequestResult wird beim Starten eines Tasks zurückgegeben * @export - * @interface Timestamp + * @interface TaskRequestResult */ -export interface Timestamp { +export interface TaskRequestResult { /** * - * @type {number} - * @memberof Timestamp + * @type {boolean} + * @memberof TaskRequestResult */ - time: number -} -/** - * Systemzeitzone - * @export - * @interface Timezone - */ -export interface Timezone { + Started?: boolean /** * - * @type {string} - * @memberof Timezone + * @type {boolean} + * @memberof TaskRequestResult */ - timezone: string -} -/** - * - * @export - * @interface ZoneID - */ -export interface ZoneID { - /** - * - * @type {number} - * @memberof ZoneID - */ - id?: number + Stopped?: boolean } /** @@ -376,12 +400,12 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati /** * * @summary Lösche einen gespeicherten Zeitplan. - * @param {JobID} [jobId] JobID + * @param {number} [id] * @param {*} [options] Override http request option. * @throws {RequiredError} */ deleteJob: async ( - jobId?: JobID, + id?: number, options: AxiosRequestConfig = {} ): Promise => { const localVarPath = `/job` @@ -411,7 +435,7 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati ...options.headers, } localVarRequestOptions.data = serializeDataIfNeeded( - jobId, + id, localVarRequestOptions, configuration ) @@ -454,6 +478,40 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati options: localVarRequestOptions, } }, + /** + * Rufe die aktuelle Systemzeit/Zeitzone ab + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getConfigTime: async ( + options: AxiosRequestConfig = {} + ): Promise => { + const localVarPath = `/config/time` + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL) + let baseOptions + if (configuration) { + baseOptions = configuration.baseOptions + } + + const localVarRequestOptions = {method: "GET", ...baseOptions, ...options} + const localVarHeaderParameter = {} as any + const localVarQueryParameter = {} as any + + setSearchParams(localVarUrlObj, localVarQueryParameter) + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {} + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + } + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + } + }, /** * * @summary Rufe die Standardzeit bei manueller Bewässerung ab. @@ -565,81 +623,14 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati options: localVarRequestOptions, } }, - /** - * Rufe die aktuelle Systemzeit/Zeitzone ab - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getSystemTime: async ( - options: AxiosRequestConfig = {} - ): Promise => { - const localVarPath = `/config/time` - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL) - let baseOptions - if (configuration) { - baseOptions = configuration.baseOptions - } - - const localVarRequestOptions = {method: "GET", ...baseOptions, ...options} - const localVarHeaderParameter = {} as any - const localVarQueryParameter = {} as any - - setSearchParams(localVarUrlObj, localVarQueryParameter) - let headersFromBaseOptions = - baseOptions && baseOptions.headers ? baseOptions.headers : {} - localVarRequestOptions.headers = { - ...localVarHeaderParameter, - ...headersFromBaseOptions, - ...options.headers, - } - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - } - }, - /** - * - * @summary Rufe alle momentan laufenden Bewässerungsaufgaben ab. - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getTasks: async (options: AxiosRequestConfig = {}): Promise => { - const localVarPath = `/tasks` - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL) - let baseOptions - if (configuration) { - baseOptions = configuration.baseOptions - } - - const localVarRequestOptions = {method: "GET", ...baseOptions, ...options} - const localVarHeaderParameter = {} as any - const localVarQueryParameter = {} as any - - setSearchParams(localVarUrlObj, localVarQueryParameter) - let headersFromBaseOptions = - baseOptions && baseOptions.headers ? baseOptions.headers : {} - localVarRequestOptions.headers = { - ...localVarHeaderParameter, - ...headersFromBaseOptions, - ...options.headers, - } - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - } - }, /** * Automatikmodus aktivieren/deaktivieren - * @param {AutoMode} [state] Zustand des Automatikmodus + * @param {InlineObject} [state] * @param {*} [options] Override http request option. * @throws {RequiredError} */ setAutoMode: async ( - state?: AutoMode, + state?: InlineObject, options: AxiosRequestConfig = {} ): Promise => { const localVarPath = `/config/auto` @@ -675,6 +666,49 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati options: localVarRequestOptions, } }, + /** + * Automatikmodus aktivieren/deaktivieren + * @param {ConfigTime} [configTime] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + setConfigTime: async ( + configTime?: ConfigTime, + options: AxiosRequestConfig = {} + ): Promise => { + const localVarPath = `/config/time` + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL) + let baseOptions + if (configuration) { + baseOptions = configuration.baseOptions + } + + const localVarRequestOptions = {method: "POST", ...baseOptions, ...options} + const localVarHeaderParameter = {} as any + const localVarQueryParameter = {} as any + + localVarHeaderParameter["Content-Type"] = "application/json" + + setSearchParams(localVarUrlObj, localVarQueryParameter) + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {} + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + } + localVarRequestOptions.data = serializeDataIfNeeded( + configTime, + localVarRequestOptions, + configuration + ) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + } + }, /** * * @summary Setze die die Standardzeit bei manueller Bewässerung. @@ -720,16 +754,16 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati } }, /** - * Systemzeit einstellen - * @param {Timestamp} [timestamp] + * Starte/stoppe manuell eine neue Bewässerungsaufgabe + * @param {InlineObject1} [taskRequest] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - setSystemTime: async ( - timestamp?: Timestamp, + startManualTask: async ( + taskRequest?: InlineObject1, options: AxiosRequestConfig = {} ): Promise => { - const localVarPath = `/config/time` + const localVarPath = `/task/manual` // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL) let baseOptions @@ -752,137 +786,7 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati ...options.headers, } localVarRequestOptions.data = serializeDataIfNeeded( - timestamp, - localVarRequestOptions, - configuration - ) - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - } - }, - /** - * Systemzeitzone einstellen - * @param {Timezone} [timezone] - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - setSystemTimezone: async ( - timezone?: Timezone, - options: AxiosRequestConfig = {} - ): Promise => { - const localVarPath = `/config/timezone` - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL) - let baseOptions - if (configuration) { - baseOptions = configuration.baseOptions - } - - const localVarRequestOptions = {method: "POST", ...baseOptions, ...options} - const localVarHeaderParameter = {} as any - const localVarQueryParameter = {} as any - - localVarHeaderParameter["Content-Type"] = "application/json" - - setSearchParams(localVarUrlObj, localVarQueryParameter) - let headersFromBaseOptions = - baseOptions && baseOptions.headers ? baseOptions.headers : {} - localVarRequestOptions.headers = { - ...localVarHeaderParameter, - ...headersFromBaseOptions, - ...options.headers, - } - localVarRequestOptions.data = serializeDataIfNeeded( - timezone, - localVarRequestOptions, - configuration - ) - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - } - }, - /** - * Starte eine neue manuelle Bewässerungsaufgabe mit der eingestellten Standardzeit. - * @param {ZoneID} [zoneId] ZoneID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - startTask: async ( - zoneId?: ZoneID, - options: AxiosRequestConfig = {} - ): Promise => { - const localVarPath = `/task/start` - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL) - let baseOptions - if (configuration) { - baseOptions = configuration.baseOptions - } - - const localVarRequestOptions = {method: "POST", ...baseOptions, ...options} - const localVarHeaderParameter = {} as any - const localVarQueryParameter = {} as any - - localVarHeaderParameter["Content-Type"] = "application/json" - - setSearchParams(localVarUrlObj, localVarQueryParameter) - let headersFromBaseOptions = - baseOptions && baseOptions.headers ? baseOptions.headers : {} - localVarRequestOptions.headers = { - ...localVarHeaderParameter, - ...headersFromBaseOptions, - ...options.headers, - } - localVarRequestOptions.data = serializeDataIfNeeded( - zoneId, - localVarRequestOptions, - configuration - ) - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - } - }, - /** - * - * @summary Stoppe eine manuelle Bewässerungsaufgabe. - * @param {ZoneID} [zoneId] ZoneID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - stopTask: async ( - zoneId?: ZoneID, - options: AxiosRequestConfig = {} - ): Promise => { - const localVarPath = `/task/stop` - // use dummy base URL string because the URL constructor only accepts absolute URLs. - const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL) - let baseOptions - if (configuration) { - baseOptions = configuration.baseOptions - } - - const localVarRequestOptions = {method: "POST", ...baseOptions, ...options} - const localVarHeaderParameter = {} as any - const localVarQueryParameter = {} as any - - localVarHeaderParameter["Content-Type"] = "application/json" - - setSearchParams(localVarUrlObj, localVarQueryParameter) - let headersFromBaseOptions = - baseOptions && baseOptions.headers ? baseOptions.headers : {} - localVarRequestOptions.headers = { - ...localVarHeaderParameter, - ...headersFromBaseOptions, - ...options.headers, - } - localVarRequestOptions.data = serializeDataIfNeeded( - zoneId, + taskRequest, localVarRequestOptions, configuration ) @@ -973,18 +877,18 @@ export const DefaultApiFp = function (configuration?: Configuration) { /** * * @summary Lösche einen gespeicherten Zeitplan. - * @param {JobID} [jobId] JobID + * @param {number} [id] * @param {*} [options] Override http request option. * @throws {RequiredError} */ async deleteJob( - jobId?: JobID, + id?: number, options?: AxiosRequestConfig ): Promise< (axios?: AxiosInstance, basePath?: string) => AxiosPromise > { const localVarAxiosArgs = await localVarAxiosParamCreator.deleteJob( - jobId, + id, options ) return createRequestFunction( @@ -1015,6 +919,26 @@ export const DefaultApiFp = function (configuration?: Configuration) { configuration ) }, + /** + * Rufe die aktuelle Systemzeit/Zeitzone ab + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getConfigTime( + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.getConfigTime( + options + ) + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ) + }, /** * * @summary Rufe die Standardzeit bei manueller Bewässerung ab. @@ -1080,16 +1004,19 @@ export const DefaultApiFp = function (configuration?: Configuration) { ) }, /** - * Rufe die aktuelle Systemzeit/Zeitzone ab + * Automatikmodus aktivieren/deaktivieren + * @param {InlineObject} [state] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getSystemTime( + async setAutoMode( + state?: InlineObject, options?: AxiosRequestConfig ): Promise< - (axios?: AxiosInstance, basePath?: string) => AxiosPromise + (axios?: AxiosInstance, basePath?: string) => AxiosPromise > { - const localVarAxiosArgs = await localVarAxiosParamCreator.getSystemTime( + const localVarAxiosArgs = await localVarAxiosParamCreator.setAutoMode( + state, options ) return createRequestFunction( @@ -1099,39 +1026,20 @@ export const DefaultApiFp = function (configuration?: Configuration) { configuration ) }, - /** - * - * @summary Rufe alle momentan laufenden Bewässerungsaufgaben ab. - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async getTasks( - options?: AxiosRequestConfig - ): Promise< - (axios?: AxiosInstance, basePath?: string) => AxiosPromise - > { - const localVarAxiosArgs = await localVarAxiosParamCreator.getTasks(options) - return createRequestFunction( - localVarAxiosArgs, - globalAxios, - BASE_PATH, - configuration - ) - }, /** * Automatikmodus aktivieren/deaktivieren - * @param {AutoMode} [state] Zustand des Automatikmodus + * @param {ConfigTime} [configTime] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async setAutoMode( - state?: AutoMode, + async setConfigTime( + configTime?: ConfigTime, options?: AxiosRequestConfig ): Promise< (axios?: AxiosInstance, basePath?: string) => AxiosPromise > { - const localVarAxiosArgs = await localVarAxiosParamCreator.setAutoMode( - state, + const localVarAxiosArgs = await localVarAxiosParamCreator.setConfigTime( + configTime, options ) return createRequestFunction( @@ -1167,89 +1075,19 @@ export const DefaultApiFp = function (configuration?: Configuration) { ) }, /** - * Systemzeit einstellen - * @param {Timestamp} [timestamp] + * Starte/stoppe manuell eine neue Bewässerungsaufgabe + * @param {InlineObject1} [taskRequest] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async setSystemTime( - timestamp?: Timestamp, + async startManualTask( + taskRequest?: InlineObject1, options?: AxiosRequestConfig ): Promise< (axios?: AxiosInstance, basePath?: string) => AxiosPromise > { - const localVarAxiosArgs = await localVarAxiosParamCreator.setSystemTime( - timestamp, - options - ) - return createRequestFunction( - localVarAxiosArgs, - globalAxios, - BASE_PATH, - configuration - ) - }, - /** - * Systemzeitzone einstellen - * @param {Timezone} [timezone] - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async setSystemTimezone( - timezone?: Timezone, - options?: AxiosRequestConfig - ): Promise< - (axios?: AxiosInstance, basePath?: string) => AxiosPromise - > { - const localVarAxiosArgs = await localVarAxiosParamCreator.setSystemTimezone( - timezone, - options - ) - return createRequestFunction( - localVarAxiosArgs, - globalAxios, - BASE_PATH, - configuration - ) - }, - /** - * Starte eine neue manuelle Bewässerungsaufgabe mit der eingestellten Standardzeit. - * @param {ZoneID} [zoneId] ZoneID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async startTask( - zoneId?: ZoneID, - options?: AxiosRequestConfig - ): Promise< - (axios?: AxiosInstance, basePath?: string) => AxiosPromise - > { - const localVarAxiosArgs = await localVarAxiosParamCreator.startTask( - zoneId, - options - ) - return createRequestFunction( - localVarAxiosArgs, - globalAxios, - BASE_PATH, - configuration - ) - }, - /** - * - * @summary Stoppe eine manuelle Bewässerungsaufgabe. - * @param {ZoneID} [zoneId] ZoneID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async stopTask( - zoneId?: ZoneID, - options?: AxiosRequestConfig - ): Promise< - (axios?: AxiosInstance, basePath?: string) => AxiosPromise - > { - const localVarAxiosArgs = await localVarAxiosParamCreator.stopTask( - zoneId, + const localVarAxiosArgs = await localVarAxiosParamCreator.startManualTask( + taskRequest, options ) return createRequestFunction( @@ -1312,13 +1150,13 @@ export const DefaultApiFactory = function ( /** * * @summary Lösche einen gespeicherten Zeitplan. - * @param {JobID} [jobId] JobID + * @param {number} [id] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - deleteJob(jobId?: JobID, options?: any): AxiosPromise { + deleteJob(id?: number, options?: any): AxiosPromise { return localVarFp - .deleteJob(jobId, options) + .deleteJob(id, options) .then((request) => request(axios, basePath)) }, /** @@ -1332,6 +1170,16 @@ export const DefaultApiFactory = function ( .getAutoMode(options) .then((request) => request(axios, basePath)) }, + /** + * Rufe die aktuelle Systemzeit/Zeitzone ab + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getConfigTime(options?: any): AxiosPromise { + return localVarFp + .getConfigTime(options) + .then((request) => request(axios, basePath)) + }, /** * * @summary Rufe die Standardzeit bei manueller Bewässerung ab. @@ -1367,35 +1215,28 @@ export const DefaultApiFactory = function ( .then((request) => request(axios, basePath)) }, /** - * Rufe die aktuelle Systemzeit/Zeitzone ab + * Automatikmodus aktivieren/deaktivieren + * @param {InlineObject} [state] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getSystemTime(options?: any): AxiosPromise { + setAutoMode(state?: InlineObject, options?: any): AxiosPromise { return localVarFp - .getSystemTime(options) - .then((request) => request(axios, basePath)) - }, - /** - * - * @summary Rufe alle momentan laufenden Bewässerungsaufgaben ab. - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getTasks(options?: any): AxiosPromise { - return localVarFp - .getTasks(options) + .setAutoMode(state, options) .then((request) => request(axios, basePath)) }, /** * Automatikmodus aktivieren/deaktivieren - * @param {AutoMode} [state] Zustand des Automatikmodus + * @param {ConfigTime} [configTime] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - setAutoMode(state?: AutoMode, options?: any): AxiosPromise { + setConfigTime( + configTime?: ConfigTime, + options?: any + ): AxiosPromise { return localVarFp - .setAutoMode(state, options) + .setConfigTime(configTime, options) .then((request) => request(axios, basePath)) }, /** @@ -1414,54 +1255,17 @@ export const DefaultApiFactory = function ( .then((request) => request(axios, basePath)) }, /** - * Systemzeit einstellen - * @param {Timestamp} [timestamp] + * Starte/stoppe manuell eine neue Bewässerungsaufgabe + * @param {InlineObject1} [taskRequest] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - setSystemTime( - timestamp?: Timestamp, + startManualTask( + taskRequest?: InlineObject1, options?: any ): AxiosPromise { return localVarFp - .setSystemTime(timestamp, options) - .then((request) => request(axios, basePath)) - }, - /** - * Systemzeitzone einstellen - * @param {Timezone} [timezone] - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - setSystemTimezone( - timezone?: Timezone, - options?: any - ): AxiosPromise { - return localVarFp - .setSystemTimezone(timezone, options) - .then((request) => request(axios, basePath)) - }, - /** - * Starte eine neue manuelle Bewässerungsaufgabe mit der eingestellten Standardzeit. - * @param {ZoneID} [zoneId] ZoneID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - startTask(zoneId?: ZoneID, options?: any): AxiosPromise { - return localVarFp - .startTask(zoneId, options) - .then((request) => request(axios, basePath)) - }, - /** - * - * @summary Stoppe eine manuelle Bewässerungsaufgabe. - * @param {ZoneID} [zoneId] ZoneID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - stopTask(zoneId?: ZoneID, options?: any): AxiosPromise { - return localVarFp - .stopTask(zoneId, options) + .startManualTask(taskRequest, options) .then((request) => request(axios, basePath)) }, /** @@ -1503,14 +1307,14 @@ export class DefaultApi extends BaseAPI { /** * * @summary Lösche einen gespeicherten Zeitplan. - * @param {JobID} [jobId] JobID + * @param {number} [id] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApi */ - public deleteJob(jobId?: JobID, options?: AxiosRequestConfig) { + public deleteJob(id?: number, options?: AxiosRequestConfig) { return DefaultApiFp(this.configuration) - .deleteJob(jobId, options) + .deleteJob(id, options) .then((request) => request(this.axios, this.basePath)) } @@ -1527,6 +1331,18 @@ export class DefaultApi extends BaseAPI { .then((request) => request(this.axios, this.basePath)) } + /** + * Rufe die aktuelle Systemzeit/Zeitzone ab + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public getConfigTime(options?: AxiosRequestConfig) { + return DefaultApiFp(this.configuration) + .getConfigTime(options) + .then((request) => request(this.axios, this.basePath)) + } + /** * * @summary Rufe die Standardzeit bei manueller Bewässerung ab. @@ -1568,40 +1384,28 @@ export class DefaultApi extends BaseAPI { } /** - * Rufe die aktuelle Systemzeit/Zeitzone ab + * Automatikmodus aktivieren/deaktivieren + * @param {InlineObject} [state] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApi */ - public getSystemTime(options?: AxiosRequestConfig) { + public setAutoMode(state?: InlineObject, options?: AxiosRequestConfig) { return DefaultApiFp(this.configuration) - .getSystemTime(options) - .then((request) => request(this.axios, this.basePath)) - } - - /** - * - * @summary Rufe alle momentan laufenden Bewässerungsaufgaben ab. - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof DefaultApi - */ - public getTasks(options?: AxiosRequestConfig) { - return DefaultApiFp(this.configuration) - .getTasks(options) + .setAutoMode(state, options) .then((request) => request(this.axios, this.basePath)) } /** * Automatikmodus aktivieren/deaktivieren - * @param {AutoMode} [state] Zustand des Automatikmodus + * @param {ConfigTime} [configTime] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApi */ - public setAutoMode(state?: AutoMode, options?: AxiosRequestConfig) { + public setConfigTime(configTime?: ConfigTime, options?: AxiosRequestConfig) { return DefaultApiFp(this.configuration) - .setAutoMode(state, options) + .setConfigTime(configTime, options) .then((request) => request(this.axios, this.basePath)) } @@ -1623,55 +1427,15 @@ export class DefaultApi extends BaseAPI { } /** - * Systemzeit einstellen - * @param {Timestamp} [timestamp] + * Starte/stoppe manuell eine neue Bewässerungsaufgabe + * @param {InlineObject1} [taskRequest] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApi */ - public setSystemTime(timestamp?: Timestamp, options?: AxiosRequestConfig) { + public startManualTask(taskRequest?: InlineObject1, options?: AxiosRequestConfig) { return DefaultApiFp(this.configuration) - .setSystemTime(timestamp, options) - .then((request) => request(this.axios, this.basePath)) - } - - /** - * Systemzeitzone einstellen - * @param {Timezone} [timezone] - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof DefaultApi - */ - public setSystemTimezone(timezone?: Timezone, options?: AxiosRequestConfig) { - return DefaultApiFp(this.configuration) - .setSystemTimezone(timezone, options) - .then((request) => request(this.axios, this.basePath)) - } - - /** - * Starte eine neue manuelle Bewässerungsaufgabe mit der eingestellten Standardzeit. - * @param {ZoneID} [zoneId] ZoneID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof DefaultApi - */ - public startTask(zoneId?: ZoneID, options?: AxiosRequestConfig) { - return DefaultApiFp(this.configuration) - .startTask(zoneId, options) - .then((request) => request(this.axios, this.basePath)) - } - - /** - * - * @summary Stoppe eine manuelle Bewässerungsaufgabe. - * @param {ZoneID} [zoneId] ZoneID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof DefaultApi - */ - public stopTask(zoneId?: ZoneID, options?: AxiosRequestConfig) { - return DefaultApiFp(this.configuration) - .stopTask(zoneId, options) + .startManualTask(taskRequest, options) .then((request) => request(this.axios, this.basePath)) } diff --git a/ui/src/util/apiUrls.ts b/ui/src/util/apiUrls.ts index 36ecca4..cceed04 100644 --- a/ui/src/util/apiUrls.ts +++ b/ui/src/util/apiUrls.ts @@ -15,6 +15,6 @@ let apicfg = new Configuration({ basePath: apiUrl, }) -const tsgrainApi = new DefaultApi(apicfg) +const sebraucApi = new DefaultApi(apicfg) -export {apiUrl, wsUrl, tsgrainApi} +export {apiUrl, wsUrl, sebraucApi} diff --git a/ui/src/util/config.ts b/ui/src/util/config.ts index d9f27a7..f5950c2 100644 --- a/ui/src/util/config.ts +++ b/ui/src/util/config.ts @@ -19,8 +19,9 @@ export function getConfig(): Config { return window.config } + console.error("App config not found") return { version: "dev", - n_zones: 7, + n_zones: 0, } } diff --git a/ui/src/util/functions.ts b/ui/src/util/functions.ts index 1b8f912..18179e2 100644 --- a/ui/src/util/functions.ts +++ b/ui/src/util/functions.ts @@ -1,120 +1,18 @@ -import {format, parse, parseISO} from "date-fns" - -const S_YEAR = 31536000 -const S_DAY = 86400 -const S_HOUR = 3600 -const S_MIN = 60 - function secondsToString(seconds: number): string { - const numyears = Math.floor(seconds / S_YEAR) - const numdays = Math.floor((seconds % S_YEAR) / S_DAY) - const numhours = Math.floor(((seconds % S_YEAR) % S_DAY) / S_HOUR) - const numminutes = Math.floor((((seconds % S_YEAR) % S_DAY) % S_HOUR) / S_MIN) - const numseconds = (((seconds % S_YEAR) % S_DAY) % S_HOUR) % S_MIN + const numyears = Math.floor(seconds / 31536000) + const numdays = Math.floor((seconds % 31536000) / 86400) + const numhours = Math.floor(((seconds % 31536000) % 86400) / 3600) + const numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60) + const numseconds = (((seconds % 31536000) % 86400) % 3600) % 60 let res = [] if (numyears > 0) res.push(numyears + "yr") if (numdays > 0) res.push(numdays + "d") if (numhours > 0) res.push(numhours + "h") if (numminutes > 0) res.push(numminutes + "m") - if (numseconds > 0 || res.length === 0) res.push(numseconds + "s") + if (seconds < 60) res.push(numseconds + "s") return res.join(" ") } -function parseTimeString(timeString: string): number { - const parts = timeString.split(/[ ,;]/) - let seconds = 0 - const regexpPart = /^(\d+)\s*(?:([yjdthms])|$)/i - - parts.forEach((part) => { - const match = part.match(regexpPart) - if (match) { - const n = parseInt(match[1]) - const unit = match[2] === undefined ? "" : match[2].toLowerCase() - - switch (unit) { - case "y": - case "j": - seconds += n * S_YEAR - break - case "d": - case "t": - seconds += n * S_DAY - break - case "h": - seconds += n * S_HOUR - break - case "m": - seconds += n * S_MIN - break - case "s": - seconds += n - break - default: - if (seconds === 0) seconds += n * S_MIN - else seconds += n - break - } - } - }) - - return seconds -} - -function getTimestamp(): number { - return Math.round(Date.now() / 1000) -} - -function timestampToDate(timestamp: number): Date { - return new Date(timestamp * 1000) -} - -function dateToTimestamp(date: Date): number { - return Math.round(date.getTime() / 1000) -} - -function timestampToString(timestamp: number): string { - return dateToString(timestampToDate(timestamp)) -} - -function dateToString(date: Date): string { - return date.toLocaleString("de-DE") -} - -const INPUT_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss" - -function dateToInputString(date: Date): string { - return format(date, INPUT_DATE_FORMAT) -} - -function inputStringToDate(inputString: string): Date { - return parseISO(inputString) -} - -function handleApiError(error: any) { - if (error.response) { - const msg = error.response.data.msg - - if (msg !== undefined) { - alert("Error: " + msg) - } else { - alert("Error: no response") - } - } else { - alert(String(error)) - } -} - -export { - secondsToString, - parseTimeString, - getTimestamp, - timestampToDate, - dateToTimestamp, - timestampToString, - dateToString, - dateToInputString, - inputStringToDate, - handleApiError, -} +export {secondsToString} diff --git a/ui/src/util/websocket.ts b/ui/src/util/websocket.ts index 56d5f60..8d75673 100644 --- a/ui/src/util/websocket.ts +++ b/ui/src/util/websocket.ts @@ -1,19 +1,10 @@ -import {Task, TaskList} from "../tsgrain-client" -import {tsgrainApi, wsUrl} from "./apiUrls" - -class WebsocketMessage implements TaskList { - auto_mode = false - now = 0 - tasks: Task[] = [] -} +import {wsUrl} from "./apiUrls" class WebsocketAPI { - private static ws?: WebsocketAPI + private static ws: WebsocketAPI | undefined - private conn?: WebSocket + private conn: WebSocket | undefined private wsConnected: boolean - private lastMessage?: WebsocketMessage - private lastMessageDate?: Date private clients: Set @@ -49,24 +40,10 @@ class WebsocketAPI { window.setTimeout(() => this.connect(), 3000) } this.conn.onmessage = (evt) => { - const msg = Object.assign(new WebsocketMessage(), JSON.parse(evt.data)) - this.broadcastMsg(msg) + this.clients.forEach((client) => { + client.msgCallback(evt) + }) } - - // Get initial state via REST api - tsgrainApi.getTasks().then((response) => { - this.broadcastMsg(response.data) - }) - } - - private broadcastMsg(msg: WebsocketMessage) { - const date = new Date() - this.lastMessage = msg - this.lastMessageDate = date - - this.clients.forEach((client) => { - client.msgCallback(msg, date) - }) } static Get(): WebsocketAPI { @@ -81,28 +58,26 @@ class WebsocketAPI { } addClient(client: WebsocketClient) { + console.log("added client", client) this.clients.add(client) - - if (this.lastMessage !== undefined && this.lastMessageDate !== undefined) { - client.msgCallback(this.lastMessage, this.lastMessageDate) - } } removeClient(client: WebsocketClient) { + console.log("removed client", client) this.clients.delete(client) } } -class WebsocketClient { +export default class WebsocketClient { statusCallback: (wsConnected: boolean) => void - msgCallback: (msg: WebsocketMessage, date: Date) => void + msgCallback: (evt: MessageEvent) => void constructor( - statusCallback?: (wsConnected: boolean) => void, - msgCallback?: (msg: WebsocketMessage, date: Date) => void + statusCallback: (wsConnected: boolean) => void, + msgCallback: (evt: MessageEvent) => void ) { - this.statusCallback = statusCallback || ((con) => {}) - this.msgCallback = msgCallback || ((msg, date) => {}) + this.statusCallback = statusCallback + this.msgCallback = msgCallback this.api().addClient(this) } @@ -115,5 +90,3 @@ class WebsocketClient { this.api().removeClient(this) } } - -export {WebsocketMessage, WebsocketClient} diff --git a/ui/src/vite-env.ts b/ui/src/vite-env.d.ts similarity index 77% rename from ui/src/vite-env.ts rename to ui/src/vite-env.d.ts index 714c59c..11f02fe 100644 --- a/ui/src/vite-env.ts +++ b/ui/src/vite-env.d.ts @@ -1,3 +1 @@ /// - -export {} diff --git a/ui/tsconfig.json b/ui/tsconfig.json index bcf685d..dd76ca6 100644 --- a/ui/tsconfig.json +++ b/ui/tsconfig.json @@ -14,6 +14,8 @@ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, - "jsx": "preserve" + "jsx": "preserve", + "jsxFactory": "h", + "jsxFragmentFactory": "Fragment" } } diff --git a/ui/vite.config.js b/ui/vite.config.ts similarity index 53% rename from ui/vite.config.js rename to ui/vite.config.ts index 46785b9..80a2f42 100644 --- a/ui/vite.config.js +++ b/ui/vite.config.ts @@ -1,7 +1,7 @@ import {defineConfig} from "vite" -import reactRefresh from "@vitejs/plugin-react-refresh" +import preact from "@preact/preset-vite" // https://vitejs.dev/config/ export default defineConfig({ - plugins: [reactRefresh()], + plugins: [preact()], })