bullet_train 1.0.98 → 1.0.99
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/javascripts/bullet-train.js +1 -1
- data/app/assets/javascripts/bullet-train.js.map +1 -1
- data/app/controllers/concerns/account/invitations/controller_base.rb +13 -6
- data/app/controllers/concerns/controllers/base.rb +1 -2
- data/app/controllers/concerns/registrations/controller_base.rb +4 -7
- data/app/controllers/concerns/sessions/controller_base.rb +0 -6
- data/app/helpers/account/forms_helper.rb +0 -4
- data/app/helpers/invitations_helper.rb +0 -15
- data/app/javascript/controllers/index.js +2 -0
- data/app/javascript/controllers/mobile_menu_controller.js +18 -16
- data/app/javascript/controllers/text_toggle_controller.js +33 -0
- data/app/models/concerns/records/base.rb +10 -0
- data/app/models/concerns/users/base.rb +1 -4
- data/app/views/devise/sessions/new.html.erb +6 -6
- data/app/views/layouts/docs.html.erb +7 -18
- data/docs/field-partials/super-select.md +60 -2
- data/docs/field-partials.md +24 -17
- data/docs/index.md +1 -0
- data/docs/invitation_only.md +13 -0
- data/docs/super-scaffolding/delegated-types.md +31 -3
- data/lib/bullet_train/version.rb +1 -1
- data/lib/bullet_train.rb +4 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 00a1173803e9bee7ab0710b0b58cc2acd39410f253b1998ddbac32ad2d7aa159
|
|
4
|
+
data.tar.gz: 3fb346b3c73b5f6dc7d423f7cf40e1c98f35832850c13d9afaeecf7260c222d7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f69696c007457c625b410741693ef467c5c528d9a23871fedcacd7ec926cc73d8d9fa369c72f3f8048f47acbff62264e1cb3d1877e4ad51b5937fbf3e9eb940d
|
|
7
|
+
data.tar.gz: c7eff30ad9b7faa0770b481a1b3967981105b005bb0e4520f64d26a0e08e4f68583a26599098c93cddd68b948c716ad1a7e6a64d13f80d1a2b629324e890467c
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Controller as e}from"@hotwired/stimulus";function t(e){const t=(e.match(/^(?:\.\/)?(.+)(?:[_-]controller\..+?)$/)||[])[1];if(t)return t.replace(/_/g,"-").replace(/\//g,"--")}class l extends e{connect(){this.updateAvailability()}updateFormAndSubmit(e){return this.recreateIdsHiddenFields(),this.createOrUpdateAllField(),!0}updateIds(e){var t;null!=e&&null!=(t=e.detail)&&t.ids&&(this.idsValue=e.detail.ids,this.allValue=e.detail.all),this.updateAvailability(),this.updateButtonLabel()}updateAvailability(){this.element.classList.toggle(this.hiddenClass,0===this.idsValue.length)}updateButtonLabel(){let e=this.buttonIfAllValue;this.idsValue.length&&!1===this.allValue&&(e=this.buttonIfIdsValue.replace("{num}",this.idsValue.length)),"INPUT"===this.buttonTarget.tagName?this.buttonTarget.value=e:this.buttonTarget.textContent=e}recreateIdsHiddenFields(){this.removeIdsHiddenFields(),this.createIdsHiddenFields()}removeIdsHiddenFields(){this.idsHiddenFieldTargets.forEach(e=>{this.element.removeChild(e)})}createIdsHiddenFields(){this.idsValue.forEach(e=>{let t=document.createElement("input");t.type="hidden",t.name=this.objectNameValue+"["+this.idsFieldNameValue+"][]",t.value=e,this.element.appendChild(t)})}createOrUpdateAllField(){this.hasAllHiddenFieldTarget?this.allHiddenFieldTarget.value=this.allValue?"true":"false":this.createAllField()}createAllField(){let e=document.createElement("input");e.type="hidden",e.name=this.objectNameValue+"["+this.allFieldNameValue+"]",e.value=this.allValue?"true":"false",this.element.appendChild(e)}}l.targets=["button","idsHiddenField","allHiddenField"],l.classes=["hidden"],l.values={buttonIfAll:String,buttonIfIds:String,ids:Array,all:Boolean,objectName:String,idsFieldName:String,allFieldName:String};class s extends e{connect(){this.element.classList.add(this.selectableAvailableClass)}toggleSelectable(){this.selectableValue=!this.selectableValue}updateSelectedIds(){this.updateActions(),this.updateSelectAllCheckbox()}updateActions(){this.actionTargets.forEach(e=>{e.dispatchEvent(new CustomEvent("update-ids",{detail:{ids:this.selectedIds,all:this.allSelected}}))})}selectAllOrNone(e){this.allSelected?this.selectNone():this.selectAll(),this.updateSelectAllCheckbox()}selectAll(){this.checkboxTargets.forEach(e=>{e.checked=!0}),this.updateActions()}selectNone(){this.checkboxTargets.forEach(e=>{e.checked=!1}),this.updateActions()}updateSelectAllCheckbox(){let e=this.selectAllCheckboxTarget,t=this.selectAllLabelTarget;this.allSelected?(e.checked=!0,e.indeterminate=!1,t.dispatchEvent(new CustomEvent("toggle",{detail:{useAlternate:!0}}))):this.selectedIds.length>0?(e.indeterminate=!0,t.dispatchEvent(new CustomEvent("toggle",{detail:{useAlternate:!1}}))):(e.checked=!1,e.indeterminate=!1,t.dispatchEvent(new CustomEvent("toggle",{detail:{useAlternate:!1}})))}selectableValueChanged(){this.element.classList.toggle(this.selectableClass,this.selectableValue),this.updateToggleLabel()}updateToggleLabel(){this.selectableToggleTarget.dispatchEvent(new CustomEvent("toggle",{detail:{useAlternate:this.selectableValue}}))}get selectedIds(){let e=[];return this.checkboxTargets.forEach(t=>{t.checked&&e.push(t.value)}),e}get allSelected(){return this.selectedIds.length===this.checkboxTargets.length}}s.targets=["checkbox","selectAllCheckbox","action","selectableToggle","selectAllLabel"],s.classes=["selectableAvailable","selectable"],s.values={selectable:Boolean};class
|
|
1
|
+
import{Controller as e}from"@hotwired/stimulus";function t(e){const t=(e.match(/^(?:\.\/)?(.+)(?:[_-]controller\..+?)$/)||[])[1];if(t)return t.replace(/_/g,"-").replace(/\//g,"--")}class l extends e{connect(){this.updateAvailability()}updateFormAndSubmit(e){return this.recreateIdsHiddenFields(),this.createOrUpdateAllField(),!0}updateIds(e){var t;null!=e&&null!=(t=e.detail)&&t.ids&&(this.idsValue=e.detail.ids,this.allValue=e.detail.all),this.updateAvailability(),this.updateButtonLabel()}updateAvailability(){this.element.classList.toggle(this.hiddenClass,0===this.idsValue.length)}updateButtonLabel(){let e=this.buttonIfAllValue;this.idsValue.length&&!1===this.allValue&&(e=this.buttonIfIdsValue.replace("{num}",this.idsValue.length)),"INPUT"===this.buttonTarget.tagName?this.buttonTarget.value=e:this.buttonTarget.textContent=e}recreateIdsHiddenFields(){this.removeIdsHiddenFields(),this.createIdsHiddenFields()}removeIdsHiddenFields(){this.idsHiddenFieldTargets.forEach(e=>{this.element.removeChild(e)})}createIdsHiddenFields(){this.idsValue.forEach(e=>{let t=document.createElement("input");t.type="hidden",t.name=this.objectNameValue+"["+this.idsFieldNameValue+"][]",t.value=e,this.element.appendChild(t)})}createOrUpdateAllField(){this.hasAllHiddenFieldTarget?this.allHiddenFieldTarget.value=this.allValue?"true":"false":this.createAllField()}createAllField(){let e=document.createElement("input");e.type="hidden",e.name=this.objectNameValue+"["+this.allFieldNameValue+"]",e.value=this.allValue?"true":"false",this.element.appendChild(e)}}l.targets=["button","idsHiddenField","allHiddenField"],l.classes=["hidden"],l.values={buttonIfAll:String,buttonIfIds:String,ids:Array,all:Boolean,objectName:String,idsFieldName:String,allFieldName:String};class s extends e{connect(){this.element.classList.add(this.selectableAvailableClass)}toggleSelectable(){this.selectableValue=!this.selectableValue}updateSelectedIds(){this.updateActions(),this.updateSelectAllCheckbox()}updateActions(){this.actionTargets.forEach(e=>{e.dispatchEvent(new CustomEvent("update-ids",{detail:{ids:this.selectedIds,all:this.allSelected}}))})}selectAllOrNone(e){this.allSelected?this.selectNone():this.selectAll(),this.updateSelectAllCheckbox()}selectAll(){this.checkboxTargets.forEach(e=>{e.checked=!0}),this.updateActions()}selectNone(){this.checkboxTargets.forEach(e=>{e.checked=!1}),this.updateActions()}updateSelectAllCheckbox(){let e=this.selectAllCheckboxTarget,t=this.selectAllLabelTarget;this.allSelected?(e.checked=!0,e.indeterminate=!1,t.dispatchEvent(new CustomEvent("toggle",{detail:{useAlternate:!0}}))):this.selectedIds.length>0?(e.indeterminate=!0,t.dispatchEvent(new CustomEvent("toggle",{detail:{useAlternate:!1}}))):(e.checked=!1,e.indeterminate=!1,t.dispatchEvent(new CustomEvent("toggle",{detail:{useAlternate:!1}})))}selectableValueChanged(){this.element.classList.toggle(this.selectableClass,this.selectableValue),this.updateToggleLabel()}updateToggleLabel(){this.selectableToggleTarget.dispatchEvent(new CustomEvent("toggle",{detail:{useAlternate:this.selectableValue}}))}get selectedIds(){let e=[];return this.checkboxTargets.forEach(t=>{t.checked&&e.push(t.value)}),e}get allSelected(){return this.selectedIds.length===this.checkboxTargets.length}}s.targets=["checkbox","selectAllCheckbox","action","selectableToggle","selectAllLabel"],s.classes=["selectableAvailable","selectable"],s.values={selectable:Boolean};class a extends e{copy(){this.inputTarget.value=this.sourceTarget.innerText,this.inputTarget.select(),document.execCommand("copy"),this.buttonTarget.innerHTML='<i id="copied" class="fas fa-check w-4 h-4 block text-green-600"></i>',setTimeout(function(){document.getElementById("copied").innerHTML='<i class="far fa-copy w-4 h-4 block text-gray-600"></i>'},1500)}}a.targets=["source","input","button"];class i extends e{constructor(){super(...arguments),this.removeTrailingNewlines=e=>{e.element.innerHTML.match(/<br><\/div>$/)&&(e.element.innerHTML=e.element.innerHTML.slice(0,-10)+"</div>",this.removeTrailingNewlines(e))},this.removeTrailingWhitespace=e=>{e.element.innerHTML.match(/ <\/div>$/)?(e.element.innerHTML=e.element.innerHTML.slice(0,-12)+"</div>",this.removeTrailingWhitespace(e)):e.element.innerHTML.match(/ <\/div>$/)&&(e.element.innerHTML=e.element.innerHTML.slice(0,-13)+"</div>",this.removeTrailingWhitespace(e))}}resetOnSuccess(e){e.detail.success&&e.target.reset()}stripTrix(){this.trixFieldTargets.forEach(e=>{this.removeTrailingNewlines(e.editor),this.removeTrailingWhitespace(e.editor),e.parentElement.querySelector("input").value=e.innerHTML})}submitOnReturn(e){if((e.metaKey||e.ctrlKey)&&13==e.keyCode){e.preventDefault();let t=e.target.closest("form");this.submitForm(t)}}submitForm(e){e.requestSubmit?e.requestSubmit():e.querySelector("[type=submit]").click()}}async function n(e,t,l){const s=t.dataset,a=l?`${l}-${e}`:e;let i=`transition${e.charAt(0).toUpperCase()+e.slice(1)}`;const n=s[i]?s[i].split(" "):[a],c=s[`${i}Start`]?s[`${i}Start`].split(" "):[`${a}-start`],o=s[`${i}End`]?s[`${i}End`].split(" "):[`${a}-end`];r(t,n),r(t,c),await new Promise(e=>{requestAnimationFrame(()=>{requestAnimationFrame(e)})}),d(t,c),r(t,o),await function(e){return new Promise(t=>{const l=getComputedStyle(e).transitionDuration.split(",")[0],s=1e3*Number(l.replace("s",""));setTimeout(()=>{t()},s)})}(t),d(t,o),d(t,n)}function r(e,t){e.classList.add(...t)}function d(e,t){e.classList.remove(...t)}i.targets=["trixField","scroll"];class c extends e{open(){this.showWrapper(),this.revealableTargets.forEach(e=>{!async function(e,t=null){e.classList.remove("hidden"),await n("enter",e,t)}(e)})}close(){Promise.all(this.revealableTargets.map(e=>async function(e,t=null){await n("leave",e,t),e.classList.add("hidden")}(e))).then(()=>{this.hideWrapper()})}showWrapper(){this.wrapperTarget.classList.remove(this.hiddenClass)}hideWrapper(){this.wrapperTarget.classList.add(this.hiddenClass)}}c.targets=["wrapper","revealable"],c.classes=["hidden"];class o extends e{connect(){this.updateLabel()}toggle(e){var t;this.useAlternateValue=void 0!==(null==e||null==(t=e.detail)?void 0:t.useAlternate)?e.detail.useAlternate:!this.useAlternateValue}useAlternateValueChanged(){this.updateLabel()}updateLabel(){this.hasLabelValue&&this.hasLabelAlternateValue&&this.hasUseAlternateValue&&(this.element.textContent=!0===this.useAlternateValue?this.labelAlternateValue:this.labelValue)}}o.values={label:String,labelAlternate:String,useAlternate:Boolean};const h=[[l,"bulk_action_form_controller.js"],[s,"bulk_actions_controller.js"],[a,"clipboard_controller.js"],[i,"form_controller.js"],[c,"mobile_menu_controller.js"],[o,"text_toggle_controller.js"]].map(function(e){const l=e[0];return{identifier:t(e[1]),controllerConstructor:l}});document.addEventListener("turbo:load",()=>{navigator.userAgent.toLocaleLowerCase().includes("electron")&&document.body.classList.add("electron")});export{h as controllerDefinitions};
|
|
2
2
|
//# sourceMappingURL=bullet-train.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bullet-train.js","sources":["../../../node_modules/@hotwired/stimulus-webpack-helpers/dist/stimulus-webpack-helpers.js","../../javascript/controllers/bulk_action_form_controller.js","../../javascript/controllers/bulk_actions_controller.js","../../javascript/controllers/clipboard_controller.js","../../javascript/controllers/form_controller.js","../../javascript/controllers/mobile_menu_controller.js","../../javascript/controllers/index.js","../../javascript/electron/index.js"],"sourcesContent":["/*\nStimulus Webpack Helpers 1.0.0\nCopyright © 2021 Basecamp, LLC\n */\nfunction definitionsFromContext(context) {\n return context.keys()\n .map((key) => definitionForModuleWithContextAndKey(context, key))\n .filter((value) => value);\n}\nfunction definitionForModuleWithContextAndKey(context, key) {\n const identifier = identifierForContextKey(key);\n if (identifier) {\n return definitionForModuleAndIdentifier(context(key), identifier);\n }\n}\nfunction definitionForModuleAndIdentifier(module, identifier) {\n const controllerConstructor = module.default;\n if (typeof controllerConstructor == \"function\") {\n return { identifier, controllerConstructor };\n }\n}\nfunction identifierForContextKey(key) {\n const logicalName = (key.match(/^(?:\\.\\/)?(.+)(?:[_-]controller\\..+?)$/) || [])[1];\n if (logicalName) {\n return logicalName.replace(/_/g, \"-\").replace(/\\//g, \"--\");\n }\n}\n\nexport { definitionForModuleAndIdentifier, definitionForModuleWithContextAndKey, definitionsFromContext, identifierForContextKey };\n","import { Controller } from '@hotwired/stimulus'\n\nexport default class extends Controller {\n static targets = [ \"button\", \"idsHiddenField\", \"allHiddenField\" ]\n static classes = [ \"hidden\" ]\n static values = {\n buttonIfAll: String,\n buttonIfIds: String,\n ids: Array,\n all: Boolean,\n objectName: String,\n idsFieldName: String,\n allFieldName: String\n }\n\n connect() {\n this.updateAvailability()\n }\n\n updateFormAndSubmit(event) {\n this.recreateIdsHiddenFields()\n this.createOrUpdateAllField()\n return true\n }\n\n updateIds(event) {\n if (event?.detail?.ids) {\n this.idsValue = event.detail.ids\n this.allValue = event.detail.all\n }\n\n this.updateAvailability()\n this.updateButtonLabel()\n }\n\n updateAvailability() {\n this.element.classList.toggle(this.hiddenClass, this.idsValue.length === 0)\n }\n\n updateButtonLabel() {\n let label = this.buttonIfAllValue\n if (this.idsValue.length && this.allValue === false) {\n label = this.buttonIfIdsValue.replace('{num}', this.idsValue.length)\n }\n\n switch (this.buttonTarget.tagName) {\n case 'INPUT': this.buttonTarget.value = label; break;\n default: this.buttonTarget.textContent = label; break;\n }\n }\n\n recreateIdsHiddenFields() {\n this.removeIdsHiddenFields()\n this.createIdsHiddenFields()\n }\n\n removeIdsHiddenFields() {\n this.idsHiddenFieldTargets.forEach(field => {\n this.element.removeChild(field)\n })\n }\n\n createIdsHiddenFields() {\n this.idsValue.forEach(id => {\n let field = document.createElement('input')\n field.type = 'hidden'\n field.name = `${this.objectNameValue}[${this.idsFieldNameValue}][]`\n field.value = id\n this.element.appendChild(field)\n })\n }\n\n createOrUpdateAllField() {\n if (this.hasAllHiddenFieldTarget) {\n this.allHiddenFieldTarget.value = this.allValue? 'true': 'false'\n } else {\n this.createAllField()\n }\n }\n\n createAllField() {\n let field = document.createElement('input')\n field.type = 'hidden'\n field.name = `${this.objectNameValue}[${this.allFieldNameValue}]`\n field.value = this.allValue? 'true': 'false'\n this.element.appendChild(field)\n }\n}","import { Controller } from '@hotwired/stimulus'\n\nexport default class extends Controller {\n static targets = [ \"checkbox\", \"selectAllCheckbox\", \"action\", \"selectableToggle\", \"selectAllLabel\" ]\n static classes = [ \"selectableAvailable\", \"selectable\" ]\n static values = {\n selectable: Boolean\n }\n\n connect() {\n this.element.classList.add(this.selectableAvailableClass)\n }\n\n toggleSelectable() {\n this.selectableValue = !this.selectableValue\n }\n\n updateSelectedIds() {\n this.updateActions()\n this.updateSelectAllCheckbox()\n }\n\n updateActions() {\n this.actionTargets.forEach(actionTarget => {\n actionTarget.dispatchEvent(new CustomEvent('update-ids', { detail: {\n ids: this.selectedIds,\n all: this.allSelected\n }}))\n })\n }\n\n selectAllOrNone(event) {\n if (this.allSelected) {\n this.selectNone()\n } else {\n this.selectAll()\n }\n this.updateSelectAllCheckbox()\n }\n\n selectAll() {\n this.checkboxTargets.forEach(checkbox => {\n checkbox.checked = true\n })\n this.updateActions()\n }\n\n selectNone() {\n this.checkboxTargets.forEach(checkbox => {\n checkbox.checked = false\n })\n this.updateActions()\n }\n\n updateSelectAllCheckbox() {\n let checkbox = this.selectAllCheckboxTarget\n let label = this.selectAllLabelTarget\n\n if (this.allSelected) {\n checkbox.checked = true\n checkbox.indeterminate = false\n label.dispatchEvent(new CustomEvent('toggle', { detail: { useAlternate: true }} ))\n } else if (this.selectedIds.length > 0) {\n checkbox.indeterminate = true\n label.dispatchEvent(new CustomEvent('toggle', { detail: { useAlternate: false }} ))\n } else {\n checkbox.checked = false\n checkbox.indeterminate = false\n label.dispatchEvent(new CustomEvent('toggle', { detail: { useAlternate: false }} ))\n }\n }\n\n selectableValueChanged() {\n this.element.classList.toggle(this.selectableClass, this.selectableValue)\n this.updateToggleLabel()\n }\n\n updateToggleLabel() {\n this.selectableToggleTarget.dispatchEvent(new CustomEvent('toggle', { detail: { useAlternate: this.selectableValue }} ))\n }\n\n get selectedIds() {\n let ids = []\n this.checkboxTargets.forEach(checkbox => {\n if (checkbox.checked) {\n ids.push(checkbox.value)\n }\n })\n return ids\n }\n\n get allSelected() {\n return this.selectedIds.length === this.checkboxTargets.length\n }\n}","import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = ['source', 'input', 'button']\n\n copy() {\n this.inputTarget.value = this.sourceTarget.innerText\n this.inputTarget.select()\n document.execCommand('copy')\n this.buttonTarget.innerHTML = '<i id=\"copied\" class=\"fas fa-check w-4 h-4 block text-green-600\"></i>'\n setTimeout(function () {\n document.getElementById('copied').innerHTML = '<i class=\"far fa-copy w-4 h-4 block text-gray-600\"></i>'\n }, 1500)\n }\n}\n","import { Controller } from \"@hotwired/stimulus\"\n\n// TODO Some of this feels really specific to the conversation messages form. Should we rename this controller?\nexport default class extends Controller {\n static targets = ['trixField', 'scroll']\n\n resetOnSuccess(e){\n if(e.detail.success) {\n e.target.reset();\n }\n }\n\n stripTrix(){\n this.trixFieldTargets.forEach(element => {\n this.removeTrailingNewlines(element.editor)\n this.removeTrailingWhitespace(element.editor)\n // When doing this as part of the form submission, Trix does not update the input element's value attribute fast enough.\n // In order to submit the stripped value, we manually update it here to fix the race condition\n element.parentElement.querySelector(\"input\").value = element.innerHTML\n })\n }\n\n submitOnReturn(e) {\n if((e.metaKey || e.ctrlKey) && e.keyCode == 13) {\n e.preventDefault();\n let form = e.target.closest(\"form\")\n this.submitForm(form)\n }\n }\n\n removeTrailingNewlines = (trixEditor) => {\n if (trixEditor.element.innerHTML.match(/<br><\\/div>$/)) {\n trixEditor.element.innerHTML = trixEditor.element.innerHTML.slice(0, -10) + \"</div>\"\n this.removeTrailingNewlines(trixEditor)\n }\n }\n\n removeTrailingWhitespace = (trixEditor) => {\n if (trixEditor.element.innerHTML.match(/ <\\/div>$/)) {\n trixEditor.element.innerHTML = trixEditor.element.innerHTML.slice(0, -12) + \"</div>\"\n this.removeTrailingWhitespace(trixEditor)\n } else if (trixEditor.element.innerHTML.match(/ <\\/div>$/)) {\n trixEditor.element.innerHTML = trixEditor.element.innerHTML.slice(0, -13) + \"</div>\"\n this.removeTrailingWhitespace(trixEditor)\n }\n }\n\n submitForm(form) {\n // Right now, Safari and IE don't support the requestSubmit method which is required for Turbo\n // Doing form.submit() doesn't actually fire the submit event which Turbo needs\n if (form.requestSubmit) {\n form.requestSubmit()\n } else {\n form.querySelector(\"[type=submit]\").click()\n }\n }\n}\n","import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = [ \"wrapper\"]\n static classes = [ \"hidden\" ] // necessary because stimulus-reveal will mess with the [hidden] attribute on the wrapper\n static values = {\n showEventName: String,\n hideEventName: String,\n }\n\n toggle() {\n const eventName = this.isWrapperHidden? this.showEventNameValue: this.hideEventNameValue\n if (this.isWrapperHidden) {\n this.showWrapper()\n }\n \n this.wrapperTarget.dispatchEvent(new CustomEvent(eventName))\n }\n \n get isWrapperHidden() {\n return this.wrapperTarget.classList.contains(this.hiddenClass)\n }\n \n showWrapper() {\n this.wrapperTarget.classList.remove(this.hiddenClass)\n }\n \n hideWrapper() {\n this.wrapperTarget.classList.add(this.hiddenClass)\n }\n}","import { identifierForContextKey } from \"@hotwired/stimulus-webpack-helpers\"\n\nimport BulkActionFormController from './bulk_action_form_controller'\nimport BulkActionsController from './bulk_actions_controller'\nimport ClipboardController from './clipboard_controller'\nimport FormController from './form_controller'\nimport MobileMenuController from './mobile_menu_controller'\n\nexport const controllerDefinitions = [\n [BulkActionFormController, 'bulk_action_form_controller.js'],\n [BulkActionsController, 'bulk_actions_controller.js'],\n [ClipboardController, 'clipboard_controller.js'],\n [FormController, 'form_controller.js'],\n [MobileMenuController, 'mobile_menu_controller.js'],\n].map(function(d) {\n const key = d[1]\n const controller = d[0]\n return {\n identifier: identifierForContextKey(key),\n controllerConstructor: controller\n }\n})\n","document.addEventListener(\"turbo:load\", () => {\n if (navigator.userAgent.toLocaleLowerCase().includes('electron')) {\n document.body.classList.add('electron')\n }\n})"],"names":["identifierForContextKey","key","logicalName","match","replace","_class","connect","this","updateAvailability","updateFormAndSubmit","event","recreateIdsHiddenFields","createOrUpdateAllField","updateIds","_event$detail","detail","ids","idsValue","allValue","all","updateButtonLabel","element","classList","toggle","hiddenClass","length","label","buttonIfAllValue","buttonIfIdsValue","buttonTarget","tagName","value","textContent","removeIdsHiddenFields","createIdsHiddenFields","idsHiddenFieldTargets","forEach","field","removeChild","id","document","createElement","type","name","objectNameValue","idsFieldNameValue","appendChild","hasAllHiddenFieldTarget","allHiddenFieldTarget","createAllField","allFieldNameValue","targets","classes","values","buttonIfAll","String","buttonIfIds","Array","Boolean","objectName","idsFieldName","allFieldName","Controller","add","selectableAvailableClass","toggleSelectable","selectableValue","updateSelectedIds","updateActions","updateSelectAllCheckbox","actionTargets","actionTarget","dispatchEvent","selectedIds","allSelected","selectAllOrNone","selectNone","selectAll","checkboxTargets","checkbox","checked","selectAllCheckboxTarget","selectAllLabelTarget","indeterminate","CustomEvent","useAlternate","selectableValueChanged","selectableClass","updateToggleLabel","selectableToggleTarget","push","selectable","copy","inputTarget","sourceTarget","innerText","select","execCommand","innerHTML","setTimeout","getElementById","removeTrailingNewlines","trixEditor","slice","removeTrailingWhitespace","resetOnSuccess","e","success","target","reset","stripTrix","trixFieldTargets","editor","parentElement","querySelector","submitOnReturn","metaKey","ctrlKey","keyCode","preventDefault","form","closest","submitForm","requestSubmit","click","isWrapperHidden","showEventNameValue","hideEventNameValue","showWrapper","wrapperTarget","eventName","contains","remove","hideWrapper","showEventName","hideEventName","controllerDefinitions","BulkActionFormController","BulkActionsController","ClipboardController","FormController","MobileMenuController","map","d","identifier","controllerConstructor","controller","addEventListener","navigator","userAgent","toLocaleLowerCase","includes","body"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bullet-train.js","sources":["../../../node_modules/@hotwired/stimulus-webpack-helpers/dist/stimulus-webpack-helpers.js","../../javascript/controllers/bulk_action_form_controller.js","../../javascript/controllers/bulk_actions_controller.js","../../javascript/controllers/clipboard_controller.js","../../javascript/controllers/form_controller.js","../../../node_modules/el-transition/index.js","../../javascript/controllers/mobile_menu_controller.js","../../javascript/controllers/text_toggle_controller.js","../../javascript/controllers/index.js","../../javascript/electron/index.js"],"sourcesContent":["/*\nStimulus Webpack Helpers 1.0.0\nCopyright © 2021 Basecamp, LLC\n */\nfunction definitionsFromContext(context) {\n return context.keys()\n .map((key) => definitionForModuleWithContextAndKey(context, key))\n .filter((value) => value);\n}\nfunction definitionForModuleWithContextAndKey(context, key) {\n const identifier = identifierForContextKey(key);\n if (identifier) {\n return definitionForModuleAndIdentifier(context(key), identifier);\n }\n}\nfunction definitionForModuleAndIdentifier(module, identifier) {\n const controllerConstructor = module.default;\n if (typeof controllerConstructor == \"function\") {\n return { identifier, controllerConstructor };\n }\n}\nfunction identifierForContextKey(key) {\n const logicalName = (key.match(/^(?:\\.\\/)?(.+)(?:[_-]controller\\..+?)$/) || [])[1];\n if (logicalName) {\n return logicalName.replace(/_/g, \"-\").replace(/\\//g, \"--\");\n }\n}\n\nexport { definitionForModuleAndIdentifier, definitionForModuleWithContextAndKey, definitionsFromContext, identifierForContextKey };\n","import { Controller } from '@hotwired/stimulus'\n\nexport default class extends Controller {\n static targets = [ \"button\", \"idsHiddenField\", \"allHiddenField\" ]\n static classes = [ \"hidden\" ]\n static values = {\n buttonIfAll: String,\n buttonIfIds: String,\n ids: Array,\n all: Boolean,\n objectName: String,\n idsFieldName: String,\n allFieldName: String\n }\n\n connect() {\n this.updateAvailability()\n }\n\n updateFormAndSubmit(event) {\n this.recreateIdsHiddenFields()\n this.createOrUpdateAllField()\n return true\n }\n\n updateIds(event) {\n if (event?.detail?.ids) {\n this.idsValue = event.detail.ids\n this.allValue = event.detail.all\n }\n\n this.updateAvailability()\n this.updateButtonLabel()\n }\n\n updateAvailability() {\n this.element.classList.toggle(this.hiddenClass, this.idsValue.length === 0)\n }\n\n updateButtonLabel() {\n let label = this.buttonIfAllValue\n if (this.idsValue.length && this.allValue === false) {\n label = this.buttonIfIdsValue.replace('{num}', this.idsValue.length)\n }\n\n switch (this.buttonTarget.tagName) {\n case 'INPUT': this.buttonTarget.value = label; break;\n default: this.buttonTarget.textContent = label; break;\n }\n }\n\n recreateIdsHiddenFields() {\n this.removeIdsHiddenFields()\n this.createIdsHiddenFields()\n }\n\n removeIdsHiddenFields() {\n this.idsHiddenFieldTargets.forEach(field => {\n this.element.removeChild(field)\n })\n }\n\n createIdsHiddenFields() {\n this.idsValue.forEach(id => {\n let field = document.createElement('input')\n field.type = 'hidden'\n field.name = `${this.objectNameValue}[${this.idsFieldNameValue}][]`\n field.value = id\n this.element.appendChild(field)\n })\n }\n\n createOrUpdateAllField() {\n if (this.hasAllHiddenFieldTarget) {\n this.allHiddenFieldTarget.value = this.allValue? 'true': 'false'\n } else {\n this.createAllField()\n }\n }\n\n createAllField() {\n let field = document.createElement('input')\n field.type = 'hidden'\n field.name = `${this.objectNameValue}[${this.allFieldNameValue}]`\n field.value = this.allValue? 'true': 'false'\n this.element.appendChild(field)\n }\n}","import { Controller } from '@hotwired/stimulus'\n\nexport default class extends Controller {\n static targets = [ \"checkbox\", \"selectAllCheckbox\", \"action\", \"selectableToggle\", \"selectAllLabel\" ]\n static classes = [ \"selectableAvailable\", \"selectable\" ]\n static values = {\n selectable: Boolean\n }\n\n connect() {\n this.element.classList.add(this.selectableAvailableClass)\n }\n\n toggleSelectable() {\n this.selectableValue = !this.selectableValue\n }\n\n updateSelectedIds() {\n this.updateActions()\n this.updateSelectAllCheckbox()\n }\n\n updateActions() {\n this.actionTargets.forEach(actionTarget => {\n actionTarget.dispatchEvent(new CustomEvent('update-ids', { detail: {\n ids: this.selectedIds,\n all: this.allSelected\n }}))\n })\n }\n\n selectAllOrNone(event) {\n if (this.allSelected) {\n this.selectNone()\n } else {\n this.selectAll()\n }\n this.updateSelectAllCheckbox()\n }\n\n selectAll() {\n this.checkboxTargets.forEach(checkbox => {\n checkbox.checked = true\n })\n this.updateActions()\n }\n\n selectNone() {\n this.checkboxTargets.forEach(checkbox => {\n checkbox.checked = false\n })\n this.updateActions()\n }\n\n updateSelectAllCheckbox() {\n let checkbox = this.selectAllCheckboxTarget\n let label = this.selectAllLabelTarget\n\n if (this.allSelected) {\n checkbox.checked = true\n checkbox.indeterminate = false\n label.dispatchEvent(new CustomEvent('toggle', { detail: { useAlternate: true }} ))\n } else if (this.selectedIds.length > 0) {\n checkbox.indeterminate = true\n label.dispatchEvent(new CustomEvent('toggle', { detail: { useAlternate: false }} ))\n } else {\n checkbox.checked = false\n checkbox.indeterminate = false\n label.dispatchEvent(new CustomEvent('toggle', { detail: { useAlternate: false }} ))\n }\n }\n\n selectableValueChanged() {\n this.element.classList.toggle(this.selectableClass, this.selectableValue)\n this.updateToggleLabel()\n }\n\n updateToggleLabel() {\n this.selectableToggleTarget.dispatchEvent(new CustomEvent('toggle', { detail: { useAlternate: this.selectableValue }} ))\n }\n\n get selectedIds() {\n let ids = []\n this.checkboxTargets.forEach(checkbox => {\n if (checkbox.checked) {\n ids.push(checkbox.value)\n }\n })\n return ids\n }\n\n get allSelected() {\n return this.selectedIds.length === this.checkboxTargets.length\n }\n}","import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static targets = ['source', 'input', 'button']\n\n copy() {\n this.inputTarget.value = this.sourceTarget.innerText\n this.inputTarget.select()\n document.execCommand('copy')\n this.buttonTarget.innerHTML = '<i id=\"copied\" class=\"fas fa-check w-4 h-4 block text-green-600\"></i>'\n setTimeout(function () {\n document.getElementById('copied').innerHTML = '<i class=\"far fa-copy w-4 h-4 block text-gray-600\"></i>'\n }, 1500)\n }\n}\n","import { Controller } from \"@hotwired/stimulus\"\n\n// TODO Some of this feels really specific to the conversation messages form. Should we rename this controller?\nexport default class extends Controller {\n static targets = ['trixField', 'scroll']\n\n resetOnSuccess(e){\n if(e.detail.success) {\n e.target.reset();\n }\n }\n\n stripTrix(){\n this.trixFieldTargets.forEach(element => {\n this.removeTrailingNewlines(element.editor)\n this.removeTrailingWhitespace(element.editor)\n // When doing this as part of the form submission, Trix does not update the input element's value attribute fast enough.\n // In order to submit the stripped value, we manually update it here to fix the race condition\n element.parentElement.querySelector(\"input\").value = element.innerHTML\n })\n }\n\n submitOnReturn(e) {\n if((e.metaKey || e.ctrlKey) && e.keyCode == 13) {\n e.preventDefault();\n let form = e.target.closest(\"form\")\n this.submitForm(form)\n }\n }\n\n removeTrailingNewlines = (trixEditor) => {\n if (trixEditor.element.innerHTML.match(/<br><\\/div>$/)) {\n trixEditor.element.innerHTML = trixEditor.element.innerHTML.slice(0, -10) + \"</div>\"\n this.removeTrailingNewlines(trixEditor)\n }\n }\n\n removeTrailingWhitespace = (trixEditor) => {\n if (trixEditor.element.innerHTML.match(/ <\\/div>$/)) {\n trixEditor.element.innerHTML = trixEditor.element.innerHTML.slice(0, -12) + \"</div>\"\n this.removeTrailingWhitespace(trixEditor)\n } else if (trixEditor.element.innerHTML.match(/ <\\/div>$/)) {\n trixEditor.element.innerHTML = trixEditor.element.innerHTML.slice(0, -13) + \"</div>\"\n this.removeTrailingWhitespace(trixEditor)\n }\n }\n\n submitForm(form) {\n // Right now, Safari and IE don't support the requestSubmit method which is required for Turbo\n // Doing form.submit() doesn't actually fire the submit event which Turbo needs\n if (form.requestSubmit) {\n form.requestSubmit()\n } else {\n form.querySelector(\"[type=submit]\").click()\n }\n }\n}\n","export async function enter(element, transitionName = null) {\n element.classList.remove('hidden')\n await transition('enter', element, transitionName)\n}\n\nexport async function leave(element, transitionName = null) {\n await transition('leave', element, transitionName)\n element.classList.add('hidden')\n}\n\nexport async function toggle(element, transitionName = null) {\n if (element.classList.contains('hidden')) {\n await enter(element, transitionName)\n } else {\n await leave(element, transitionName)\n }\n}\n\nasync function transition(direction, element, animation) {\n const dataset = element.dataset\n const animationClass = animation ? `${animation}-${direction}` : direction\n let transition = `transition${direction.charAt(0).toUpperCase() + direction.slice(1)}`\n const genesis = dataset[transition] ? dataset[transition].split(\" \") : [animationClass]\n const start = dataset[`${transition}Start`] ? dataset[`${transition}Start`].split(\" \") : [`${animationClass}-start`]\n const end = dataset[`${transition}End`] ? dataset[`${transition}End`].split(\" \") : [`${animationClass}-end`]\n\n addClasses(element, genesis)\n addClasses(element, start)\n await nextFrame()\n removeClasses(element, start)\n addClasses(element, end);\n await afterTransition(element)\n removeClasses(element, end)\n removeClasses(element, genesis)\n}\n\nfunction addClasses(element, classes) {\n element.classList.add(...classes)\n}\n\nfunction removeClasses(element, classes) {\n element.classList.remove(...classes)\n}\n\nfunction nextFrame() {\n return new Promise(resolve => {\n requestAnimationFrame(() => {\n requestAnimationFrame(resolve)\n });\n });\n}\n\nfunction afterTransition(element) {\n return new Promise(resolve => {\n // safari return string with comma separate values\n const computedDuration = getComputedStyle(element).transitionDuration.split(\",\")[0]\n const duration = Number(computedDuration.replace('s', '')) * 1000;\n setTimeout(() => {\n resolve()\n }, duration)\n });\n}","import { Controller } from \"@hotwired/stimulus\"\nimport { enter, leave } from \"el-transition\"\n\nexport default class extends Controller {\n static targets = [ \"wrapper\", \"revealable\"]\n static classes = [ \"hidden\" ] // necessary because we're always hiding the mobile menu on larger screens and this is the class used for only mobile screen sizes\n \n open() {\n this.showWrapper()\n this.revealableTargets.forEach(revealableTarget => {\n enter(revealableTarget)\n })\n }\n \n close() {\n Promise.all(\n this.revealableTargets.map(revealableTarget => {\n return leave(revealableTarget)\n })\n ).then(() => {\n this.hideWrapper()\n })\n \n }\n \n showWrapper() {\n this.wrapperTarget.classList.remove(this.hiddenClass)\n }\n \n hideWrapper() {\n this.wrapperTarget.classList.add(this.hiddenClass)\n }\n}","import { Controller } from \"@hotwired/stimulus\"\n\nexport default class extends Controller {\n static values = {\n label: String,\n labelAlternate: String,\n useAlternate: Boolean,\n }\n\n connect() {\n this.updateLabel()\n }\n\n toggle(event) {\n if (undefined !== event?.detail?.useAlternate) {\n this.useAlternateValue = event.detail.useAlternate\n } else {\n this.useAlternateValue = !this.useAlternateValue\n }\n }\n\n useAlternateValueChanged() {\n this.updateLabel()\n }\n\n updateLabel() {\n if (!this.hasLabelValue || !this.hasLabelAlternateValue || !this.hasUseAlternateValue) {\n return\n }\n\n this.element.textContent = this.useAlternateValue === true ? this.labelAlternateValue : this.labelValue\n }\n}\n","import { identifierForContextKey } from \"@hotwired/stimulus-webpack-helpers\"\n\nimport BulkActionFormController from './bulk_action_form_controller'\nimport BulkActionsController from './bulk_actions_controller'\nimport ClipboardController from './clipboard_controller'\nimport FormController from './form_controller'\nimport MobileMenuController from './mobile_menu_controller'\nimport TextToggleController from './text_toggle_controller'\n\nexport const controllerDefinitions = [\n [BulkActionFormController, 'bulk_action_form_controller.js'],\n [BulkActionsController, 'bulk_actions_controller.js'],\n [ClipboardController, 'clipboard_controller.js'],\n [FormController, 'form_controller.js'],\n [MobileMenuController, 'mobile_menu_controller.js'],\n [TextToggleController, 'text_toggle_controller.js'],\n].map(function(d) {\n const key = d[1]\n const controller = d[0]\n return {\n identifier: identifierForContextKey(key),\n controllerConstructor: controller\n }\n})\n","document.addEventListener(\"turbo:load\", () => {\n if (navigator.userAgent.toLocaleLowerCase().includes('electron')) {\n document.body.classList.add('electron')\n }\n})"],"names":["identifierForContextKey","key","logicalName","match","replace","_class","connect","this","updateAvailability","updateFormAndSubmit","event","recreateIdsHiddenFields","createOrUpdateAllField","updateIds","_event$detail","detail","ids","idsValue","allValue","all","updateButtonLabel","element","classList","toggle","hiddenClass","length","label","buttonIfAllValue","buttonIfIdsValue","buttonTarget","tagName","value","textContent","removeIdsHiddenFields","createIdsHiddenFields","idsHiddenFieldTargets","forEach","field","removeChild","id","document","createElement","type","name","objectNameValue","idsFieldNameValue","appendChild","hasAllHiddenFieldTarget","allHiddenFieldTarget","createAllField","allFieldNameValue","targets","classes","values","buttonIfAll","String","buttonIfIds","Array","Boolean","objectName","idsFieldName","allFieldName","Controller","add","selectableAvailableClass","toggleSelectable","selectableValue","updateSelectedIds","updateActions","updateSelectAllCheckbox","actionTargets","actionTarget","dispatchEvent","selectedIds","allSelected","selectAllOrNone","selectNone","selectAll","checkboxTargets","checkbox","checked","selectAllCheckboxTarget","selectAllLabelTarget","indeterminate","CustomEvent","useAlternate","selectableValueChanged","selectableClass","updateToggleLabel","selectableToggleTarget","push","selectable","copy","inputTarget","sourceTarget","innerText","select","execCommand","innerHTML","setTimeout","getElementById","removeTrailingNewlines","trixEditor","slice","removeTrailingWhitespace","resetOnSuccess","e","success","target","reset","stripTrix","trixFieldTargets","editor","parentElement","querySelector","submitOnReturn","metaKey","ctrlKey","keyCode","preventDefault","form","closest","submitForm","requestSubmit","click","async","transition","direction","animation","dataset","animationClass","charAt","toUpperCase","genesis","split","start","end","addClasses","Promise","resolve","requestAnimationFrame","removeClasses","computedDuration","getComputedStyle","transitionDuration","duration","Number","afterTransition","remove","open","showWrapper","revealableTargets","revealableTarget","transitionName","enter","close","map","leave","then","hideWrapper","wrapperTarget","updateLabel","useAlternateValue","undefined","useAlternateValueChanged","hasLabelValue","hasLabelAlternateValue","hasUseAlternateValue","labelAlternateValue","labelValue","labelAlternate","controllerDefinitions","BulkActionFormController","BulkActionsController","ClipboardController","FormController","MobileMenuController","TextToggleController","d","controller","identifier","controllerConstructor","addEventListener","navigator","userAgent","toLocaleLowerCase","includes","body"],"mappings":"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"}
|
|
@@ -60,17 +60,24 @@ module Account::Invitations::ControllerBase
|
|
|
60
60
|
# assume the user needs to create an account.
|
|
61
61
|
# this is not the default for devise, but a sensible default here.
|
|
62
62
|
redirect_to new_user_registration_path
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
|
|
64
|
+
# session[:invitation_uuid] should only be present if the user is registering for the first time.
|
|
65
|
+
elsif (@invitation = Invitation.find_by(uuid: session[:invitation_uuid] || params[:id]))
|
|
66
|
+
session.delete(:invitation_uuid) if session[:invitation_uuid].present?
|
|
67
|
+
|
|
68
|
+
if @invitation
|
|
69
|
+
@team = @invitation.team
|
|
70
|
+
if @invitation.is_for?(current_user) || request.post?
|
|
71
|
+
@invitation.accept_for(current_user)
|
|
72
|
+
redirect_to account_dashboard_path, notice: I18n.t("invitations.notifications.welcome", team_name: @team.name)
|
|
73
|
+
else
|
|
74
|
+
redirect_to account_invitation_path(@invitation.uuid)
|
|
75
|
+
end
|
|
68
76
|
else
|
|
69
77
|
redirect_to account_invitation_path(@invitation.uuid)
|
|
70
78
|
end
|
|
71
79
|
else
|
|
72
80
|
redirect_to account_dashboard_path
|
|
73
|
-
|
|
74
81
|
end
|
|
75
82
|
end
|
|
76
83
|
|
|
@@ -33,8 +33,7 @@ module Controllers::Base
|
|
|
33
33
|
end
|
|
34
34
|
else
|
|
35
35
|
respond_to do |format|
|
|
36
|
-
|
|
37
|
-
format.html { redirect_to [:account, current_user.teams.first], alert: exception.message }
|
|
36
|
+
format.html { redirect_to account_teams_url, alert: exception.message }
|
|
38
37
|
end
|
|
39
38
|
end
|
|
40
39
|
end
|
|
@@ -19,14 +19,11 @@ module Registrations::ControllerBase
|
|
|
19
19
|
|
|
20
20
|
# if current_user is defined, that means they were successful registering.
|
|
21
21
|
if current_user
|
|
22
|
-
|
|
23
|
-
# TODO i think this might be redundant. we've added a hook into `session["user_return_to"]` in the
|
|
24
|
-
# `invitations#accept` action and that might be enough to get them where they're supposed to be after
|
|
25
|
-
# either creating a new account or signing into an existing account.
|
|
26
|
-
handle_outstanding_invitation
|
|
27
|
-
|
|
28
22
|
# if the user doesn't have a team at this point, create one.
|
|
29
|
-
|
|
23
|
+
# If the user is accepting an invitation, then the user's current_team is populated
|
|
24
|
+
# with the information attached to their invitation via `@invitation.accept_for` later on,
|
|
25
|
+
# so we don't have to create a default team for them here.
|
|
26
|
+
unless current_user.teams.any? || session[:invitation_uuid].present?
|
|
30
27
|
current_user.create_default_team
|
|
31
28
|
end
|
|
32
29
|
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
module Sessions::ControllerBase
|
|
2
2
|
extend ActiveSupport::Concern
|
|
3
3
|
|
|
4
|
-
included do
|
|
5
|
-
# TODO I'm not sure why the sign-in page started throwing a `ActionController::InvalidAuthenticityToken`. I'm doing
|
|
6
|
-
# this as a temporary workaround, but this shouldn't be here long-term.
|
|
7
|
-
skip_before_action :verify_authenticity_token, only: [:create]
|
|
8
|
-
end
|
|
9
|
-
|
|
10
4
|
def pre_otp
|
|
11
5
|
if (@email = params["user"]["email"].downcase.strip.presence)
|
|
12
6
|
@user = User.find_by(email: @email)
|
|
@@ -27,10 +27,6 @@ module Account::FormsHelper
|
|
|
27
27
|
string.present? ? string : nil
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
def id_for(form, method)
|
|
31
|
-
[form.object.class.name, form.index, method].compact.join("_").underscore
|
|
32
|
-
end
|
|
33
|
-
|
|
34
30
|
def model_key(form)
|
|
35
31
|
form.object.class.name.pluralize.underscore
|
|
36
32
|
end
|
|
@@ -1,17 +1,2 @@
|
|
|
1
1
|
module InvitationsHelper
|
|
2
|
-
def handle_outstanding_invitation
|
|
3
|
-
# was this user registering to claim an invitation?
|
|
4
|
-
if session[:invitation_uuid].present?
|
|
5
|
-
|
|
6
|
-
# try to find the invitation, if it still exists.
|
|
7
|
-
invitation = Invitation.find_by_uuid(session[:invitation_uuid])
|
|
8
|
-
|
|
9
|
-
# if the invitation was found, claim it for this user.
|
|
10
|
-
invitation&.accept_for(current_user)
|
|
11
|
-
|
|
12
|
-
# remove the uuid from the session.
|
|
13
|
-
session.delete(:invitation_uuid)
|
|
14
|
-
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
2
|
end
|
|
@@ -5,6 +5,7 @@ import BulkActionsController from './bulk_actions_controller'
|
|
|
5
5
|
import ClipboardController from './clipboard_controller'
|
|
6
6
|
import FormController from './form_controller'
|
|
7
7
|
import MobileMenuController from './mobile_menu_controller'
|
|
8
|
+
import TextToggleController from './text_toggle_controller'
|
|
8
9
|
|
|
9
10
|
export const controllerDefinitions = [
|
|
10
11
|
[BulkActionFormController, 'bulk_action_form_controller.js'],
|
|
@@ -12,6 +13,7 @@ export const controllerDefinitions = [
|
|
|
12
13
|
[ClipboardController, 'clipboard_controller.js'],
|
|
13
14
|
[FormController, 'form_controller.js'],
|
|
14
15
|
[MobileMenuController, 'mobile_menu_controller.js'],
|
|
16
|
+
[TextToggleController, 'text_toggle_controller.js'],
|
|
15
17
|
].map(function(d) {
|
|
16
18
|
const key = d[1]
|
|
17
19
|
const controller = d[0]
|
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
import { Controller } from "@hotwired/stimulus"
|
|
2
|
+
import { enter, leave } from "el-transition"
|
|
2
3
|
|
|
3
4
|
export default class extends Controller {
|
|
4
|
-
static targets = [ "wrapper"]
|
|
5
|
-
static classes = [ "hidden" ] // necessary because
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const eventName = this.isWrapperHidden? this.showEventNameValue: this.hideEventNameValue
|
|
13
|
-
if (this.isWrapperHidden) {
|
|
14
|
-
this.showWrapper()
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
this.wrapperTarget.dispatchEvent(new CustomEvent(eventName))
|
|
5
|
+
static targets = [ "wrapper", "revealable"]
|
|
6
|
+
static classes = [ "hidden" ] // necessary because we're always hiding the mobile menu on larger screens and this is the class used for only mobile screen sizes
|
|
7
|
+
|
|
8
|
+
open() {
|
|
9
|
+
this.showWrapper()
|
|
10
|
+
this.revealableTargets.forEach(revealableTarget => {
|
|
11
|
+
enter(revealableTarget)
|
|
12
|
+
})
|
|
18
13
|
}
|
|
19
14
|
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
close() {
|
|
16
|
+
Promise.all(
|
|
17
|
+
this.revealableTargets.map(revealableTarget => {
|
|
18
|
+
return leave(revealableTarget)
|
|
19
|
+
})
|
|
20
|
+
).then(() => {
|
|
21
|
+
this.hideWrapper()
|
|
22
|
+
})
|
|
23
|
+
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
showWrapper() {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
|
2
|
+
|
|
3
|
+
export default class extends Controller {
|
|
4
|
+
static values = {
|
|
5
|
+
label: String,
|
|
6
|
+
labelAlternate: String,
|
|
7
|
+
useAlternate: Boolean,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
connect() {
|
|
11
|
+
this.updateLabel()
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
toggle(event) {
|
|
15
|
+
if (undefined !== event?.detail?.useAlternate) {
|
|
16
|
+
this.useAlternateValue = event.detail.useAlternate
|
|
17
|
+
} else {
|
|
18
|
+
this.useAlternateValue = !this.useAlternateValue
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
useAlternateValueChanged() {
|
|
23
|
+
this.updateLabel()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
updateLabel() {
|
|
27
|
+
if (!this.hasLabelValue || !this.hasLabelAlternateValue || !this.hasUseAlternateValue) {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
this.element.textContent = this.useAlternateValue === true ? this.labelAlternateValue : this.labelValue
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require "rake"
|
|
2
|
+
|
|
1
3
|
module Records::Base
|
|
2
4
|
extend ActiveSupport::Concern
|
|
3
5
|
|
|
@@ -65,4 +67,12 @@ module Records::Base
|
|
|
65
67
|
# parent_key = model_name.reflect_on_all_associations(:belongs_to).first.name
|
|
66
68
|
raise "You're trying to use a feature that requires #{model_name} to have a `collection` method defined that returns the Active Record association that this model belongs to within its parent object."
|
|
67
69
|
end
|
|
70
|
+
|
|
71
|
+
def seeding?
|
|
72
|
+
rake_tasks = ObjectSpace.each_object(Rake::Task)
|
|
73
|
+
return false if rake_tasks.count.zero?
|
|
74
|
+
|
|
75
|
+
db_seed_task = rake_tasks.find { |task| task.name.match?(/^db:seed$/) }
|
|
76
|
+
db_seed_task.already_invoked
|
|
77
|
+
end
|
|
68
78
|
end
|
|
@@ -37,11 +37,8 @@ module Users::Base
|
|
|
37
37
|
after_update :set_teams_time_zone
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
# TODO we need to update this to some sort of invalid email address or something
|
|
41
|
-
# people know to ignore. it would be a security problem to have this pointing
|
|
42
|
-
# at anybody's real email address.
|
|
43
40
|
def email_is_oauth_placeholder?
|
|
44
|
-
!!email.match(/noreply
|
|
41
|
+
!!email.match(/noreply@\h{32}\.example\.com/)
|
|
45
42
|
end
|
|
46
43
|
|
|
47
44
|
def label_string
|
|
@@ -42,12 +42,12 @@
|
|
|
42
42
|
<%= form.submit t('global.buttons.sign_in'), class: 'button full' %>
|
|
43
43
|
</div>
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
</
|
|
50
|
-
|
|
45
|
+
<% if devise_mapping.rememberable? %>
|
|
46
|
+
<div class="flex items-center">
|
|
47
|
+
<%= form.check_box :remember_me, class: "h-4 w-4 text-blue focus:ring-blue-dark border-gray-300 rounded" %>
|
|
48
|
+
<%= form.label :remember_me, class: "ml-2 block" %>
|
|
49
|
+
</div>
|
|
50
|
+
<% end %>
|
|
51
51
|
<% end %>
|
|
52
52
|
<% end %>
|
|
53
53
|
<% end %>
|
|
@@ -37,8 +37,6 @@
|
|
|
37
37
|
<div class="h-screen md:h-auto overflow-hidden md:rounded-lg flex shadow"
|
|
38
38
|
data-controller="mobile-menu"
|
|
39
39
|
data-mobile-menu-hidden-class="hidden"
|
|
40
|
-
data-mobile-menu-show-event-name-value="mobile-menu:show"
|
|
41
|
-
data-mobile-menu-hide-event-name-value="mobile-menu:hide"
|
|
42
40
|
>
|
|
43
41
|
|
|
44
42
|
<% menu = capture do %>
|
|
@@ -47,7 +45,7 @@
|
|
|
47
45
|
|
|
48
46
|
<div class="lg:hidden absolute right-0">
|
|
49
47
|
<button class="ml-1 flex items-center justify-center h-10 w-10 rounded-full focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white"
|
|
50
|
-
data-action="
|
|
48
|
+
data-action="mobile-menu#close"
|
|
51
49
|
>
|
|
52
50
|
<span class="sr-only">Close Application Menu</span>
|
|
53
51
|
<svg class="h-6 w-6 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
|
@@ -265,20 +263,12 @@
|
|
|
265
263
|
|
|
266
264
|
<div class="lg:hidden hidden"
|
|
267
265
|
data-mobile-menu-target="wrapper"
|
|
268
|
-
|
|
269
|
-
data-controller="reveal"
|
|
270
|
-
data-reveal-away-value="true"
|
|
271
|
-
data-reveal-hide-keys-value="escape"
|
|
272
|
-
|
|
273
|
-
data-action="mobile-menu:show->reveal#show mobile-menu:hide->reveal#hide mobile-menu-toggle->reveal#toggle reveal:hidden->mobile-menu#hideWrapper"
|
|
274
266
|
>
|
|
275
267
|
<div class="fixed inset-0 flex z-40">
|
|
276
268
|
<button
|
|
277
|
-
data-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
data-reveal
|
|
281
|
-
data-transition
|
|
269
|
+
data-mobile-menu-target="revealable"
|
|
270
|
+
data-action="mobile-menu#close"
|
|
271
|
+
|
|
282
272
|
data-transition-enter="transition-opacity ease-linear duration-200"
|
|
283
273
|
data-transition-enter-start="opacity-0"
|
|
284
274
|
data-transition-enter-end="opacity-100"
|
|
@@ -291,9 +281,8 @@
|
|
|
291
281
|
<div class="absolute inset-0 bg-light-gradient opacity-75"></div>
|
|
292
282
|
</button>
|
|
293
283
|
<div
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
data-transition
|
|
284
|
+
data-mobile-menu-target="revealable"
|
|
285
|
+
|
|
297
286
|
data-transition-enter="transition ease-in-out duration-200 transform"
|
|
298
287
|
data-transition-enter-start="-translate-x-full"
|
|
299
288
|
data-transition-enter-end="translate-x-0"
|
|
@@ -319,7 +308,7 @@
|
|
|
319
308
|
<main class="flex-1 relative z-0 overflow-y-auto focus:outline-none" tabindex="0">
|
|
320
309
|
|
|
321
310
|
<button class="lg:hidden h-12 w-12 ml-1 flex-none inline-flex items-center justify-center rounded-md text-gray-500 hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-blue"
|
|
322
|
-
data-action="mobile-menu#
|
|
311
|
+
data-action="mobile-menu#open"
|
|
323
312
|
>
|
|
324
313
|
<span class="sr-only">Open Application Menu</span>
|
|
325
314
|
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Examples for the `super_select` Field Partial
|
|
2
2
|
|
|
3
|
-
The `super_select` partial provides a wonderful default UI (in contrast to the vanilla browser experience for this, which is horrible) with optional search and multi-select functionality out-of-the-box. It invokes the [Select2]
|
|
3
|
+
The `super_select` partial provides a wonderful default UI (in contrast to the vanilla browser experience for this, which is horrible) with optional search and multi-select functionality out-of-the-box. It invokes the [Select2][select2] library to provide you these features.
|
|
4
4
|
|
|
5
5
|
## Define Available Buttons via Localization Yaml
|
|
6
6
|
|
|
@@ -66,4 +66,62 @@ Here is an example allowing a new option to be entered by the user:
|
|
|
66
66
|
other_options: {accepts_new: true} %>
|
|
67
67
|
</code></pre>
|
|
68
68
|
|
|
69
|
-
Note: this will set the option `value` (which will be submitted to the server) to the entered text.
|
|
69
|
+
Note: this will set the option `value` (which will be submitted to the server) to the entered text.
|
|
70
|
+
## Events
|
|
71
|
+
|
|
72
|
+
All events dispatched from the `super_select` partial are [Select2's jQuery events][select2_events] re-dispatched as native DOM events with the following caveats:
|
|
73
|
+
|
|
74
|
+
1. The native DOM event name is pre-pended with `$`
|
|
75
|
+
2. The original jQuery event is passed through under `event.detail.event`
|
|
76
|
+
|
|
77
|
+
| Select2 event name | DOM event name |
|
|
78
|
+
|---------------------|----------------------|
|
|
79
|
+
| change | $change |
|
|
80
|
+
| select2:closing | $select2:closing |
|
|
81
|
+
| select2:close | $select2:close |
|
|
82
|
+
| select2:opening | $select2:opening |
|
|
83
|
+
| select2:open | $select2:open |
|
|
84
|
+
| select2:selecting | $select2:selecting |
|
|
85
|
+
| select2:select | $select2:select |
|
|
86
|
+
| select2:unselecting | $select2:unselecting |
|
|
87
|
+
| select2:unselect | $select2:unselect |
|
|
88
|
+
| select2:clearing | $select2:clearing |
|
|
89
|
+
| select2:clear | $select2:clear |
|
|
90
|
+
|
|
91
|
+
For example, catching the `$change` events in a parent `dependent-form-fields` Stimulus controller with a single `updateDependentFields` method would look like this:
|
|
92
|
+
|
|
93
|
+
<pre><code><div data-controller="dependent-form-fields">
|
|
94
|
+
<div data-action="$change->dependent-form-fields#updateDependentFields">
|
|
95
|
+
<%= render 'shared/fields/super_select', form: form, method: :category_id,
|
|
96
|
+
choices: Category.all.map { |category| [category.label_string, category.id] } %>
|
|
97
|
+
</div>
|
|
98
|
+
<div>
|
|
99
|
+
<!-- This is the dependent field that would get updated when the previous one changes -->
|
|
100
|
+
<%= render 'shared/fields/super_select', form: form, method: :category_id,
|
|
101
|
+
choices: Category.all.map { |category| [category.label_string, category.id] },
|
|
102
|
+
html_options: { data: { 'dependent-form-fields-target': 'dependentField' }} %>
|
|
103
|
+
</div>
|
|
104
|
+
</div></code></pre>
|
|
105
|
+
|
|
106
|
+
And this is an example of what the `dependent-form-fields` Stimulus controller would look like.
|
|
107
|
+
|
|
108
|
+
<pre><code>
|
|
109
|
+
// dependent_form_fields_controller.js
|
|
110
|
+
import { Controller } from "stimulus"
|
|
111
|
+
|
|
112
|
+
export default class extends Controller {
|
|
113
|
+
static targets = [ "dependentField" ]
|
|
114
|
+
|
|
115
|
+
updateDependentFields(event) {
|
|
116
|
+
const originalSelect2Event = event.detail.event
|
|
117
|
+
console.log(`catching event ${event.type}`, originalSelect2Event)
|
|
118
|
+
|
|
119
|
+
this.dependentFieldTargets.forEach((dependentField) => {
|
|
120
|
+
// update dependentField based on value found in originalSelect2Event.target.value
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
</code></pre>
|
|
125
|
+
|
|
126
|
+
[select2]: https://select2.org
|
|
127
|
+
[select2_events]: https://select2.org/programmatic-control/events
|
data/docs/field-partials.md
CHANGED
|
@@ -109,23 +109,30 @@ Certain form field partials like `buttons` and `super_select` can also have thei
|
|
|
109
109
|
|
|
110
110
|
## Available Field Partials
|
|
111
111
|
|
|
112
|
-
| Field Partial | Multiple Values? | Assignment Helpers | JavaScript Library | Description | Commercial License Required |
|
|
113
|
-
| --- | --- | --- | --- | --- | --- |
|
|
114
|
-
| `boolean` | | `assign_boolean` | | | |
|
|
115
|
-
| [`buttons`](/docs/field-partials/buttons.md) | Optionally | `assign_checkboxes` | | | |
|
|
116
|
-
| `cloudinary_image` | | | | | |
|
|
117
|
-
| `color_picker` | | | [pickr](https://simonwep.github.io/pickr/) | | |
|
|
118
|
-
| `date_and_time_field` | | `assign_date_and_time` | [Date Range Picker](https://www.daterangepicker.com) | | |
|
|
119
|
-
| `date_field` | | `assign_date` | [Date Range Picker](https://www.daterangepicker.com) | | |
|
|
120
|
-
| `email_field` | | | | | |
|
|
121
|
-
| `file_field` | | | [Active Storage](https://edgeguides.rubyonrails.org/active_storage_overview.html) | | |
|
|
122
|
-
| `options` | Optionally | `assign_checkboxes` | | | |
|
|
123
|
-
| `password_field` | | | | | |
|
|
124
|
-
| `phone_field` | | | [International Telephone Input](https://intl-tel-input.com) | Ensures telephone numbers are in a format that can be used by providers like Twilio. | |
|
|
125
|
-
| [`super_select`](/docs/field-partials/super-select.md) | Optionally | `assign_select_options` | [Select2](https://select2.org) | Provides powerful option search, AJAX search, and multi-select functionality. | |
|
|
126
|
-
| `text_area` | | | | | |
|
|
127
|
-
| `text_field` | | | | | |
|
|
128
|
-
| `trix_editor` | | | [Trix](https://github.com/basecamp/trix) | Basic HTML-powered formatting features and support for at-mentions amongst team members. | |
|
|
112
|
+
| Field Partial | Data Type | Multiple Values? | Assignment Helpers | JavaScript Library | Description | Commercial License Required |
|
|
113
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
114
|
+
| `boolean` | `boolean` | `assign_boolean` | | | |
|
|
115
|
+
| [`buttons`](/docs/field-partials/buttons.md) | `string` | Optionally | `assign_checkboxes` | | | |
|
|
116
|
+
| `cloudinary_image` | `string` | | | | | |
|
|
117
|
+
| `color_picker` | | | | [pickr](https://simonwep.github.io/pickr/) | | |
|
|
118
|
+
| `date_and_time_field` | `datetime` | | `assign_date_and_time` | [Date Range Picker](https://www.daterangepicker.com) | | |
|
|
119
|
+
| `date_field` | `date` | | `assign_date` | [Date Range Picker](https://www.daterangepicker.com) | | |
|
|
120
|
+
| `email_field` | `string` | | | | | |
|
|
121
|
+
| `file_field` | `attachment` | | [Active Storage](https://edgeguides.rubyonrails.org/active_storage_overview.html) | | |
|
|
122
|
+
| `options` | `string` | Optionally | `assign_checkboxes` | | | |
|
|
123
|
+
| `password_field` | `string` | | | | | |
|
|
124
|
+
| `phone_field` | `string` | | | [International Telephone Input](https://intl-tel-input.com) | Ensures telephone numbers are in a format that can be used by providers like Twilio. | |
|
|
125
|
+
| [`super_select`](/docs/field-partials/super-select.md) | `string` | Optionally | `assign_select_options` | [Select2](https://select2.org) | Provides powerful option search, AJAX search, and multi-select functionality. | |
|
|
126
|
+
| `text_area` | `text` | | | | | |
|
|
127
|
+
| `text_field` | `string` | | | | | |
|
|
128
|
+
| `trix_editor` | `text` | | | [Trix](https://github.com/basecamp/trix) | Basic HTML-powered formatting features and support for at-mentions amongst team members. | |
|
|
129
|
+
|
|
130
|
+
## A Note On Data Types
|
|
131
|
+
Set the data type to `jsonb` whenever passing the `multiple` option to a new attribute.
|
|
132
|
+
```
|
|
133
|
+
> rails generate model Project team:references multiple_buttons:jsonb
|
|
134
|
+
> bin/super-scaffold crud Project Team multiple_buttons:buttons{multiple}
|
|
135
|
+
```
|
|
129
136
|
|
|
130
137
|
## Additional Field Partials Documentation
|
|
131
138
|
- [`buttons`](/docs/field-partials/buttons.md)
|
data/docs/index.md
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Invitation Only Mode
|
|
2
|
+
|
|
3
|
+
By providing a randomized string to `ENV["INVITATION_KEYS"]`, you can enable invitation only mode on your Bullet Train application. This will set up your app so that users cannot register to your website unless they have access to a specific link, or if they are invited via email.
|
|
4
|
+
|
|
5
|
+
`config/application.yml`:
|
|
6
|
+
```ruby
|
|
7
|
+
INVITATION_KEYS: ofr9h5h9ghzeodh
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
In this case, the user will be able to register their own account by accessing the following link:
|
|
11
|
+
```
|
|
12
|
+
http://localhost:3000/invitations?key=ofr9h5h9ghzeodh
|
|
13
|
+
```
|
|
@@ -34,7 +34,7 @@ rails g model Message subject:string
|
|
|
34
34
|
rails g model Comment content:text
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
Note that in this specific approach we don't need a `team:references` on `Message` and `Comment`. That's because in this approach there are no controllers specific to `Message` and `Comment`, so all permissions are being
|
|
37
|
+
Note that in this specific approach we don't need a `team:references` on `Message` and `Comment`. That's because in this approach there are no controllers specific to `Message` and `Comment`, so all permissions are being enforced by checking the ownership of `Entry`. (That's not to say it would be wrong to add them for other reasons, we're just keeping it as simple as possible here.)
|
|
38
38
|
|
|
39
39
|
### 2. Super Scaffolding for `Entry`
|
|
40
40
|
|
|
@@ -59,7 +59,33 @@ fields: &fields
|
|
|
59
59
|
"Comment": Comment
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
We will add this block below in the next step on our `new.html.erb` page so you don't have to worry about it now, but with the options above in place, our buttons partial will now allow your users to select either a `Message` or a `Comment` before creating the `Entry` itself:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
<% with_field_settings form: form do %>
|
|
66
|
+
<%= render 'shared/fields/buttons', method: :entryable_type, html_options: {autofocus: true} %>
|
|
67
|
+
<%# 🚅 super scaffolding will insert new fields above this line. %>
|
|
68
|
+
<% end %>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
This will produce the following HTML:
|
|
72
|
+
```
|
|
73
|
+
<div>
|
|
74
|
+
<label class="btn-toggle" data-controller="fields--button-toggle">
|
|
75
|
+
<input data-fields--button-toggle-target="shadowField" type="radio" value="Message" name="entry[entryable_type]" id="entry_entryable_type_message">
|
|
76
|
+
<button type="button" class="button-alternative mb-1.5 mr-1" data-action="fields--button-toggle#clickShadowField">
|
|
77
|
+
Message
|
|
78
|
+
</button>
|
|
79
|
+
</label>
|
|
80
|
+
<label class="btn-toggle" data-controller="fields--button-toggle">
|
|
81
|
+
<input data-fields--button-toggle-target="shadowField" type="radio" value="Comment" name="entry[entryable_type]" id="entry_entryable_type_comment">
|
|
82
|
+
<button type="button" class="button-alternative mb-1.5 mr-1" data-action="fields--button-toggle#clickShadowField">
|
|
83
|
+
Comment
|
|
84
|
+
</button>
|
|
85
|
+
</label>
|
|
86
|
+
</div>
|
|
87
|
+
```
|
|
88
|
+
|
|
63
89
|
|
|
64
90
|
### 4. Add Our First Step to `new.html.erb`
|
|
65
91
|
|
|
@@ -234,9 +260,11 @@ We add this _below_ the Super Scaffolding hook because we want any additional fi
|
|
|
234
260
|
|
|
235
261
|
### 10. Add Attributes of the Concrete Children to `show.html.erb`
|
|
236
262
|
|
|
237
|
-
|
|
263
|
+
Add the following in `app/views/account/entries/show.html.erb` under the Super Scaffolding hook shown in the example code below:
|
|
238
264
|
|
|
239
265
|
```
|
|
266
|
+
<%# 🚅 super scaffolding will insert new fields above this line. %>
|
|
267
|
+
|
|
240
268
|
<% with_attribute_settings object: @entry.entryable, strategy: :label do %>
|
|
241
269
|
<% case @entry.entryable %>
|
|
242
270
|
<% when Message %>
|
data/lib/bullet_train/version.rb
CHANGED
data/lib/bullet_train.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bullet_train
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.99
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrew Culver
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-
|
|
11
|
+
date: 2022-08-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: standard
|
|
@@ -477,6 +477,7 @@ files:
|
|
|
477
477
|
- app/javascript/controllers/form_controller.js
|
|
478
478
|
- app/javascript/controllers/index.js
|
|
479
479
|
- app/javascript/controllers/mobile_menu_controller.js
|
|
480
|
+
- app/javascript/controllers/text_toggle_controller.js
|
|
480
481
|
- app/javascript/electron/index.js
|
|
481
482
|
- app/javascript/index.js
|
|
482
483
|
- app/mailers/concerns/mailers/base.rb
|
|
@@ -622,6 +623,7 @@ files:
|
|
|
622
623
|
- docs/i18n.md
|
|
623
624
|
- docs/index.md
|
|
624
625
|
- docs/indirection.md
|
|
626
|
+
- docs/invitation_only.md
|
|
625
627
|
- docs/javascript.md
|
|
626
628
|
- docs/modeling.md
|
|
627
629
|
- docs/namespacing.md
|