Skip to content

Commit

Permalink
Merge pull request #15480 from opf/chore/autocompleter_inputs
Browse files Browse the repository at this point in the history
Separate input for project autocompleter
  • Loading branch information
dominic-braeunlein authored May 7, 2024
2 parents 2bf12e5 + cc624fe commit d56ce78
Show file tree
Hide file tree
Showing 11 changed files with 122 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ export class ProjectAutocompleterComponent extends OpAutocompleterComponent<IPro

@Input() public isInlineContext = false;

@Input() public disabledProjects:{ [key:string]:string|boolean } = {};

// This function allows mapping of the results before they are fed to the tree
// structuring and destructuring algorithms used internally the this component
// to show the tree structure. By default it does not do much, but it is
Expand Down Expand Up @@ -140,9 +142,12 @@ export class ProjectAutocompleterComponent extends OpAutocompleterComponent<IPro
const arrayedValue = (Array.isArray(normalizedValue) ? normalizedValue : [normalizedValue]).map((p) => p.href || p.id);
return projects.map((project) => {
const isSelected = !!arrayedValue.find((selected) => selected === this.projectTracker(project));
const id = project.id.toString();
const disabled = isSelected || project.disabled || !!this.disabledProjects[id];
return {
...project,
disabled: isSelected || project.disabled,
disabled,
disabledReason: (typeof this.disabledProjects[id] === 'string') ? this.disabledProjects[id] as string : '',
};
});
}
Expand Down Expand Up @@ -176,14 +181,20 @@ export class ProjectAutocompleterComponent extends OpAutocompleterComponent<IPro
},
)
.pipe(
map((projects) => projects.map((project) => ({
id: project.id,
href: project._links.self.href,
name: project.name,
disabled: false,
ancestors: project._links.ancestors,
children: [],
}))),
map((projects) => projects.map((project) => {
const id = project.id.toString();
const disabled = !!this.disabledProjects[id];

return {
id: project.id,
href: project._links.self.href,
name: project.name,
disabled,
disabledReason: (typeof this.disabledProjects[id] === 'string') ? this.disabledProjects[id] as string : '',
ancestors: project._links.ancestors,
children: [],
};
})),
map(this.mapResultsFn),
map((projects) => {
this.dataLoaded = true;
Expand Down
2 changes: 1 addition & 1 deletion lib/primer/open_project/forms/autocompleter.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
append_to: @autocomplete_options.fetch(:append_to, 'body')
} %>
<% else %>
<%= angular_component_tag @autocomplete_options.fetch(:component, 'opce-autocompleter'),
<%= angular_component_tag @autocomplete_options.fetch(:component),
data: @autocomplete_options.delete(:data) { {} },
inputs: @autocomplete_options.merge(
classes: "ng-select--primerized #{@input.invalid? ? '-error' : ''}",
Expand Down
8 changes: 7 additions & 1 deletion lib/primer/open_project/forms/dsl/autocompleter_input.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def to_h
def initialize(name:, label:, autocomplete_options:, wrapper_data_attributes: {}, **system_arguments)
@name = name
@label = label
@autocomplete_options = autocomplete_options
@autocomplete_options = derive_autocompleter_options(autocomplete_options)
@wrapper_data_attributes = wrapper_data_attributes
@select_options = []

Expand All @@ -37,6 +37,12 @@ def initialize(name:, label:, autocomplete_options:, wrapper_data_attributes: {}
yield(self) if block_given?
end

def derive_autocompleter_options(options)
options.reverse_merge(
component: "opce-autocompleter"
)
end

def option(**args)
@select_options << Option.new(**args)
end
Expand Down
8 changes: 8 additions & 0 deletions lib/primer/open_project/forms/dsl/input_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ def autocompleter(**, &)
add_input AutocompleterInput.new(builder: @builder, form: @form, **, &)
end

def work_package_autocompleter(**, &)
add_input WorkPackageAutocompleterInput.new(builder: @builder, form: @form, **, &)
end

def project_autocompleter(**, &)
add_input ProjectAutocompleterInput.new(builder: @builder, form: @form, **, &)
end

def rich_text_area(**)
add_input RichTextAreaInput.new(builder: @builder, form: @form, **)
end
Expand Down
25 changes: 25 additions & 0 deletions lib/primer/open_project/forms/dsl/project_autocompleter_input.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

module Primer
module OpenProject
module Forms
module Dsl
class ProjectAutocompleterInput < AutocompleterInput
def derive_autocompleter_options(options)
options.reverse_merge!(
component: "opce-project-autocompleter",
defaultData: false,
filters: [{ name: 'active', operator: '=', values: ['t'] }],
)

if options[:disabledProjects]
options[:disabledProjects].stringify_keys!
end

options
end
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

module Primer
module OpenProject
module Forms
module Dsl
class WorkPackageAutocompleterInput < AutocompleterInput
def derive_autocompleter_options(options)
options.reverse_merge(
component: "opce-autocompleter",
resource: "work_packages",
searchKey: "subjectOrId",
)
end
end
end
end
end
end
7 changes: 7 additions & 0 deletions lookbook/docs/patterns/03-autocompleters.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ Keep in mind that this component uses the live work packages API, so results wil

<%= embed OpenProject::Common::AutocompletePreview, :work_package, panels: %i[source] %>

### Project autocompletion

For project autocompletion, you can use the same field, but with a different configuration.
Keep in mind that this component uses the live projects API, so results will depend on whether you are logged in.

<%= embed OpenProject::Common::AutocompletePreview, :project, panels: %i[source] %>

### Outside primer

If you're not in a primer form, you can render the autocomplete directly like so:
Expand Down
5 changes: 5 additions & 0 deletions lookbook/previews/open_project/common/autocomplete_preview.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ def decorated
def work_package
render_with_template
end

# @display min_height 250px
def project
render_with_template
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<%
the_form = Class.new(ApplicationForm) do
form do |f|
f.project_autocompleter(
name: :id,
label: Project.model_name.human,
visually_hide_label: true,
autocomplete_options: {
openDirectly: false,
focusDirectly: false,
dropdownPosition: 'bottom',
disabledProjects: Project.visible.take(10).pluck(:id).to_h { |id| [id, "Disabled reason!"] }
}
)
end
end

model = Project.new
%>
<%= primer_form_with(
model:,
url: '/abc',
id: 'asdf') do |f|
render(the_form.new(f))
end
%>
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<%
the_form = Class.new(ApplicationForm) do
form do |f|
f.autocompleter(
f.work_package_autocompleter(
name: :id,
label: WorkPackage.model_name.human,
visually_hide_label: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

class MeetingAgendaItem::WorkPackage < ApplicationForm
form do |agenda_item_form|
agenda_item_form.autocompleter(
agenda_item_form.work_package_autocompleter(
name: :work_package_id,
label: WorkPackage.model_name.human,
visually_hide_label: true,
Expand All @@ -37,8 +37,6 @@ class MeetingAgendaItem::WorkPackage < ApplicationForm
data: {
"test-selector": "op-agenda-items-wp-autocomplete"
},
resource: "work_packages",
searchKey: "subjectOrId",
focusDirectly: true,
disabled: @disabled
}
Expand Down

0 comments on commit d56ce78

Please sign in to comment.