bullet_train 1.0.76 → 1.0.83
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/controllers/concerns/account/controllers/base.rb +9 -0
- data/app/controllers/concerns/account/teams/controller_base.rb +1 -1
- data/app/helpers/base_helper.rb +5 -1
- data/app/models/concerns/memberships/base.rb +5 -0
- data/app/models/concerns/records/base.rb +8 -0
- data/app/models/concerns/teams/base.rb +19 -0
- data/config/locales/en/billing/products.en.yml +17 -0
- data/lib/bullet_train/version.rb +1 -1
- data/lib/bullet_train.rb +6 -1
- metadata +4 -5
- data/app/assets/javascripts/bullet-train.js +0 -2
- data/app/assets/javascripts/bullet-train.js.map +0 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d2119a17f5ed1aace492642ab674c8fb67cadefd29100aee3809e590813da3bb
|
|
4
|
+
data.tar.gz: '0679c15de2ec6260be9beab3c1261fbef4892cacd961d285f813229aac5b1616'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 807684f8b6d5a99a6d35a78d0e50cbeb8a0ef40d06b1e56c1c653a6851ea0289e50c75f2a1e75a1500f6799f3fcd91a603fffaa64ea12324068a851290e67186
|
|
7
|
+
data.tar.gz: 964b44f5ddaa872e26e8cefcf0dd6f9a11d19fc7d3b435e10e7a14d6f62c420a60945dde1eb0c9c588f049cd64423e93c82c52e2b207c01c2cfbe7d58c5b125b
|
|
@@ -5,6 +5,10 @@ module Account::Controllers::Base
|
|
|
5
5
|
include LoadsAndAuthorizesResource
|
|
6
6
|
include Fields::ControllerSupport
|
|
7
7
|
|
|
8
|
+
if billing_enabled?
|
|
9
|
+
include Billing::ControllerSupport
|
|
10
|
+
end
|
|
11
|
+
|
|
8
12
|
before_action :set_last_seen_at, if: proc {
|
|
9
13
|
user_signed_in? && (current_user.last_seen_at.nil? || current_user.last_seen_at < 1.minute.ago)
|
|
10
14
|
}
|
|
@@ -106,6 +110,11 @@ module Account::Controllers::Base
|
|
|
106
110
|
end
|
|
107
111
|
end
|
|
108
112
|
|
|
113
|
+
# TODO Maybe in this context we should check whether `Billing::ControllerSupport` is included instead of just defined?
|
|
114
|
+
if defined?(Billing::ControllerSupport)
|
|
115
|
+
enforce_billing_requirements
|
|
116
|
+
# See `app/controllers/concerns/billing_support.rb` for details.
|
|
117
|
+
end
|
|
109
118
|
end
|
|
110
119
|
|
|
111
120
|
true
|
|
@@ -81,7 +81,7 @@ module Account::Teams::ControllerBase
|
|
|
81
81
|
format.html { redirect_to [:account, @team], notice: I18n.t("teams.notifications.created") }
|
|
82
82
|
format.json { render :show, status: :created, location: [:account, @team] }
|
|
83
83
|
else
|
|
84
|
-
format.html { render :new, layout: "devise" }
|
|
84
|
+
format.html { render :new, layout: "devise", status: :unprocessable_entity }
|
|
85
85
|
format.json { render json: @team.errors, status: :unprocessable_entity }
|
|
86
86
|
end
|
|
87
87
|
end
|
data/app/helpers/base_helper.rb
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
module BaseHelper
|
|
2
2
|
# TODO This is for the billing package to override, but I feel like there has got to be a better way to do this.
|
|
3
3
|
def hide_team_resource_menus?
|
|
4
|
-
|
|
4
|
+
if billing_enabled?
|
|
5
|
+
current_team.needs_billing_subscription?
|
|
6
|
+
else
|
|
7
|
+
false
|
|
8
|
+
end
|
|
5
9
|
end
|
|
6
10
|
end
|
|
@@ -29,6 +29,11 @@ module Memberships::Base
|
|
|
29
29
|
scope :current_and_invited, -> { includes(:invitation).where("user_id IS NOT NULL OR invitations.id IS NOT NULL").references(:invitation) }
|
|
30
30
|
scope :current, -> { where("user_id IS NOT NULL") }
|
|
31
31
|
scope :tombstones, -> { includes(:invitation).where("user_id IS NULL AND invitations.id IS NULL").references(:invitation) }
|
|
32
|
+
|
|
33
|
+
# TODO Probably we can provide a way for gem packages to define these kinds of extensions.
|
|
34
|
+
if billing_enabled?
|
|
35
|
+
scope :billable, -> { current }
|
|
36
|
+
end
|
|
32
37
|
end
|
|
33
38
|
|
|
34
39
|
def name
|
|
@@ -28,6 +28,14 @@ module Records::Base
|
|
|
28
28
|
scope :newest_updated, -> { order("updated_at DESC") }
|
|
29
29
|
scope :oldest_updated, -> { order("updated_at ASC") }
|
|
30
30
|
|
|
31
|
+
# TODO Probably we can provide a way for gem packages to define these kinds of extensions.
|
|
32
|
+
if billing_enabled?
|
|
33
|
+
# By default, any model in a collection is considered active for billing purposes.
|
|
34
|
+
# This can be overloaded in the child model class to specify more specific criteria for billing.
|
|
35
|
+
# See `app/models/concerns/memberships/base.rb` for an example.
|
|
36
|
+
scope :billable, -> { order("TRUE") }
|
|
37
|
+
end
|
|
38
|
+
|
|
31
39
|
# Microscope adds useful scopes targeting ActiveRecord `boolean`, `date` and `datetime` attributes.
|
|
32
40
|
# https://github.com/mirego/microscope
|
|
33
41
|
acts_as_microscope
|
|
@@ -18,6 +18,17 @@ module Teams::Base
|
|
|
18
18
|
# integrations
|
|
19
19
|
has_many :integrations_stripe_installations, class_name: "Integrations::StripeInstallation", dependent: :destroy if stripe_enabled?
|
|
20
20
|
|
|
21
|
+
# TODO Probably we can provide a way for gem packages to define these kinds of extensions.
|
|
22
|
+
if billing_enabled?
|
|
23
|
+
# subscriptions
|
|
24
|
+
has_many :billing_subscriptions, class_name: "Billing::Subscription", dependent: :destroy, foreign_key: :team_id
|
|
25
|
+
|
|
26
|
+
# TODO We need a way for `bullet_train-billing-stripe` to define these.
|
|
27
|
+
if defined?(Billing::Stripe::Subscription)
|
|
28
|
+
has_many :billing_stripe_subscriptions, class_name: "Billing::Stripe::Subscription", dependent: :destroy, foreign_key: :team_id
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
21
32
|
# validations
|
|
22
33
|
validates :name, presence: true
|
|
23
34
|
validates :time_zone, inclusion: {in: ActiveSupport::TimeZone.all.map(&:name)}, allow_nil: true
|
|
@@ -48,4 +59,12 @@ module Teams::Base
|
|
|
48
59
|
# generic functions need to function for a team model as well, so we do this.
|
|
49
60
|
self
|
|
50
61
|
end
|
|
62
|
+
|
|
63
|
+
# TODO Probably we can provide a way for gem packages to define these kinds of extensions.
|
|
64
|
+
if billing_enabled?
|
|
65
|
+
def needs_billing_subscription?
|
|
66
|
+
return false if freemium_enabled?
|
|
67
|
+
billing_subscriptions.active.empty?
|
|
68
|
+
end
|
|
69
|
+
end
|
|
51
70
|
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
en:
|
|
2
|
+
billing/products:
|
|
3
|
+
free:
|
|
4
|
+
name: Free
|
|
5
|
+
basic:
|
|
6
|
+
name: Basic
|
|
7
|
+
description: This is an example plan that includes a free trial when paid for monthly.
|
|
8
|
+
features:
|
|
9
|
+
- Demonstrates pricing per team member.
|
|
10
|
+
- Allows creation of up to fifty "Creative Concepts".
|
|
11
|
+
- Soft enforcement that limit.
|
|
12
|
+
pro:
|
|
13
|
+
name: Pro
|
|
14
|
+
description: An improved example plan that demonstrates different features.
|
|
15
|
+
features:
|
|
16
|
+
- Demonstrates a fixed price for up to ten team members.
|
|
17
|
+
- Allows creation of an unlimited number of "Creative Concepts".
|
data/lib/bullet_train/version.rb
CHANGED
data/lib/bullet_train.rb
CHANGED
|
@@ -61,7 +61,12 @@ def inbound_email_enabled?
|
|
|
61
61
|
ENV["INBOUND_EMAIL_DOMAIN"].present?
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
def
|
|
64
|
+
def billing_enabled?
|
|
65
|
+
defined?(BulletTrain::Billing)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# TODO This should be in an initializer or something.
|
|
69
|
+
def billing_subscription_creation_disabled?
|
|
65
70
|
false
|
|
66
71
|
end
|
|
67
72
|
|
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.83
|
|
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-06-
|
|
11
|
+
date: 2022-06-28 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
|
|
@@ -558,6 +556,7 @@ files:
|
|
|
558
556
|
- config/initializers/concerns/inflections_base.rb
|
|
559
557
|
- config/initializers/concerns/turbo_failure_app.rb
|
|
560
558
|
- config/locales/en/base.yml
|
|
559
|
+
- config/locales/en/billing/products.en.yml
|
|
561
560
|
- config/locales/en/devise.en.yml
|
|
562
561
|
- config/locales/en/doorkeeper.en.yml
|
|
563
562
|
- config/locales/en/invitations.en.yml
|
|
@@ -667,7 +666,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
667
666
|
- !ruby/object:Gem::Version
|
|
668
667
|
version: '0'
|
|
669
668
|
requirements: []
|
|
670
|
-
rubygems_version: 3.
|
|
669
|
+
rubygems_version: 3.2.22
|
|
671
670
|
signing_key:
|
|
672
671
|
specification_version: 4
|
|
673
672
|
summary: Bullet Train
|
|
@@ -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 i 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)}}i.targets=["source","input","button"];class r 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()}}r.targets=["trixField","scroll"];class s extends e{toggle(){const e=this.isWrapperHidden?this.showEventNameValue:this.hideEventNameValue;this.isWrapperHidden&&this.showWrapper(),this.wrapperTarget.dispatchEvent(new CustomEvent(e))}get isWrapperHidden(){return this.wrapperTarget.classList.contains(this.hiddenClass)}showWrapper(){this.wrapperTarget.classList.remove(this.hiddenClass)}hideWrapper(){this.wrapperTarget.classList.add(this.hiddenClass)}}s.targets=["wrapper"],s.classes=["hidden"],s.values={showEventName:String,hideEventName:String};const n=[[i,"clipboard_controller.js"],[r,"form_controller.js"],[s,"mobile_menu_controller.js"]].map(function(e){const i=e[0];return{identifier:t(e[1]),controllerConstructor:i}});document.addEventListener("turbo:load",()=>{navigator.userAgent.toLocaleLowerCase().includes("electron")&&document.body.classList.add("electron")});export{n 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/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 = ['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 ClipboardController from './clipboard_controller'\nimport FormController from './form_controller'\nimport MobileMenuController from './mobile_menu_controller'\n\nexport const controllerDefinitions = [\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","Controller","copy","this","inputTarget","value","sourceTarget","innerText","select","document","execCommand","buttonTarget","innerHTML","setTimeout","getElementById","targets","removeTrailingNewlines","trixEditor","element","slice","removeTrailingWhitespace","resetOnSuccess","e","detail","success","target","reset","stripTrix","trixFieldTargets","forEach","editor","parentElement","querySelector","submitOnReturn","metaKey","ctrlKey","keyCode","preventDefault","form","closest","submitForm","requestSubmit","click","toggle","eventName","isWrapperHidden","showEventNameValue","hideEventNameValue","showWrapper","wrapperTarget","dispatchEvent","CustomEvent","classList","contains","hiddenClass","remove","hideWrapper","add","classes","values","showEventName","String","hideEventName","controllerDefinitions","ClipboardController","FormController","MobileMenuController","map","d","controller","identifier","controllerConstructor","addEventListener","navigator","userAgent","toLocaleLowerCase","includes","body"],"mappings":"gDAqBA,SAASA,EAAwBC,GAC7B,MAAMC,GAAeD,EAAIE,MAAM,2CAA6C,IAAI,GAChF,GAAID,EACA,OAAOA,EAAYE,QAAQ,KAAM,KAAKA,QAAQ,MAAO,sBCtBhCC,EAG3BC,OACEC,KAAKC,YAAYC,MAAQF,KAAKG,aAAaC,UAC3CJ,KAAKC,YAAYI,SACjBC,SAASC,YAAY,QACrBP,KAAKQ,aAAaC,UAAY,wEAC9BC,WAAW,WACTJ,SAASK,eAAe,UAAUF,UAAY,2DAC7C,SATEG,QAAU,CAAC,SAAU,QAAS,0BCAVd,yCA2B3Be,uBAA0BC,IACpBA,EAAWC,QAAQN,UAAUb,MAAM,kBACrCkB,EAAWC,QAAQN,UAAYK,EAAWC,QAAQN,UAAUO,MAAM,GAAI,IAAM,SAC5EhB,KAAKa,uBAAuBC,UAIhCG,yBAA4BH,IACtBA,EAAWC,QAAQN,UAAUb,MAAM,mBACrCkB,EAAWC,QAAQN,UAAYK,EAAWC,QAAQN,UAAUO,MAAM,GAAI,IAAM,SAC5EhB,KAAKiB,yBAAyBH,IACrBA,EAAWC,QAAQN,UAAUb,MAAM,qBAC5CkB,EAAWC,QAAQN,UAAYK,EAAWC,QAAQN,UAAUO,MAAM,GAAI,IAAM,SAC5EhB,KAAKiB,yBAAyBH,KArClCI,eAAeC,GACVA,EAAEC,OAAOC,SACVF,EAAEG,OAAOC,QAIbC,YACExB,KAAKyB,iBAAiBC,QAAQX,IAC5Bf,KAAKa,uBAAuBE,EAAQY,QACpC3B,KAAKiB,yBAAyBF,EAAQY,QAGtCZ,EAAQa,cAAcC,cAAc,SAAS3B,MAAQa,EAAQN,YAIjEqB,eAAeX,GACb,IAAIA,EAAEY,SAAWZ,EAAEa,UAA0B,IAAbb,EAAEc,QAAe,CAC/Cd,EAAEe,iBACF,IAAIC,EAAOhB,EAAEG,OAAOc,QAAQ,QAC5BpC,KAAKqC,WAAWF,IAqBpBE,WAAWF,GAGLA,EAAKG,cACPH,EAAKG,gBAELH,EAAKN,cAAc,iBAAiBU,WAjDjC3B,QAAU,CAAC,YAAa,0BCFJd,EAQ3B0C,SACE,MAAMC,EAAYzC,KAAK0C,gBAAiB1C,KAAK2C,mBAAoB3C,KAAK4C,mBAClE5C,KAAK0C,iBACP1C,KAAK6C,cAGP7C,KAAK8C,cAAcC,cAAc,IAAIC,YAAYP,IAG/CC,sBACF,YAAYI,cAAcG,UAAUC,SAASlD,KAAKmD,aAGpDN,cACE7C,KAAK8C,cAAcG,UAAUG,OAAOpD,KAAKmD,aAG3CE,cACErD,KAAK8C,cAAcG,UAAUK,IAAItD,KAAKmD,gBAzBjCvC,QAAU,CAAE,aACZ2C,QAAU,CAAE,YACZC,OAAS,CACdC,cAAeC,OACfC,cAAeD,QCDNE,MAAAA,EAAwB,CACnC,CAACC,EAAqB,2BACtB,CAACC,EAAgB,sBACjB,CAACC,EAAsB,8BACvBC,IAAI,SAASC,GACb,MACMC,EAAaD,EAAE,GACrB,MAAO,CACLE,WAAY1E,EAHFwE,EAAE,IAIZG,sBAAuBF,KCf3B5D,SAAS+D,iBAAiB,aAAc,KAClCC,UAAUC,UAAUC,oBAAoBC,SAAS,aACnDnE,SAASoE,KAAKzB,UAAUK,IAAI"}
|