Skip to content

Commit 331ab16

Browse files
committed
Refactor snippet form to Phlex component
1 parent bbcd4ef commit 331ab16

File tree

7 files changed

+134
-96
lines changed

7 files changed

+134
-96
lines changed

app/javascript/controllers/snippets/editor.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ import debug from '../../utils/debug';
66
const console = debug('app:javascript:controllers:snippets:editor');
77

88
export default class extends Controller {
9-
static targets = ['previewButton', 'source', 'textarea'];
9+
static targets = ['source', 'textarea'];
1010

11-
declare previewButtonTarget: HTMLButtonElement;
1211
declare sourceTarget: HTMLElement;
1312
declare textareaTarget: HTMLTextAreaElement;
1413

app/javascript/controllers/snippets/preview.ts

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,9 @@ export default class extends Controller<HTMLFormElement> {
1414

1515
declare readonly hasPreviewButtonTarget: boolean;
1616
declare readonly previewButtonTarget: HTMLInputElement;
17-
declare readonly previewButtonTargets: HTMLInputElement[];
1817

1918
declare readonly hasSnippetTarget: boolean;
2019
declare readonly snippetTarget: HTMLInputElement;
21-
declare readonly snippetTargets: HTMLInputElement[];
2220

2321
connect(): void {
2422
console.log('Connect!');
@@ -48,20 +46,6 @@ export default class extends Controller<HTMLFormElement> {
4846
this.previewButtonTarget.click();
4947
};
5048

51-
share = async (event: CustomEvent) => {
52-
console.log('Share!');
53-
event.preventDefault();
54-
55-
const data = await htmlToImage.toPng(this.snippetTarget);
56-
57-
const input = document.createElement('input');
58-
input.type = 'hidden';
59-
input.name = 'snippet[screenshot]';
60-
input.value = data;
61-
62-
this.element.requestSubmit();
63-
};
64-
6549
prepareScreenshot = async (event) => {
6650
event.preventDefault();
6751

app/views/components/code_block/snippet.rb

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,17 @@ class CodeBlock::Snippet < ApplicationComponent
77

88
def initialize(snippet, editing: false, data: {}, **)
99
@snippet = snippet
10-
@editing = editing
11-
@data = data
1210
end
1311

1412
def view_template
15-
div(class: "snippet-background", data:) do
13+
div(class: "snippet-background") do
1614
render CodeBlock::Container.new(language: language, class: "snippet") do
1715
render CodeBlock::Header.new do
18-
if editing?
19-
label(class: "sr-only", for: "snippet[filename]") { "Filename" }
20-
input(type: "text", name: "snippet[filename]", value: filename)
21-
else
22-
filename
23-
end
16+
filename
2417
end
2518

26-
render CodeBlock::Body.new(data: editor_data) do
27-
div(class: "grid-stack") do
28-
render CodeBlock::Code.new(source, language: language, data: {snippet_editor_target: "source"})
29-
if editing?
30-
label(class: "sr-only", for: "snippet[source]") { "Source" }
31-
div(class: "code-editor autogrow-wrapper") do
32-
textarea(
33-
name: "snippet[source]",
34-
data: {snippet_editor_target: "textarea"}
35-
) { source }
36-
end
37-
end
38-
end
19+
render CodeBlock::Body.new do
20+
render CodeBlock::Code.new(source, language: language, data: {snippet_editor_target: "source"})
3921
end
4022
end
4123
end
@@ -54,11 +36,5 @@ def source
5436
snippet.source || ""
5537
end
5638

57-
def editing? = !!@editing
58-
5939
delegate :language, :filename, to: :snippet
60-
61-
def editor_data
62-
editing? ? {controller: "snippet-editor"} : {}
63-
end
6440
end

app/views/snippets/_form.html.erb

Lines changed: 0 additions & 48 deletions
This file was deleted.

app/views/snippets/edit.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<%= render Pages::Header.new(title: "Edit snippet") %>
22
<div class="section-content container py-gap">
3-
<%= render "form", snippet: @snippet %>
3+
<%= render Snippets::Form.new(snippet: @snippet) %>
44

55
<br>
66

app/views/snippets/form.rb

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
class Snippets::Form < ApplicationComponent
2+
include Phlex::Rails::Helpers::DOMID
3+
include Phlex::Rails::Helpers::FormWith
4+
include Phlex::Rails::Helpers::TurboFrameTag
5+
include Phlex::Rails::Helpers::Pluralize
6+
7+
attr_accessor :snippet
8+
9+
def initialize(snippet:)
10+
@snippet = snippet
11+
end
12+
13+
def view_template
14+
form_with(
15+
model: snippet,
16+
class: "grid-content",
17+
data: {
18+
controller: "snippet-preview",
19+
action: "snippet-editor:changed->snippet-preview#preview"
20+
}
21+
) do |form|
22+
errors
23+
24+
language_select(form, data: {action: "change->snippet-preview#preview"})
25+
26+
turbo_frame_tag dom_id(snippet, :code_block), class: "snippet-frame grid-cols-12" do
27+
div(class: "snippet-background", data: {snippet_preview_target: "snippet"}) do
28+
render CodeBlock::Container.new(language: language, class: "snippet") do
29+
render CodeBlock::Header.new do
30+
label(class: "sr-only", for: "snippet[filename]") { "Filename" }
31+
input(type: "text", name: "snippet[filename]", value: filename)
32+
end
33+
34+
render CodeBlock::Body.new(data: {controller: "snippet-editor"}) do
35+
div(class: "grid-stack") do
36+
render CodeBlock::Code.new(source, language: language, data: {snippet_editor_target: "source"})
37+
label(class: "sr-only", for: "snippet[source]") { "Source" }
38+
div(class: "code-editor autogrow-wrapper") do
39+
textarea(
40+
name: "snippet[source]",
41+
data: {snippet_editor_target: "textarea"}
42+
) { source }
43+
end
44+
end
45+
end
46+
end
47+
end
48+
end
49+
50+
fieldset do
51+
plain form.submit class: "button primary"
52+
whitespace
53+
plain form.button "Share",
54+
class: "button secondary",
55+
data: {
56+
action: "snippet-preview#share"
57+
}
58+
whitespace
59+
plain form.submit "Preview",
60+
class: "button secondary hidden",
61+
formaction: form_path,
62+
formmethod: "get",
63+
formnovalidate: true,
64+
data: {
65+
snippet_preview_target: "previewButton",
66+
turbo_frame: dom_id(snippet, :code_block)
67+
}
68+
end
69+
end
70+
end
71+
72+
private
73+
74+
def language = snippet.language
75+
76+
def filename = snippet.filename
77+
78+
def source = snippet.source || ""
79+
80+
def errors
81+
if snippet.errors.any?
82+
div(style: "color:red") do
83+
h2 do
84+
pluralize(snippet.errors.count, "error")
85+
plain " prohibited this snippet from being saved:"
86+
end
87+
ul do
88+
snippet.errors.each do |error|
89+
li { error.full_message }
90+
whitespace
91+
end
92+
end
93+
end
94+
end
95+
end
96+
97+
def language_select(form, data: {})
98+
div(class: "flex items-start flex-col space-col-4 md:items-center md:flex-row md:space-row-4") do
99+
fieldset do
100+
plain form.label :language, class: "sr-only"
101+
plain form.select :language,
102+
language_select_options,
103+
{},
104+
data:,
105+
class:
106+
"flex-1 rounded bg-white/5 focus-ring focus:ring-0 ring-1 ring-inset ring-white/10 w-full lg:min-w-[36ch]"
107+
end
108+
end
109+
end
110+
111+
def language_select_options
112+
[%w[Auto auto]] +
113+
Rouge::Lexer.all.map { |lexer|
114+
[lexer.title, lexer.tag]
115+
}
116+
end
117+
118+
def form_path
119+
if snippet.persisted?
120+
edit_snippet_path(snippet)
121+
else
122+
new_snippet_path
123+
end
124+
end
125+
end

app/views/snippets/new.html.erb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<%= render Pages::Header.new(title: "New Snippet") %>
22
<div class="section-content container py-gap">
3-
<%= render "form", snippet: @snippet %>
3+
<%= render Snippets::Form.new(snippet: @snippet) %>
4+
5+
<br>
46

57
<div>
68
<%= link_to "Back to snippets", snippets_path %>

0 commit comments

Comments
 (0)