Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions frontend/src/global_styles/openproject.sass
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
@import "../../../modules/documents/app/components/_index.sass"
@import "../../../modules/gitlab_integration/app/components/_index.sass"
@import "../../../modules/grids/app/components/_index.sass"
@import "../../../modules/llm/app/components/_index.sass"
@import "../../../modules/meeting/app/components/_index.sass"
@import "../../../modules/overviews/app/components/_index.sass"
@import "../../../modules/resource_management/app/components/_index.sass"
Expand Down
1 change: 1 addition & 0 deletions modules/llm/app/components/_index.sass
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@import "llm_connections/semantic_indexes/box_component"
Original file line number Diff line number Diff line change
Expand Up @@ -33,52 +33,26 @@ See COPYRIGHT and LICENSE files for more details.
<%= render(Primer::Beta::Text.new(tag: :p, color: :muted, mb: 2)) { feature.caption } %>
<% end %>

<% if dangling? %>
<%= render(Primer::Alpha::Banner.new(scheme: :warning, mb: 2, icon: :alert)) do %>
<%= t("admin.llm_feature_bindings.dangling", model: binding.resolved_model_id) %>
<% end %>
<% end %>

<% if locked? %>
<%= render(Primer::Alpha::Banner.new(scheme: :warning, mb: 2, icon: :lock)) do %>
<%= t("admin.llm_feature_bindings.locked", model: binding.model_id) %>
<% unless feature.embedding? %>
<% if dangling? %>
<%= render(Primer::Alpha::Banner.new(scheme: :warning, mb: 2, icon: :alert)) do %>
<%= t("admin.llm_feature_bindings.dangling", model: binding.resolved_model_id) %>
<% end %>
<% end %>
<% end %>

<%= primer_form_with(model: form_model, url: form_url, method: :patch, scope: :llm_feature_binding) do |f| %>
<%= render(
LlmConnections::FeatureBindingForm.new(
f,
options: model_options,
inherit_label:,
feature_key: feature.key,
locked: locked?,
embedding: feature.embedding?,
models_left_out: models_left_out?,
selected_model_id: binding&.model_id,
dimensions_hint: probed_dimensions
)
) %>
<% end %>

<% if locked? && feature.embedding? %>
<%# Rendered as text rather than disabled inputs: a disabled input submits
nothing, so the values would arrive blank and wipe the columns. %>
<%= render(Primer::Beta::Text.new(tag: :p, font_weight: :bold, mt: 2, mb: 1)) do %>
<%= t("admin.llm_feature_bindings.locked_values_heading") %>
<% end %>
<% locked_values.each do |label, value| %>
<%= render(Primer::Beta::Text.new(tag: :p, color: :muted, mb: 0)) do %>
<%= "#{label}: #{value}" %>
<% end %>
<%= primer_form_with(model: form_model, url: form_url, method: :patch, scope: :llm_feature_binding) do |f| %>
<%= render(
LlmConnections::FeatureBindingForm.new(
f,
options: model_options,
inherit_label:,
feature_key: feature.key,
models_left_out: models_left_out?,
selected_model_id: binding&.model_id
)
) %>
<% end %>
<% end %>

<% if feature.embedding? %>
<%= button_to t("admin.work_package_embeddings.reindex.button"),
reindex_work_package_embeddings_path,
method: :post,
class: "Button Button--secondary Button--small mt-3" %>
<%= render(LlmConnections::IndexingStatusComponent.new) %>
<% end %>
<%= content %>
<% end %>
Original file line number Diff line number Diff line change
Expand Up @@ -63,28 +63,8 @@ def inherit_label
end
end

def locked? = binding&.locked?

def dangling? = binding&.dangling?

# What the embeddings probe last saw, offered as information. Never filled
# into the field: the server decides the vector size at index time.
def probed_dimensions
return unless feature.embedding?

model_id = binding&.resolved_model_id
return if model_id.blank?

connection.capability_verdicts.for_model(model_id).for_capability(:embeddings).first&.dimensions
end

def locked_values
[
[LlmFeatureBinding.human_attribute_name(:model_id), binding.model_id],
[LlmFeatureBinding.human_attribute_name(:dimensions), binding.dimensions || "—"]
]
end

private

attr_reader :feature, :connection, :binding
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) the OpenProject GmbH

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 3.

OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
Copyright (C) 2006-2013 Jean-Philippe Lang
Copyright (C) 2010-2013 the ChiliProject Team

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

See COPYRIGHT and LICENSE files for more details.

++#%>

<%=
render(
Primer::Alpha::Dialog.new(
title: t("admin.semantic_indexes.activate.title", title: semantic_index.title),
size: :medium,
id: DIALOG_ID,
test_selector: DIALOG_ID
)
) do |d|
d.with_header(variant: :large)

d.with_body do
form_with(url: activate_semantic_index_path(semantic_index), method: :post, id: FORM_ID) do
render(Primer::Beta::Text.new(tag: :p)) { body }
end
end

d.with_footer do
component_collection do |buttons|
buttons.with_component(Primer::Beta::Button.new(data: { close_dialog_id: DIALOG_ID })) do
t(:button_cancel)
end

buttons.with_component(
Primer::Beta::Button.new(
scheme: :primary,
form: FORM_ID,
type: :submit,
test_selector: "llm-semantic-index--activate-submit"
)
) do
t("admin.semantic_indexes.activate.confirm")
end
end
end
end
%>
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# frozen_string_literal: true

#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++

module LlmConnections
module SemanticIndexes
class ActivateDialogComponent < ApplicationComponent
include OpTurbo::Streamable
include OpPrimer::ComponentHelpers

DIALOG_ID = "llm-semantic-index-activate-dialog"
FORM_ID = "llm-semantic-index-activate-form"

alias_method :semantic_index, :model

options :current

private

def body
if current
t("admin.semantic_indexes.activate.body_switch_html", current: current.title, title: semantic_index.title)
else
t("admin.semantic_indexes.activate.body_html", title: semantic_index.title)
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -27,31 +27,57 @@ See COPYRIGHT and LICENSE files for more details.

++#%>

<%= render(Primer::Box.new(border: true, border_radius: 2, p: 3, mb: 3, test_selector: "llm-semantic-index--box")) do %>
<%=
flex_layout(justify_content: :space_between, align_items: :flex_start, mb: 3) do |header|
header.with_column do
concat(render(Primer::Beta::Text.new(tag: :h3, font_size: 4, font_weight: :bold, mb: 1)) { t("admin.semantic_indexes.box.title") })
concat(render(Primer::Beta::Text.new(tag: :p, color: :muted, mb: 0)) { t("admin.semantic_indexes.box.caption") })
end
<%= component_wrapper(**wrapper_data_attrs) do %>
<%= render(Primer::Box.new(mt: 4, test_selector: "llm-semantic-index--box")) do %>
<%=
flex_layout(justify_content: :space_between, align_items: :flex_start, mb: 3) do |header|
header.with_column do
concat(render(Primer::Beta::Text.new(tag: :h4, font_weight: :bold, mb: 1)) { t("admin.semantic_indexes.box.title") })
concat(render(Primer::Beta::Text.new(tag: :p, color: :muted, mb: 0)) { t("admin.semantic_indexes.box.caption") })
end

header.with_column(ml: 3) do
render(
Primer::Beta::Button.new(
scheme: :primary,
size: :small,
tag: :a,
href: new_dialog_semantic_indexes_path,
data: { controller: "async-dialog" },
test_selector: "llm-semantic-index--new-button"
)
) do |button|
button.with_leading_visual_icon(icon: :plus)
t("admin.semantic_indexes.box.new")
header.with_column(ml: 3) do
render(
Primer::Beta::Button.new(
scheme: :primary,
size: :small,
tag: :a,
href: new_dialog_semantic_indexes_path,
data: { controller: "async-dialog" },
test_selector: "llm-semantic-index--new-button"
)
) do |button|
button.with_leading_visual_icon(icon: :plus)
t("admin.semantic_indexes.box.new")
end
end
end
end
%>
%>

<% if active_semantic_index %>
<%= render(Primer::Box.new(mb: 4, classes: "op-semantic-index-active-card", test_selector: "llm-semantic-index--active")) do %>
<%=
flex_layout(
justify_content: :space_between, align_items: :center, flex_wrap: :wrap,
px: 3, py: 2, classes: "op-semantic-index-active-card--header"
) do |header|
header.with_column(font_weight: :bold) do
concat(render(Primer::Beta::Octicon.new(icon: :"check-circle-fill", mr: 2)))
concat(t("admin.semantic_indexes.box.active_heading"))
end
header.with_column(font_size: :small) { t("admin.semantic_indexes.box.active_caption") }
end
%>
<%= render(LlmConnections::SemanticIndexes::TableComponent.new(rows: [active_semantic_index], active: true)) %>
<% end %>
<% else %>
<%= render(Primer::Box.new(mb: 4, test_selector: "llm-semantic-index--no-active")) do %>
<%= render(LlmConnections::SemanticIndexes::TableComponent.new(rows: [], active: true)) %>
<% end %>
<% end %>

<%= render(LlmConnections::SemanticIndexes::TableComponent.new(rows: semantic_indexes)) %>
<% if other_semantic_indexes.any? %>
<%= render(LlmConnections::SemanticIndexes::TableComponent.new(rows: other_semantic_indexes)) %>
<% end %>
<% end %>
<% end %>
Loading
Loading