diff --git a/app/assets/stylesheets/administrate/base/_forms.scss b/app/assets/stylesheets/administrate/base/_forms.scss
index bf014a746cc6..dcf535b58fe6 100644
--- a/app/assets/stylesheets/administrate/base/_forms.scss
+++ b/app/assets/stylesheets/administrate/base/_forms.scss
@@ -24,14 +24,6 @@ select {
font-size: $base-font-size;
}
-input,
-select,
-textarea {
- display: block;
- font-family: $base-font-family;
- font-size: 16px;
-}
-
[type="color"],
[type="date"],
[type="datetime-local"],
@@ -51,6 +43,7 @@ textarea {
background-color: $white;
border: $base-border;
border-radius: $base-border-radius;
+ font-family: $base-font-family;
padding: 0.5em;
transition: border-color $base-duration $base-timing;
width: 100%;
diff --git a/app/assets/stylesheets/administrate/components/_attributes.scss b/app/assets/stylesheets/administrate/components/_attributes.scss
index 713d9f523a8b..2b2936650a1d 100644
--- a/app/assets/stylesheets/administrate/components/_attributes.scss
+++ b/app/assets/stylesheets/administrate/components/_attributes.scss
@@ -4,8 +4,8 @@
float: left;
margin-bottom: $base-spacing;
margin-top: 0.25em;
- text-align: right;
- width: calc(15% - 1rem);
+ text-align: left;
+ width: calc(16% - 1rem);
}
.preserve-whitespace {
@@ -17,7 +17,7 @@
float: left;
margin-bottom: $base-spacing;
margin-left: 2rem;
- width: calc(85% - 1rem);
+ width: calc(84% - 1rem);
}
.attribute--nested {
diff --git a/app/assets/stylesheets/administrate/components/_buttons.scss b/app/assets/stylesheets/administrate/components/_buttons.scss
index 3e021e6584f5..7b2f6204515d 100644
--- a/app/assets/stylesheets/administrate/components/_buttons.scss
+++ b/app/assets/stylesheets/administrate/components/_buttons.scss
@@ -10,7 +10,7 @@ input[type="submit"],
color: $white;
cursor: pointer;
display: inline-block;
- font-size: $font-size-default;
+ font-size: $font-size-small;
-webkit-font-smoothing: antialiased;
font-weight: $font-weight-medium;
line-height: 1;
diff --git a/app/assets/stylesheets/administrate/components/_main-content.scss b/app/assets/stylesheets/administrate/components/_main-content.scss
index d03229828ae9..590bb098565c 100644
--- a/app/assets/stylesheets/administrate/components/_main-content.scss
+++ b/app/assets/stylesheets/administrate/components/_main-content.scss
@@ -1,13 +1,18 @@
.main-content {
font-size: $font-size-default;
- left: 23rem;
+ left: 21rem;
position: absolute;
right: 0;
top: 0;
}
.main-content__body {
+ font-size: $font-size-small;
padding: $space-two;
+
+ table {
+ font-size: $font-size-small;
+ }
}
.main-content__header {
@@ -20,7 +25,7 @@
}
.main-content__page-title {
- font-size: $font-size-large;
+ font-size: $font-size-medium;
font-weight: $font-weight-medium;
margin-right: auto;
}
diff --git a/app/assets/stylesheets/administrate/components/_navigation.scss b/app/assets/stylesheets/administrate/components/_navigation.scss
index 1e7e35d257cd..4ffc421903a9 100644
--- a/app/assets/stylesheets/administrate/components/_navigation.scss
+++ b/app/assets/stylesheets/administrate/components/_navigation.scss
@@ -1,7 +1,12 @@
.logo-brand {
margin-bottom: $space-normal;
padding: $space-normal $space-smaller $space-small;
- text-align: center;
+ text-align: left;
+
+ img {
+ margin-bottom: $space-smaller;
+ max-height: 3rem;
+ }
}
.navigation {
@@ -19,12 +24,13 @@
padding: $space-normal;
position: fixed;
top: 0;
- width: 23rem;
+ width: 21rem;
z-index: 1023;
li {
align-items: center;
display: flex;
+ font-size: $font-size-small;
a {
color: $color-gray;
@@ -35,6 +41,10 @@
min-width: $space-medium;
}
}
+
+ hr {
+ margin: $space-slab;
+ }
}
.navigation__link {
@@ -43,7 +53,7 @@
display: block;
line-height: 1;
margin-bottom: $space-smaller;
- padding: $space-one;
+ padding: $space-small;
&:hover {
color: $blue;
diff --git a/app/assets/stylesheets/administrate/library/_variables.scss b/app/assets/stylesheets/administrate/library/_variables.scss
index 5bb3c0710787..08642855603a 100644
--- a/app/assets/stylesheets/administrate/library/_variables.scss
+++ b/app/assets/stylesheets/administrate/library/_variables.scss
@@ -4,7 +4,7 @@ $base-font-family: PlusJakarta, Inter, -apple-system, BlinkMacSystemFont, "Segoe
sans-serif !default;
$heading-font-family: $base-font-family !default;
-$base-font-size: 16px !default;
+$base-font-size: 14px !default;
$base-line-height: 1.5 !default;
$heading-line-height: 1.2 !default;
diff --git a/app/views/super_admin/application/_navigation.html.erb b/app/views/super_admin/application/_navigation.html.erb
index 4e2a675bcc14..b85c0262359c 100644
--- a/app/views/super_admin/application/_navigation.html.erb
+++ b/app/views/super_admin/application/_navigation.html.erb
@@ -40,7 +40,7 @@ as defined by the routes in the `admin/` namespace
<% Administrate::Namespace.new(namespace).resources.each do |resource| %>
- <% next if ["account_users", "dashboard", "devise/sessions", "app_configs", "instance_statuses" ].include? resource.resource %>
+ <% next if ["account_users", "dashboard", "devise/sessions", "app_configs", "instance_statuses", "responses", "response_sources", "response_documents" ].include? resource.resource %>
<%= link_to(
@@ -50,6 +50,25 @@ as defined by the routes in the `admin/` namespace
<% end %>
+ <% if InstallationConfig.find_by(name: 'DEPLOYMENT_ENV')&.value == 'cloud' || Rails.env.development? %>
+
+
+
+ <%= link_to "Sources", super_admin_response_sources_url %>
+
+
+
+
+ <%= link_to "Documents", super_admin_response_documents_url %>
+
+
+
+
+ <%= link_to "Responses", super_admin_responses_url %>
+
+
+ <% end %>
+
<%= link_to "Instance Health", super_admin_instance_status_url %>
diff --git a/config/routes.rb b/config/routes.rb
index 75a300957166..7a347943901f 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -424,6 +424,9 @@
end
resources :access_tokens, only: [:index, :show]
+ resources :response_sources, only: [:index, :show, :new, :create, :edit, :update, :destroy]
+ resources :response_documents, only: [:index, :show, :new, :create, :edit, :update, :destroy]
+ resources :responses, only: [:index, :show, :new, :create, :edit, :update, :destroy]
resources :installation_configs, only: [:index, :new, :create, :show, :edit, :update]
resources :agent_bots, only: [:index, :new, :create, :show, :edit, :update] do
delete :avatar, on: :member, action: :destroy_avatar
diff --git a/enterprise/app/controllers/super_admin/response_documents_controller.rb b/enterprise/app/controllers/super_admin/response_documents_controller.rb
new file mode 100644
index 000000000000..f1317785addb
--- /dev/null
+++ b/enterprise/app/controllers/super_admin/response_documents_controller.rb
@@ -0,0 +1,44 @@
+class SuperAdmin::ResponseDocumentsController < SuperAdmin::ApplicationController
+ # Overwrite any of the RESTful controller actions to implement custom behavior
+ # For example, you may want to send an email after a foo is updated.
+ #
+ # def update
+ # super
+ # send_foo_updated_email(requested_resource)
+ # end
+
+ # Override this method to specify custom lookup behavior.
+ # This will be used to set the resource for the `show`, `edit`, and `update`
+ # actions.
+ #
+ # def find_resource(param)
+ # Foo.find_by!(slug: param)
+ # end
+
+ # The result of this lookup will be available as `requested_resource`
+
+ # Override this if you have certain roles that require a subset
+ # this will be used to set the records shown on the `index` action.
+ #
+ # def scoped_resource
+ # if current_user.super_admin?
+ # resource_class
+ # else
+ # resource_class.with_less_stuff
+ # end
+ # end
+
+ # Override `resource_params` if you want to transform the submitted
+ # data before it's persisted. For example, the following would turn all
+ # empty values into nil values. It uses other APIs such as `resource_class`
+ # and `dashboard`:
+ #
+ # def resource_params
+ # params.require(resource_class.model_name.param_key).
+ # permit(dashboard.permitted_attributes(action_name)).
+ # transform_values { |value| value == "" ? nil : value }
+ # end
+
+ # See https://administrate-demo.herokuapp.com/customizing_controller_actions
+ # for more information
+end
diff --git a/enterprise/app/controllers/super_admin/response_sources_controller.rb b/enterprise/app/controllers/super_admin/response_sources_controller.rb
new file mode 100644
index 000000000000..a0e9399138f9
--- /dev/null
+++ b/enterprise/app/controllers/super_admin/response_sources_controller.rb
@@ -0,0 +1,44 @@
+class SuperAdmin::ResponseSourcesController < SuperAdmin::ApplicationController
+ # Overwrite any of the RESTful controller actions to implement custom behavior
+ # For example, you may want to send an email after a foo is updated.
+ #
+ # def update
+ # super
+ # send_foo_updated_email(requested_resource)
+ # end
+
+ # Override this method to specify custom lookup behavior.
+ # This will be used to set the resource for the `show`, `edit`, and `update`
+ # actions.
+ #
+ # def find_resource(param)
+ # Foo.find_by!(slug: param)
+ # end
+
+ # The result of this lookup will be available as `requested_resource`
+
+ # Override this if you have certain roles that require a subset
+ # this will be used to set the records shown on the `index` action.
+ #
+ # def scoped_resource
+ # if current_user.super_admin?
+ # resource_class
+ # else
+ # resource_class.with_less_stuff
+ # end
+ # end
+
+ # Override `resource_params` if you want to transform the submitted
+ # data before it's persisted. For example, the following would turn all
+ # empty values into nil values. It uses other APIs such as `resource_class`
+ # and `dashboard`:
+ #
+ # def resource_params
+ # params.require(resource_class.model_name.param_key).
+ # permit(dashboard.permitted_attributes(action_name)).
+ # transform_values { |value| value == "" ? nil : value }
+ # end
+
+ # See https://administrate-demo.herokuapp.com/customizing_controller_actions
+ # for more information
+end
diff --git a/enterprise/app/controllers/super_admin/responses_controller.rb b/enterprise/app/controllers/super_admin/responses_controller.rb
new file mode 100644
index 000000000000..7566c8df3b3a
--- /dev/null
+++ b/enterprise/app/controllers/super_admin/responses_controller.rb
@@ -0,0 +1,44 @@
+class SuperAdmin::ResponsesController < SuperAdmin::ApplicationController
+ # Overwrite any of the RESTful controller actions to implement custom behavior
+ # For example, you may want to send an email after a foo is updated.
+ #
+ # def update
+ # super
+ # send_foo_updated_email(requested_resource)
+ # end
+
+ # Override this method to specify custom lookup behavior.
+ # This will be used to set the resource for the `show`, `edit`, and `update`
+ # actions.
+ #
+ # def find_resource(param)
+ # Foo.find_by!(slug: param)
+ # end
+
+ # The result of this lookup will be available as `requested_resource`
+
+ # Override this if you have certain roles that require a subset
+ # this will be used to set the records shown on the `index` action.
+ #
+ # def scoped_resource
+ # if current_user.super_admin?
+ # resource_class
+ # else
+ # resource_class.with_less_stuff
+ # end
+ # end
+
+ # Override `resource_params` if you want to transform the submitted
+ # data before it's persisted. For example, the following would turn all
+ # empty values into nil values. It uses other APIs such as `resource_class`
+ # and `dashboard`:
+ #
+ # def resource_params
+ # params.require(resource_class.model_name.param_key).
+ # permit(dashboard.permitted_attributes(action_name)).
+ # transform_values { |value| value == "" ? nil : value }
+ # end
+
+ # See https://administrate-demo.herokuapp.com/customizing_controller_actions
+ # for more information
+end
diff --git a/enterprise/app/dashboards/response_dashboard.rb b/enterprise/app/dashboards/response_dashboard.rb
new file mode 100644
index 000000000000..ca6fe9405a2b
--- /dev/null
+++ b/enterprise/app/dashboards/response_dashboard.rb
@@ -0,0 +1,74 @@
+require 'administrate/base_dashboard'
+
+class ResponseDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ id: Field::Number.with_options(searchable: true),
+ account: Field::BelongsToSearch.with_options(class_name: 'Account', searchable_field: [:name, :id], order: 'id DESC'),
+ answer: Field::Text.with_options(searchable: true),
+ question: Field::String.with_options(searchable: true),
+ response_document: Field::BelongsToSearch.with_options(class_name: 'ResponseDocument', searchable_field: [:document_link, :content, :id],
+ order: 'id DESC'),
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = %i[
+ id
+ question
+ answer
+ response_document
+ account
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = %i[
+ id
+ question
+ answer
+ response_document
+ account
+ created_at
+ updated_at
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = %i[
+ question
+ answer
+ response_document
+ account
+ ].freeze
+
+ # COLLECTION_FILTERS
+ # a hash that defines filters that can be used while searching via the search
+ # field of the dashboard.
+ #
+ # For example to add an option to search for open resources by typing "open:"
+ # in the search field:
+ #
+ # COLLECTION_FILTERS = {
+ # open: ->(resources) { resources.where(open: true) }
+ # }.freeze
+ COLLECTION_FILTERS = {}.freeze
+
+ # Overwrite this method to customize how responses are displayed
+ # across all pages of the admin dashboard.
+ #
+ def display_resource(response)
+ "Response: ##{response.id} - #{response.question}"
+ end
+end
diff --git a/enterprise/app/dashboards/response_document_dashboard.rb b/enterprise/app/dashboards/response_document_dashboard.rb
new file mode 100644
index 000000000000..d29b977b9b74
--- /dev/null
+++ b/enterprise/app/dashboards/response_document_dashboard.rb
@@ -0,0 +1,81 @@
+require 'administrate/base_dashboard'
+
+class ResponseDocumentDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ id: Field::Number.with_options(searchable: true),
+ account: Field::BelongsToSearch.with_options(class_name: 'Account', searchable_field: [:name, :id], order: 'id DESC'),
+ content: Field::Text.with_options(searchable: true),
+ document_id: Field::Number,
+ document_link: Field::String.with_options(searchable: true),
+ document_type: Field::String,
+ response_source: Field::BelongsToSearch.with_options(class_name: 'ResponseSource', searchable_field: [:name, :id, :source_link],
+ order: 'id DESC'),
+ responses: Field::HasMany,
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = %i[
+ id
+ account
+ response_source
+ document_link
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = %i[
+ id
+ account
+ content
+ document_id
+ document_link
+ document_type
+ response_source
+ created_at
+ updated_at
+ responses
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = %i[
+ account
+ content
+ document_id
+ document_link
+ document_type
+ response_source
+ ].freeze
+
+ # COLLECTION_FILTERS
+ # a hash that defines filters that can be used while searching via the search
+ # field of the dashboard.
+ #
+ # For example to add an option to search for open resources by typing "open:"
+ # in the search field:
+ #
+ # COLLECTION_FILTERS = {
+ # open: ->(resources) { resources.where(open: true) }
+ # }.freeze
+ COLLECTION_FILTERS = {}.freeze
+
+ # Overwrite this method to customize how response documents are displayed
+ # across all pages of the admin dashboard.
+ #
+ def display_resource(response_document)
+ "Document: ##{response_document.id} - #{response_document.document_link}"
+ end
+end
diff --git a/enterprise/app/dashboards/response_source_dashboard.rb b/enterprise/app/dashboards/response_source_dashboard.rb
new file mode 100644
index 000000000000..2d851c1dbefb
--- /dev/null
+++ b/enterprise/app/dashboards/response_source_dashboard.rb
@@ -0,0 +1,84 @@
+require 'administrate/base_dashboard'
+
+class ResponseSourceDashboard < Administrate::BaseDashboard
+ # ATTRIBUTE_TYPES
+ # a hash that describes the type of each of the model's fields.
+ #
+ # Each different type represents an Administrate::Field object,
+ # which determines how the attribute is displayed
+ # on pages throughout the dashboard.
+ ATTRIBUTE_TYPES = {
+ id: Field::Number,
+ account: Field::BelongsToSearch.with_options(class_name: 'Account', searchable_field: [:name, :id], order: 'id DESC'),
+ name: Field::String.with_options(searchable: true),
+ response_documents: Field::HasMany,
+ responses: Field::HasMany,
+ source_link: Field::String.with_options(searchable: true),
+ source_model_id: Field::Number,
+ source_model_type: Field::String,
+ source_type: Field::Select.with_options(searchable: false, collection: lambda { |field|
+ field.resource.class.send(field.attribute.to_s.pluralize).keys
+ }),
+ created_at: Field::DateTime,
+ updated_at: Field::DateTime
+ }.freeze
+
+ # COLLECTION_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's index page.
+ #
+ # By default, it's limited to four items to reduce clutter on index pages.
+ # Feel free to add, remove, or rearrange items.
+ COLLECTION_ATTRIBUTES = %i[
+ id
+ name
+ account
+ source_link
+ ].freeze
+
+ # SHOW_PAGE_ATTRIBUTES
+ # an array of attributes that will be displayed on the model's show page.
+ SHOW_PAGE_ATTRIBUTES = %i[
+ id
+ name
+ account
+ source_link
+ source_model_id
+ source_model_type
+ source_type
+ created_at
+ updated_at
+ response_documents
+ responses
+ ].freeze
+
+ # FORM_ATTRIBUTES
+ # an array of attributes that will be displayed
+ # on the model's form (`new` and `edit`) pages.
+ FORM_ATTRIBUTES = %i[
+ account
+ name
+ source_link
+ source_model_id
+ source_model_type
+ source_type
+ ].freeze
+
+ # COLLECTION_FILTERS
+ # a hash that defines filters that can be used while searching via the search
+ # field of the dashboard.
+ #
+ # For example to add an option to search for open resources by typing "open:"
+ # in the search field:
+ #
+ # COLLECTION_FILTERS = {
+ # open: ->(resources) { resources.where(open: true) }
+ # }.freeze
+ COLLECTION_FILTERS = {}.freeze
+
+ # Overwrite this method to customize how response sources are displayed
+ # across all pages of the admin dashboard.
+ #
+ def display_resource(response_source)
+ "Source: ##{response_source.id} - #{response_source.name}"
+ end
+end