bullet_train 1.0.99 → 1.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/concerns/account/teams/controller_base.rb +4 -13
- data/app/controllers/concerns/account/users/controller_base.rb +1 -0
- data/app/controllers/concerns/controllers/base.rb +24 -0
- data/app/helpers/concerns/helpers/base.rb +9 -0
- data/app/models/concerns/records/base.rb +17 -0
- data/app/models/concerns/users/base.rb +1 -0
- data/docs/permissions.md +1 -1
- data/lib/bullet_train/version.rb +1 -1
- metadata +2 -5
- data/app/assets/javascripts/bullet-train.js +0 -2
- data/app/assets/javascripts/bullet-train.js.map +0 -1
- data/docs/api.md +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 459bb309e4ce417a30b412a93a4b590fe3735e3474a40490804213c999ba4332
|
4
|
+
data.tar.gz: 109a8f50ab47b310aedc400adffef6fa78d7fcdb0eb0e0f5512c3f947b2bdf01
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dd250cd1bf923513cf37bc81a225aacd8b91436566e8e49414e2ec8adeacbc3a23ac099f5e1c3eacd456ac0f0a8157d1345edfcf8c89094a309139e03174dc55
|
7
|
+
data.tar.gz: d2ecef35d6faa0f3eef74ec2ee8b785cfaea38812249f206790d296832ab3051639a68d8426a73d6d935793dec07a6ee75126c2b84c08cec3ff75c42db5842be
|
@@ -18,6 +18,10 @@ module Account::Teams::ControllerBase
|
|
18
18
|
# for magic locales.
|
19
19
|
@child_object = @team
|
20
20
|
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
include strong_parameters_from_api
|
21
25
|
end
|
22
26
|
|
23
27
|
# GET /teams
|
@@ -124,17 +128,4 @@ module Account::Teams::ControllerBase
|
|
124
128
|
def process_params(strong_params)
|
125
129
|
raise "It looks like you've removed `process_params` from your controller. This will break Super Scaffolding."
|
126
130
|
end
|
127
|
-
|
128
|
-
# Never trust parameters from the scary internet, only allow the white list through.
|
129
|
-
def team_params
|
130
|
-
strong_params = params.require(:team).permit(
|
131
|
-
:name,
|
132
|
-
:time_zone,
|
133
|
-
:locale,
|
134
|
-
*permitted_fields,
|
135
|
-
*permitted_arrays,
|
136
|
-
)
|
137
|
-
|
138
|
-
process_params(strong_params)
|
139
|
-
end
|
140
131
|
end
|
@@ -55,6 +55,7 @@ module Account::Users::ControllerBase
|
|
55
55
|
end
|
56
56
|
|
57
57
|
# Never trust parameters from the scary internet, only allow the white list through.
|
58
|
+
# TODO Update this to use `include strong_parameters_from_api`.
|
58
59
|
def user_params
|
59
60
|
# TODO enforce permissions on updating the user's team name.
|
60
61
|
strong_params = params.require(:user).permit(
|
@@ -39,6 +39,12 @@ module Controllers::Base
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
+
class_methods do
|
43
|
+
def strong_parameters_from_api
|
44
|
+
(name.gsub(regex_to_remove_controller_namespace, "Api::#{BulletTrain::Api.current_version.upcase}::") + "::StrongParameters").constantize
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
42
48
|
# this is an ugly hack, but it's what is recommended at
|
43
49
|
# https://github.com/plataformatec/devise/wiki/How-To:-Create-custom-layouts
|
44
50
|
def layout_by_resource
|
@@ -116,4 +122,22 @@ module Controllers::Base
|
|
116
122
|
)
|
117
123
|
end
|
118
124
|
end
|
125
|
+
|
126
|
+
def permitted_fields
|
127
|
+
[]
|
128
|
+
end
|
129
|
+
|
130
|
+
def permitted_arrays
|
131
|
+
{}
|
132
|
+
end
|
133
|
+
|
134
|
+
def process_params(strong_params)
|
135
|
+
end
|
136
|
+
|
137
|
+
def delegate_json_to_api
|
138
|
+
respond_to do |format|
|
139
|
+
format.html
|
140
|
+
format.json { render "#{params[:controller].gsub(/^account\//, "api/#{BulletTrain::Api.current_version}/")}/#{params[:action]}" }
|
141
|
+
end
|
142
|
+
end
|
119
143
|
end
|
@@ -6,4 +6,13 @@ module Helpers::Base
|
|
6
6
|
# This scope has an order if the SQL changes when we remove any order clause.
|
7
7
|
scope.to_sql != scope.reorder("").to_sql
|
8
8
|
end
|
9
|
+
|
10
|
+
# TODO This should really be in the API package and included from there.
|
11
|
+
if defined?(BulletTrain::Api)
|
12
|
+
def render_pagination(json)
|
13
|
+
if @pagy
|
14
|
+
json.has_more @pagy.has_more
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
9
18
|
end
|
@@ -75,4 +75,21 @@ module Records::Base
|
|
75
75
|
db_seed_task = rake_tasks.find { |task| task.name.match?(/^db:seed$/) }
|
76
76
|
db_seed_task.already_invoked
|
77
77
|
end
|
78
|
+
|
79
|
+
# TODO This should really be in the API package and included from there.
|
80
|
+
if defined?(BulletTrain::Api)
|
81
|
+
def to_api_json
|
82
|
+
# TODO So many performance improvements available here.
|
83
|
+
controller = "Api::#{BulletTrain::Api.current_version.upcase}::ApplicationController".constantize.new
|
84
|
+
# TODO We need to fix host names here.
|
85
|
+
controller.request = ActionDispatch::Request.new({})
|
86
|
+
local_class_key = self.class.name.underscore.split("/").last.to_sym
|
87
|
+
controller.render_to_string(
|
88
|
+
"api/#{BulletTrain::Api.current_version}/#{self.class.name.underscore.pluralize}/_#{local_class_key}",
|
89
|
+
locals: {
|
90
|
+
local_class_key => self
|
91
|
+
}
|
92
|
+
)
|
93
|
+
end
|
94
|
+
end
|
78
95
|
end
|
@@ -20,6 +20,7 @@ module Users::Base
|
|
20
20
|
has_many :memberships, dependent: :destroy
|
21
21
|
has_many :scaffolding_absolutely_abstract_creative_concepts_collaborators, through: :memberships
|
22
22
|
has_many :teams, through: :memberships
|
23
|
+
has_many :collaborating_users, through: :teams, source: :users
|
23
24
|
belongs_to :current_team, class_name: "Team", optional: true
|
24
25
|
accepts_nested_attributes_for :current_team
|
25
26
|
|
data/docs/permissions.md
CHANGED
@@ -14,5 +14,5 @@ Because abilities are being evaluated on basically every request, it made sense
|
|
14
14
|
### Naming and Labeling
|
15
15
|
What we call a `Role` in the domain model is referred to as “Special Privileges” in the user-facing application. You can rename this to whatever you like in `config/locales/en/roles.en.yml`.
|
16
16
|
|
17
|
-
## Note About Pundit
|
17
|
+
## A Note About Pundit
|
18
18
|
There’s nothing stopping you from utilizing Pundit in a Bullet Train project for specific hard-to-implement cases in your permissions model, but you wouldn’t want to try and replace CanCanCan with it. We do too much automatically with CanCanCan for that to be recommended. That said, in those situations where there is a permission that needs to be implemented that isn’t easily implemented with CanCanCan, consider just writing vanilla Ruby code for that purpose.
|
data/lib/bullet_train/version.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.
|
4
|
+
version: 1.1.2
|
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-09-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: standard
|
@@ -428,8 +428,6 @@ files:
|
|
428
428
|
- README.md
|
429
429
|
- Rakefile
|
430
430
|
- app/assets/config/bullet_train_manifest.js
|
431
|
-
- app/assets/javascripts/bullet-train.js
|
432
|
-
- app/assets/javascripts/bullet-train.js.map
|
433
431
|
- app/controllers/account/invitations_controller.rb
|
434
432
|
- app/controllers/account/memberships_controller.rb
|
435
433
|
- app/controllers/account/onboarding/user_details_controller.rb
|
@@ -610,7 +608,6 @@ files:
|
|
610
608
|
- db/migrate/20211020200855_add_doorkeeper_application_to_memberships.rb
|
611
609
|
- db/migrate/20211027002944_add_doorkeeper_application_to_users.rb
|
612
610
|
- docs/action-models.md
|
613
|
-
- docs/api.md
|
614
611
|
- docs/authentication.md
|
615
612
|
- docs/billing/stripe.md
|
616
613
|
- docs/desktop.md
|
@@ -1,2 +0,0 @@
|
|
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
|
-
//# sourceMappingURL=bullet-train.js.map
|
@@ -1 +0,0 @@
|
|
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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"}
|
data/docs/api.md
DELETED