diff --git a/app/graphql/types/flow_disabled_reason_enum.rb b/app/graphql/types/flow_disabled_reason_enum.rb new file mode 100644 index 00000000..6e011e9c --- /dev/null +++ b/app/graphql/types/flow_disabled_reason_enum.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Types + class FlowDisabledReasonEnum < Types::BaseEnum + description 'The disabled reason of a flow.' + + Flow::DISABLED_REASON.each do |reason, settings| + value reason.upcase, settings[:description], value: reason.to_s + end + end +end diff --git a/app/graphql/types/flow_type.rb b/app/graphql/types/flow_type.rb index 05281d66..0da105f7 100644 --- a/app/graphql/types/flow_type.rb +++ b/app/graphql/types/flow_type.rb @@ -8,6 +8,10 @@ class FlowType < Types::BaseObject field :name, String, null: false, description: 'Name of the flow' + field :disabled_reason, Types::FlowDisabledReasonEnum, + null: true, + description: 'The reason why the flow is disabled, if it is disabled' + field :validation_status, Types::FlowValidationStatusEnum, null: false, description: 'The validation status of the flow' diff --git a/app/models/flow.rb b/app/models/flow.rb index c6026139..8697628e 100644 --- a/app/models/flow.rb +++ b/app/models/flow.rb @@ -7,11 +7,16 @@ class Flow < ApplicationRecord invalid: 2, }.with_indifferent_access + DISABLED_REASON = { + _dummy: { db: 0, description: 'Dummy value' }, # temporary until the first real disabled reason gets introduced + }.with_indifferent_access + belongs_to :project, class_name: 'NamespaceProject' belongs_to :flow_type belongs_to :starting_node, class_name: 'NodeFunction', optional: true enum :validation_status, VALIDATION_STATUS, prefix: :validation_status + enum :disabled_reason, DISABLED_REASON.transform_values { |v| v[:db] }, prefix: :disabled_reason has_many :flow_settings, class_name: 'FlowSetting', inverse_of: :flow has_many :node_functions, class_name: 'NodeFunction', inverse_of: :flow @@ -25,6 +30,12 @@ class Flow < ApplicationRecord in: VALIDATION_STATUS.keys.map(&:to_s), } + validates :disabled_reason, + inclusion: { + in: DISABLED_REASON.keys.map(&:to_s), + }, + if: :disabled? + validates :name, presence: true, allow_blank: false, uniqueness: { case_sensitive: false, scope: :project_id } @@ -32,6 +43,13 @@ class Flow < ApplicationRecord validates :input_type, length: { maximum: 2000 }, allow_nil: true validates :return_type, length: { maximum: 2000 }, allow_nil: true + scope :enabled, -> { where(disabled_reason: nil) } + scope :disabled, -> { where.not(disabled_reason: nil) } + + def disabled? + disabled_reason.present? + end + def to_grpc Tucana::Shared::ValidationFlow.new( flow_id: id, @@ -39,6 +57,7 @@ def to_grpc project_slug: project.slug, type: flow_type.identifier, data_types: [], # TODO: when data types are creatable + disable_reason: disabled_reason, input_type: input_type, return_type: return_type, settings: flow_settings.map(&:to_grpc), diff --git a/db/migrate/20260328152854_add_disabled_reason_to_flows.rb b/db/migrate/20260328152854_add_disabled_reason_to_flows.rb new file mode 100644 index 00000000..594f9b2f --- /dev/null +++ b/db/migrate/20260328152854_add_disabled_reason_to_flows.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddDisabledReasonToFlows < Code0::ZeroTrack::Database::Migration[1.0] + def change + add_column :flows, :disabled_reason, :integer, null: true + end +end diff --git a/db/schema_migrations/20260328152854 b/db/schema_migrations/20260328152854 new file mode 100644 index 00000000..9aaa898b --- /dev/null +++ b/db/schema_migrations/20260328152854 @@ -0,0 +1 @@ +a75b8ec7e9c47f5967a2f4b3fc2ffb6870f850479132b0fb7c0f64eb951a5cb8 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 47bcfce1..9ba1ed98 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -304,6 +304,7 @@ CREATE TABLE flows ( input_type text, return_type text, validation_status integer DEFAULT 0 NOT NULL, + disabled_reason integer, CONSTRAINT check_1c805d704f CHECK ((char_length(input_type) <= 2000)), CONSTRAINT check_b2f3f83908 CHECK ((char_length(return_type) <= 2000)) ); diff --git a/docs/graphql/enum/flowdisabledreason.md b/docs/graphql/enum/flowdisabledreason.md new file mode 100644 index 00000000..d534931e --- /dev/null +++ b/docs/graphql/enum/flowdisabledreason.md @@ -0,0 +1,9 @@ +--- +title: FlowDisabledReason +--- + +The disabled reason of a flow. + +| Value | Description | +|-------|-------------| +| `_DUMMY` | Dummy value | diff --git a/docs/graphql/object/flow.md b/docs/graphql/object/flow.md index a1740544..7fd6fd73 100644 --- a/docs/graphql/object/flow.md +++ b/docs/graphql/object/flow.md @@ -9,6 +9,7 @@ Represents a flow | Name | Type | Description | |------|------|-------------| | `createdAt` | [`Time!`](../scalar/time.md) | Time when this Flow was created | +| `disabledReason` | [`FlowDisabledReason`](../enum/flowdisabledreason.md) | The reason why the flow is disabled, if it is disabled | | `id` | [`FlowID!`](../scalar/flowid.md) | Global ID of this Flow | | `inputType` | [`String`](../scalar/string.md) | The input data type of the flow | | `linkedDataTypes` | [`DataTypeConnection!`](../object/datatypeconnection.md) | The data types that are referenced in this flow | diff --git a/spec/models/flow_spec.rb b/spec/models/flow_spec.rb index b8017ae3..1f6ba842 100644 --- a/spec/models/flow_spec.rb +++ b/spec/models/flow_spec.rb @@ -21,6 +21,8 @@ describe 'validations' do it { is_expected.to allow_values(*described_class::VALIDATION_STATUS.keys).for(:validation_status) } + it { is_expected.to allow_values(nil, *described_class::DISABLED_REASON.keys).for(:disabled_reason) } + it { is_expected.to validate_presence_of(:name) } it { is_expected.to validate_uniqueness_of(:name).case_insensitive.scoped_to(:project_id) } @@ -47,6 +49,7 @@ flow_type: create(:flow_type, identifier: 'HTTP'), input_type: 'string', return_type: 'number', + disabled_reason: 0, flow_settings: [ create( :flow_setting, @@ -131,6 +134,7 @@ }, } ], + disable_reason: '_dummy', } ) end