diff --git a/openc3-cosmos-cmd-tlm-api/app/controllers/timeline_controller.rb b/openc3-cosmos-cmd-tlm-api/app/controllers/timeline_controller.rb index 12806d161..358f897cc 100644 --- a/openc3-cosmos-cmd-tlm-api/app/controllers/timeline_controller.rb +++ b/openc3-cosmos-cmd-tlm-api/app/controllers/timeline_controller.rb @@ -133,7 +133,55 @@ def color return end begin - model.update_color(color: params['color']) + # Model color=(value) method handles the color validation + model.color = params['color'] + model.update() + model.notify(kind: 'updated') + render json: model.as_json(:allow_nan => true) + rescue RuntimeError, JSON::ParserError => e + log_error(e) + render json: { status: 'error', message: e.message, type: e.class }, status: 400 + rescue TypeError => e + log_error(e) + render json: { status: 'error', message: 'Invalid json object', type: e.class }, status: 400 + rescue OpenC3::TimelineInputError => e + log_error(e) + render json: { status: 'error', message: e.message, type: e.class }, status: 400 + end + end + + # Set the timeline execution status + # + # name [String] the timeline name, `system42` + # scope [String] the scope of the timeline, `TEST` + # json [String] The json of the timeline name (see below) + # @return [String] the timeline converted into json format + # Request Headers + #```json + # { + # "Authorization": "token/password", + # "Content-Type": "application/json" + # } + #``` + # Request Post Body + #```json + # { + # "enable": "false" + # } + #``` + def execute + return unless authorization('script_run') + model = @model_class.get(name: params[:name], scope: params[:scope]) + if model.nil? + render json: { + status: 'error', + message: "failed to find timeline: #{params[:name]}", + }, status: 404 + return + end + begin + # Model execute=(value) method handles the conversion of the string to a boolean + model.execute = params['enable'] model.update() model.notify(kind: 'updated') render json: model.as_json(:allow_nan => true) diff --git a/openc3-cosmos-cmd-tlm-api/config/routes.rb b/openc3-cosmos-cmd-tlm-api/config/routes.rb index 3684c667a..c97d94bc9 100644 --- a/openc3-cosmos-cmd-tlm-api/config/routes.rb +++ b/openc3-cosmos-cmd-tlm-api/config/routes.rb @@ -87,6 +87,7 @@ resources :timeline, only: [:index, :create] get '/timeline/:name', to: 'timeline#show', name: /[^\/]+/ post '/timeline/:name/color', to: 'timeline#color', name: /[^\/]+/ + post '/timeline/:name/execute', to: 'timeline#execute', name: /[^\/]+/ delete '/timeline/:name', to: 'timeline#destroy', name: /[^\/]+/ post '/timeline/activities/create', to: 'activity#multi_create' diff --git a/openc3-cosmos-cmd-tlm-api/spec/controllers/timeline_controller_spec.rb b/openc3-cosmos-cmd-tlm-api/spec/controllers/timeline_controller_spec.rb index e87b5099c..37b75406c 100644 --- a/openc3-cosmos-cmd-tlm-api/spec/controllers/timeline_controller_spec.rb +++ b/openc3-cosmos-cmd-tlm-api/spec/controllers/timeline_controller_spec.rb @@ -88,6 +88,26 @@ end end + describe "POST execute" do + it "returns a json hash of name and status code 200" do + post :create, params: {"scope"=>"DEFAULT", "name" => "test"} + expect(response).to have_http_status(:created) + json = JSON.parse(response.body, :allow_nan => true, :create_additions => true) + expect(json["name"]).to eql("test") + expect(json["execute"]).to be true + post :execute, params: {"scope"=>"DEFAULT", "name"=>"test", "enable" => "FALSE"} + expect(response).to have_http_status(:ok) + json = JSON.parse(response.body, :allow_nan => true, :create_additions => true) + expect(json["name"]).to eql("test") + expect(json["execute"]).to be false + post :execute, params: {"scope"=>"DEFAULT", "name"=>"test", "enable" => "true"} + expect(response).to have_http_status(:ok) + json = JSON.parse(response.body, :allow_nan => true, :create_additions => true) + expect(json["name"]).to eql("test") + expect(json["execute"]).to be true + end + end + describe "POST error" do it "returns a hash and status code 400" do post :create, params: {"scope"=>"DEFAULT"} diff --git a/openc3/lib/openc3/models/timeline_model.rb b/openc3/lib/openc3/models/timeline_model.rb index 4a237b30d..082360ecc 100644 --- a/openc3/lib/openc3/models/timeline_model.rb +++ b/openc3/lib/openc3/models/timeline_model.rb @@ -24,6 +24,7 @@ require 'openc3/models/activity_model' require 'openc3/models/microservice_model' require 'openc3/topics/timeline_topic' +require 'openc3/config/config_parser' module OpenC3 class TimelineError < StandardError; end @@ -31,6 +32,8 @@ class TimelineError < StandardError; end class TimelineInputError < TimelineError; end class TimelineModel < Model + attr_reader :execute + PRIMARY_KEY = 'openc3_timelines'.freeze # MUST be equal to ActivityModel::PRIMARY_KEY without leading __ KEY = '__TIMELINE__'.freeze @@ -74,7 +77,7 @@ def self.from_json(json, name:, scope:) self.new(**json.transform_keys(&:to_sym), name: name, scope: scope) end - def initialize(name:, scope:, updated_at: nil, color: nil, shard: 0) + def initialize(name:, scope:, updated_at: nil, color: nil, shard: 0, execute: true) if name.nil? || scope.nil? raise TimelineInputError.new "name or scope must not be nil" end @@ -83,10 +86,11 @@ def initialize(name:, scope:, updated_at: nil, color: nil, shard: 0) @updated_at = updated_at @timeline_name = name @shard = shard.to_i # to_i to handle nil - update_color(color: color) + self.color = color + self.execute = execute end - def update_color(color: nil) + def color=(color) if color.nil? color = '#%06x' % (rand * 0xffffff) end @@ -100,11 +104,16 @@ def update_color(color: nil) @color = color end + def execute=(value) + @execute = ConfigParser.handle_true_false(value) + end + # @return [Hash] generated from the TimelineModel def as_json(*a) { 'name' => @timeline_name, 'color' => @color, + 'execute' => @execute, 'shard' => @shard, 'scope' => @scope, 'updated_at' => @updated_at