Remove Fizzy Ask
Since we are not going to ship it
This commit is contained in:
@@ -2,11 +2,10 @@ import { Controller } from "@hotwired/stimulus"
|
||||
import { post } from "@rails/request.js"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = [ "turboFrame", "searchInput", "askInput", "buttonsContainer" ]
|
||||
static targets = [ "turboFrame", "searchInput", "buttonsContainer" ]
|
||||
static outlets = [ "dialog" ]
|
||||
static values = {
|
||||
searchUrl: String,
|
||||
askUrl: String,
|
||||
}
|
||||
|
||||
dialogOutletConnected(outlet, element) {
|
||||
@@ -21,9 +20,6 @@ export default class extends Controller {
|
||||
this.searchInputTarget.querySelector("input").value = ""
|
||||
this.#showItem(this.buttonsContainerTarget)
|
||||
this.#hideItem(this.searchInputTarget)
|
||||
if (this.hasAskInputTarget) {
|
||||
this.#hideItem(this.askInputTarget)
|
||||
}
|
||||
}
|
||||
|
||||
showModalAndSubmit(event) {
|
||||
@@ -44,18 +40,6 @@ export default class extends Controller {
|
||||
|
||||
this.#showItem(this.searchInputTarget)
|
||||
this.#hideItem(this.buttonsContainerTarget)
|
||||
if (this.hasAskInputTarget) {
|
||||
this.#hideItem(this.askInputTarget)
|
||||
}
|
||||
}
|
||||
|
||||
ask(event) {
|
||||
this.#initializeConversation()
|
||||
this.#openInTurboFrame(this.askUrlValue)
|
||||
|
||||
this.#showItem(this.askInputTarget)
|
||||
this.#hideItem(this.searchInputTarget)
|
||||
this.#hideItem(this.buttonsContainerTarget)
|
||||
}
|
||||
|
||||
#clearTurboFrame() {
|
||||
@@ -67,10 +51,6 @@ export default class extends Controller {
|
||||
this.turboFrameTarget.src = url
|
||||
}
|
||||
|
||||
#initializeConversation() {
|
||||
post(this.askUrlValue)
|
||||
}
|
||||
|
||||
#showItem(element) {
|
||||
element.removeAttribute("hidden")
|
||||
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
import { onNextEventLoopTick, nextFrame } from "helpers/timing_helpers"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = [ "textInput", "submitButton", "clientMessageIdInput" ]
|
||||
static outlets = [ "conversation--messages" ]
|
||||
|
||||
#submittingMessage
|
||||
|
||||
connect() {
|
||||
this.#submittingMessage = false
|
||||
onNextEventLoopTick(() => this.textInputTarget.focus())
|
||||
}
|
||||
|
||||
submit(event) {
|
||||
event.preventDefault()
|
||||
|
||||
if (!this.#submittingMessage) {
|
||||
this.#submittingMessage = true
|
||||
this.#submitMessage()
|
||||
}
|
||||
}
|
||||
|
||||
submitEnd(event) {
|
||||
this.#submittingMessage = false
|
||||
|
||||
if (event.detail.success) {
|
||||
this.#reset()
|
||||
} else {
|
||||
this.#failPendingMessage(
|
||||
this.clientMessageIdInputTarget.value,
|
||||
event.detail.fetchResponse
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
async #submitMessage() {
|
||||
if (this.#validInput()) {
|
||||
const messageId = this.#generateMessageId()
|
||||
|
||||
await this.conversationMessagesOutlet.insertPendingMessage(messageId, this.#messageText)
|
||||
await nextFrame()
|
||||
this.conversationMessagesOutlet.scrollToBottom()
|
||||
|
||||
this.clientMessageIdInputTarget.value = messageId
|
||||
this.element.requestSubmit()
|
||||
}
|
||||
}
|
||||
|
||||
get #messageText() {
|
||||
return this.textInputTarget.value
|
||||
}
|
||||
|
||||
#validInput() {
|
||||
return this.#messageText.trim().length > 0
|
||||
}
|
||||
|
||||
#generateMessageId() {
|
||||
return Math.random().toString(36).slice(2)
|
||||
}
|
||||
|
||||
#reset() {
|
||||
this.textInputTarget.value = ""
|
||||
this.clientMessageIdInputTarget.value = ""
|
||||
}
|
||||
|
||||
async #failPendingMessage(clientMessageId, response) {
|
||||
let errorMessage = null
|
||||
|
||||
if (response?.contentType?.includes('application/json')) {
|
||||
const error = JSON.parse(await response.responseText)
|
||||
errorMessage = error.error
|
||||
}
|
||||
|
||||
this.conversationMessagesOutlet.failPendingMessage(
|
||||
this.clientMessageIdInputTarget.value,
|
||||
errorMessage
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
import { nextFrame } from "helpers/timing_helpers"
|
||||
|
||||
export default class extends Controller {
|
||||
static SCROLL_TRESHOLD = 100
|
||||
static EMOJI_MATCHER = /^(\p{Emoji_Presentation}|\p{Extended_Pictographic}|\uFE0F)+$/gu
|
||||
|
||||
static targets = [ "messages", "messageTemplate" ]
|
||||
static classes = [ "failedMessage", "emojiMessage" ]
|
||||
|
||||
connect() {
|
||||
this.scrollToBottom()
|
||||
}
|
||||
|
||||
failPendingMessage(clientMessageId, errorMessage) {
|
||||
const message = this.element.querySelector(`#message_${clientMessageId}`)
|
||||
|
||||
if (message) {
|
||||
message.classList.add(this.failedMessageClass)
|
||||
|
||||
if (errorMessage) {
|
||||
message.dataset.error = errorMessage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async insertPendingMessage(clientMessageId, content) {
|
||||
const html = this.#pendingMessageHtml({
|
||||
clientMessageId: clientMessageId,
|
||||
content: content,
|
||||
extraClasses: this.#allEmoji(content) ? this.emojiMessageClass : ""
|
||||
})
|
||||
|
||||
this.messagesTarget.insertAdjacentHTML("beforeend", html)
|
||||
|
||||
await nextFrame()
|
||||
this.scrollToBottom()
|
||||
}
|
||||
|
||||
scrollToBottom() {
|
||||
this.element.scrollTop = this.element.scrollHeight
|
||||
}
|
||||
|
||||
beforeStreamRender(event) {
|
||||
const target = event.detail.newStream.getAttribute("target")
|
||||
|
||||
if (target === this.messagesTarget.id) {
|
||||
this.#handleScrollPositionOnTurboStreamRender(event)
|
||||
}
|
||||
}
|
||||
|
||||
#pendingMessageHtml(data) {
|
||||
let html = this.messageTemplateTarget.innerHTML
|
||||
|
||||
for (const key in data) {
|
||||
html = html.replaceAll(`$${key}$`, data[key])
|
||||
}
|
||||
|
||||
return html
|
||||
}
|
||||
|
||||
#allEmoji(content) {
|
||||
return content.match(this.constructor.EMOJI_MATCHER)
|
||||
}
|
||||
|
||||
#handleScrollPositionOnTurboStreamRender(event) {
|
||||
if (event.detail.newStream.action === "append") {
|
||||
this.#scrollToBottomOnTurboStreamRender(event)
|
||||
} else {
|
||||
this.#preserveScrollPositionOnTurboStreamRender(event)
|
||||
}
|
||||
}
|
||||
|
||||
#scrollToBottomOnTurboStreamRender(event) {
|
||||
const render = event.detail.render
|
||||
|
||||
event.detail.render = async (streamElement) => {
|
||||
await render(streamElement)
|
||||
await nextFrame()
|
||||
this.scrollToBottom()
|
||||
}
|
||||
}
|
||||
|
||||
#preserveScrollPositionOnTurboStreamRender(event) {
|
||||
const render = event.detail.render
|
||||
|
||||
event.detail.render = async (streamElement) => {
|
||||
const previousScrollHeight = this.element.scrollHeight
|
||||
const previousScrollTop = this.element.scrollTop
|
||||
const previouslyWasAtBottom = this.#scrolledToBottom
|
||||
|
||||
await render(streamElement)
|
||||
|
||||
if (previouslyWasAtBottom) {
|
||||
this.messagesTarget.scrollTop = this.messagesTarget.scrollHeight
|
||||
} else {
|
||||
const newScrollHeight = this.element.scrollHeight
|
||||
const scrollDelta = newScrollHeight - previousScrollHeight
|
||||
this.element.scrollTop = previousScrollTop + scrollDelta
|
||||
}
|
||||
|
||||
await nextFrame()
|
||||
}
|
||||
}
|
||||
|
||||
get #scrolledToBottom() {
|
||||
const scrollBottom = this.element.scrollTop + this.element.clientHeight
|
||||
const contentBottom = this.element.scrollHeight - this.constructor.SCROLL_THRESHOLD
|
||||
|
||||
return scrollBottom >= contentBottom
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user