-
Notifications
You must be signed in to change notification settings - Fork 188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Load all project drops and parse liquid async #1262
Changes from 21 commits
571c388
418d85e
ea2baa0
c148482
8929784
825eb27
ce03ecb
4f72449
305cab0
aeddb6b
b0c2a9b
365e714
3401968
499c2ac
f18b190
89c96eb
a87d0bf
0637a0f
79a26dc
25b98bc
3cfd946
1c77ace
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
document.addEventListener('turbolinks:load', function () { | ||
$('[data-behavior~=liquid-async]').each(function () { | ||
const that = this, | ||
data = { text: $(that).attr('data-content') }, | ||
$spinner = $(that).prev().find('[data-behavior~=liquid-spinner'); | ||
|
||
fetch($(that).attr('data-path'), { | ||
method: 'POST', | ||
headers: { | ||
Accept: 'text/html', | ||
'Content-Type': 'application/json', | ||
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content'), | ||
}, | ||
body: JSON.stringify(data), | ||
}) | ||
.then((response) => response.text()) | ||
.then(function (html) { | ||
$(that).html(html); | ||
$spinner.addClass('d-none'); | ||
}); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,15 @@ | ||
class LiquidAssignsService | ||
attr_accessor :project | ||
AVAILABLE_PROJECT_ASSIGNS = %w{ evidences issues nodes notes tags }.freeze | ||
|
||
def initialize(project) | ||
attr_accessor :project, :text | ||
|
||
def initialize(project:, text: nil) | ||
@project = project | ||
@text = text | ||
end | ||
|
||
def assigns | ||
result = { 'project' => ProjectDrop.new(project) } | ||
result = project_assigns | ||
result.merge!(assigns_pro) if defined?(Dradis::Pro) | ||
result | ||
end | ||
|
@@ -15,4 +18,44 @@ def assigns | |
|
||
def assigns_pro | ||
end | ||
|
||
# This method uses Liquid::VariableLookup to find all liquid variables from | ||
# a given text. We use the list to know which project assign we need. | ||
def assigns_from_content | ||
return AVAILABLE_PROJECT_ASSIGNS if text.nil? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should the default be [] rather than a full list? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a case in Word where |
||
|
||
variable_lookup = Liquid::VariableLookup.parse(text) | ||
return (variable_lookup.lookups & AVAILABLE_PROJECT_ASSIGNS) | ||
Comment on lines
+27
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. seeing this code and the intersect/validation, is L25 really needed? How does VariableLookup behave on empty input? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See comment above. If the |
||
end | ||
|
||
def cached_drops(records, record_type) | ||
return [] if records.empty? | ||
|
||
cache_key = "liquid-project-#{project.id}-#{record_type.pluralize}:#{records.maximum(:updated_at).to_i}-#{records.count}" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it seems we're working hard here to craft a unique key. Have you looked into how the Rails code does this when you pass a collection in your view cache call? Maybe there's a method we can use that takes a prefix and a collection and spits the unique cache key? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like rails is using the cache_key to uniquely identify each record and use that to individually cache each rendered view in the collection as mentioned here: https://guides.rubyonrails.org/caching_with_rails.html#collection-caching. Unfortunately, the method doesn't work for us as we're caching whole collections. For example, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is what I meant: |
||
drop_class = "#{record_type.camelize}Drop".constantize | ||
|
||
Rails.cache.fetch(cache_key) do | ||
records.map { |record| drop_class.new(record) } | ||
end | ||
end | ||
|
||
def project_assigns | ||
project_assigns = { 'project' => ProjectDrop.new(project) } | ||
|
||
assigns_from_content.each do |record_type| | ||
records = | ||
case record_type | ||
when 'evidences' | ||
project.evidence | ||
when 'nodes' | ||
project.nodes.user_nodes | ||
else | ||
project.send(record_type.to_sym) | ||
end | ||
|
||
project_assigns.merge!(record_type => cached_drops(records, record_type.singularize)) | ||
end | ||
|
||
project_assigns | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<div | ||
class="d-inline-flex align-items-center fs-6 fw-light" | ||
data-behavior="liquid-spinner" | ||
> | ||
<span class="mx-2">-</span> | ||
<%= spinner_tag spinner_class: 'spinner-border-sm text-primary', align: 'start', inline: true %> | ||
<span class="ms-2 text-nowrap">Loading liquid dynamic content</span> | ||
</div> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,14 +9,15 @@ | |
visit @path | ||
end | ||
|
||
it 'dynamically renders item properties' do | ||
it 'dynamically renders item properties', js: true do | ||
expect(page).to have_no_css('span.text-nowrap', text: 'Loading liquid dynamic content', wait: 10) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 10 seconds might be a bit long to wait, have you tested it with less? We may be able to get away with a shorter wait time There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 10 seconds is only the maximum wait time and it won't really take this long. We're only setting the value here because 2 seconds might be too short and we need to account for possible hitches in CI that could cause a false negative. |
||
|
||
expect(find('.note-text-inner')).to have_content("Liquid: #{record.title}") | ||
expect(find('.note-text-inner')).not_to have_content("Liquid: {{#{item_type}.title}}") | ||
end | ||
end | ||
|
||
shared_examples 'liquid preview' do |item_type, node_association| | ||
|
||
before do | ||
@path = if node_association | ||
polymorphic_path([:edit, current_project, record.node, record]) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about passing the
project_id
instead and finding it here?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if we're winning with this change if we have to update every instance of this initialization as well as possibly move the
can?
check. Seeliquid_enabled_resource
:The check requires a reference to the
current_user