diff --git a/Dockerfile b/Dockerfile index ec7a926..44681ee 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,4 +8,4 @@ WORKDIR /app RUN pip install -r requirements.txt # Make port 8000 available to the world outside this container -EXPOSE 8000 +EXPOSE 8000 \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 5ac1098..d428191 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,7 +6,7 @@ services: volumes: - ./../postgres-data:/var/lib/postgresql/data ports: - - "5432:5432" + - "5435:5432" environment: - POSTGRES_DB=postgres - POSTGRES_USER=postgres diff --git a/formulaic/static/admin/formulaic/ember-formulaic/.bowerrc b/formulaic/static/admin/formulaic/ember-formulaic/.bowerrc deleted file mode 100644 index 959e169..0000000 --- a/formulaic/static/admin/formulaic/ember-formulaic/.bowerrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "directory": "bower_components", - "analytics": false -} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/.eslintcache b/formulaic/static/admin/formulaic/ember-formulaic/.eslintcache new file mode 100644 index 0000000..0dfe973 --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/.eslintcache @@ -0,0 +1 @@ +[{"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/.eslintrc.js":"1","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/adapters/application.js":"2","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/app.js":"3","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/base-sortable.js":"4","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/basefield.js":"5","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/booleanfield.js":"6","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/choicefield.js":"7","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/hiddenfield.js":"8","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/index.js":"9","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/textfield.js":"10","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields.js":"11","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/index.js":"12","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/rules.js":"13","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/submissions.js":"14","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form.js":"15","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-checkbox-select-multiple.js":"16","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-checkbox.js":"17","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-email.js":"18","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-full-name.js":"19","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-hidden.js":"20","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-integer.js":"21","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-phone-number.js":"22","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-radio-select.js":"23","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-select-multiple.js":"24","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-select.js":"25","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-text.js":"26","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-textarea.js":"27","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/rule-condition.js":"28","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/rule-result.js":"29","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/sidebar.js":"30","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-field.js":"31","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-fields.js":"32","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-rule.js":"33","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-rules.js":"34","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/tinymce-editor.js":"35","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/locations/auto.js":"36","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/basefield.js":"37","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/booleanfield.js":"38","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/choicefield.js":"39","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/field.js":"40","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/form.js":"41","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/hiddenfield.js":"42","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/option.js":"43","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/optiongroup.js":"44","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/optionlist.js":"45","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/privacypolicy.js":"46","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/rule.js":"47","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/rulecondition.js":"48","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/ruleresult.js":"49","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/submission.js":"50","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/submissionsource.js":"51","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/textfield.js":"52","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/modifiers/sortable-group.js":"53","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/resolver.js":"54","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/router.js":"55","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/fields.js":"56","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/index.js":"57","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/rules.js":"58","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/submissions.js":"59","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form.js":"60","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/booleanfield.js":"61","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/choicefield.js":"62","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/field.js":"63","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/form.js":"64","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/hiddenfield.js":"65","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/option.js":"66","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/optiongroup.js":"67","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/optionlist.js":"68","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/privacypolicy.js":"69","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/rule.js":"70","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/textfield.js":"71","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/services/cookies.js":"72","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/services/field-service.js":"73","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/transforms/boolean.js":"74","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/transforms/number.js":"75","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/transforms/string.js":"76","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/utils/fields.js":"77","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/utils/slug.js":"78","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/validators/factories.js":"79","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/validators/fields/basefield.js":"80","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/validators/fields/booleanfield.js":"81","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/validators/fields/choicefield.js":"82","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/validators/fields/hiddenfield.js":"83","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/validators/fields/textfield.js":"84","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/validators/rules/rule.js":"85","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/validators/rules/rulecondition.js":"86","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/validators/rules/ruleresult.js":"87","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/config/environment.js":"88","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/config/targets.js":"89","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/dist/assets/chunk.app.5e38629b8b374693d5ac.js":"90","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/dist/assets/chunk.tests.609240ba01ee46bd0079.js":"91","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/dist/assets/chunk.vendors-node_modules_ember-qunit_dist_index_js-node_modules_dom-element-descriptors_dist_es_i-a01131.a66c7f2b824580009561.js":"92","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/dist/assets/chunk.vendors-node_modules_popperjs_core_lib_index_js-node_modules_ember-element-helper_dist_helper-87c8c0.ef646b89b449250c4da5.js":"93","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/dist/assets/ember-formulaic.js":"94","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/dist/assets/test-support.js":"95","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/dist/assets/tests.js":"96","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/dist/assets/vendor.js":"97","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/dist/testem.js":"98","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/ember-cli-build.js":"99","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/testem.js":"100","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/tests/.eslintrc.js":"101","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/tests/helpers/destroy-app.js":"102","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/tests/helpers/index.js":"103","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/tests/helpers/module-for-acceptance.js":"104","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/tests/helpers/resolver.js":"105","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/tests/helpers/start-app.js":"106","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/tests/integration/components/sidebar-test.js":"107","/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/tests/test-helper.js":"108"},{"size":185,"mtime":1717855571926,"results":"109","hashOfConfig":"110"},{"size":1182,"mtime":1721385725227,"results":"111","hashOfConfig":"110"},{"size":433,"mtime":1719678730685,"results":"112","hashOfConfig":"110"},{"size":1487,"mtime":1721982220553,"results":"113","hashOfConfig":"110"},{"size":1787,"mtime":1719793291762,"results":"114","hashOfConfig":"110"},{"size":157,"mtime":1719321300989,"results":"115","hashOfConfig":"110"},{"size":3038,"mtime":1719881758585,"results":"116","hashOfConfig":"110"},{"size":162,"mtime":1719788305793,"results":"117","hashOfConfig":"110"},{"size":1058,"mtime":1719703625917,"results":"118","hashOfConfig":"110"},{"size":159,"mtime":1719326102484,"results":"119","hashOfConfig":"110"},{"size":3451,"mtime":1719792664104,"results":"120","hashOfConfig":"110"},{"size":2344,"mtime":1719678730696,"results":"121","hashOfConfig":"110"},{"size":6214,"mtime":1721757258496,"results":"122","hashOfConfig":"110"},{"size":2590,"mtime":1718375675273,"results":"123","hashOfConfig":"110"},{"size":200,"mtime":1719313489740,"results":"124","hashOfConfig":"110"},{"size":127,"mtime":1718223255632,"results":"125","hashOfConfig":"110"},{"size":113,"mtime":1718222980976,"results":"126","hashOfConfig":"110"},{"size":110,"mtime":1718223301219,"results":"127","hashOfConfig":"110"},{"size":113,"mtime":1718223345228,"results":"128","hashOfConfig":"110"},{"size":339,"mtime":1718223419971,"results":"129","hashOfConfig":"110"},{"size":112,"mtime":1718223624513,"results":"130","hashOfConfig":"110"},{"size":116,"mtime":1718223656184,"results":"131","hashOfConfig":"110"},{"size":517,"mtime":1718223752551,"results":"132","hashOfConfig":"110"},{"size":119,"mtime":1718223949397,"results":"133","hashOfConfig":"110"},{"size":473,"mtime":1718223870940,"results":"134","hashOfConfig":"110"},{"size":109,"mtime":1718224000451,"results":"135","hashOfConfig":"110"},{"size":113,"mtime":1718224038848,"results":"136","hashOfConfig":"110"},{"size":2902,"mtime":1721278186622,"results":"137","hashOfConfig":"110"},{"size":2158,"mtime":1721210888003,"results":"138","hashOfConfig":"110"},{"size":107,"mtime":1719703178612,"results":"139","hashOfConfig":"110"},{"size":1973,"mtime":1719792437250,"results":"140","hashOfConfig":"110"},{"size":167,"mtime":1719620301573,"results":"141","hashOfConfig":"110"},{"size":1465,"mtime":1721743036153,"results":"142","hashOfConfig":"110"},{"size":418,"mtime":1721990758612,"results":"143","hashOfConfig":"110"},{"size":700,"mtime":1719351372031,"results":"144","hashOfConfig":"110"},{"size":230,"mtime":1719678730698,"results":"145","hashOfConfig":"110"},{"size":526,"mtime":1721054568909,"results":"146","hashOfConfig":"110"},{"size":473,"mtime":1719490051024,"results":"147","hashOfConfig":"110"},{"size":861,"mtime":1719594723749,"results":"148","hashOfConfig":"110"},{"size":503,"mtime":1719594702361,"results":"149","hashOfConfig":"110"},{"size":437,"mtime":1719494982922,"results":"150","hashOfConfig":"110"},{"size":457,"mtime":1719490065043,"results":"151","hashOfConfig":"110"},{"size":343,"mtime":1719603394620,"results":"152","hashOfConfig":"110"},{"size":322,"mtime":1719603394628,"results":"153","hashOfConfig":"110"},{"size":361,"mtime":1719594873240,"results":"154","hashOfConfig":"110"},{"size":242,"mtime":1719442234468,"results":"155","hashOfConfig":"110"},{"size":724,"mtime":1721755759262,"results":"156","hashOfConfig":"110"},{"size":518,"mtime":1721055265091,"results":"157","hashOfConfig":"110"},{"size":532,"mtime":1721057606882,"results":"158","hashOfConfig":"110"},{"size":313,"mtime":1719442277877,"results":"159","hashOfConfig":"110"},{"size":197,"mtime":1718231984943,"results":"160","hashOfConfig":"110"},{"size":394,"mtime":1719490018017,"results":"161","hashOfConfig":"110"},{"size":152,"mtime":1722003408564,"results":"162","hashOfConfig":"110"},{"size":65,"mtime":1717855571930,"results":"163","hashOfConfig":"110"},{"size":489,"mtime":1718323832220,"results":"164","hashOfConfig":"110"},{"size":713,"mtime":1719793940500,"results":"165","hashOfConfig":"110"},{"size":167,"mtime":1719316637078,"results":"166","hashOfConfig":"110"},{"size":920,"mtime":1721757223351,"results":"167","hashOfConfig":"110"},{"size":1698,"mtime":1718373146856,"results":"168","hashOfConfig":"110"},{"size":271,"mtime":1719067048078,"results":"169","hashOfConfig":"110"},{"size":325,"mtime":1719615274899,"results":"170","hashOfConfig":"110"},{"size":324,"mtime":1719615231643,"results":"171","hashOfConfig":"110"},{"size":5066,"mtime":1719596980629,"results":"172","hashOfConfig":"110"},{"size":311,"mtime":1719154523241,"results":"173","hashOfConfig":"110"},{"size":324,"mtime":1719615380064,"results":"174","hashOfConfig":"110"},{"size":747,"mtime":1719879794117,"results":"175","hashOfConfig":"110"},{"size":1912,"mtime":1719882055780,"results":"176","hashOfConfig":"110"},{"size":2194,"mtime":1719882043314,"results":"177","hashOfConfig":"110"},{"size":419,"mtime":1719185250648,"results":"178","hashOfConfig":"110"},{"size":3900,"mtime":1721756748879,"results":"179","hashOfConfig":"110"},{"size":322,"mtime":1719615104696,"results":"180","hashOfConfig":"110"},{"size":677,"mtime":1718327411262,"results":"181","hashOfConfig":"110"},{"size":3810,"mtime":1721757183894,"results":"182","hashOfConfig":"110"},{"size":109,"mtime":1719615418944,"results":"183","hashOfConfig":"110"},{"size":107,"mtime":1719615427401,"results":"184","hashOfConfig":"110"},{"size":101,"mtime":1719154356144,"results":"185","hashOfConfig":"110"},{"size":838,"mtime":1719794015110,"results":"186","hashOfConfig":"110"},{"size":10878,"mtime":1719713250494,"results":"187","hashOfConfig":"110"},{"size":2394,"mtime":1717855571934,"results":"188","hashOfConfig":"110"},{"size":905,"mtime":1718230993828,"results":"189","hashOfConfig":"110"},{"size":120,"mtime":1719790349957,"results":"190","hashOfConfig":"110"},{"size":504,"mtime":1719715931354,"results":"191","hashOfConfig":"110"},{"size":173,"mtime":1719791455134,"results":"192","hashOfConfig":"110"},{"size":117,"mtime":1718231048275,"results":"193","hashOfConfig":"110"},{"size":1263,"mtime":1721213009714,"results":"194","hashOfConfig":"110"},{"size":632,"mtime":1721328008517,"results":"195","hashOfConfig":"110"},{"size":1513,"mtime":1721584211848,"results":"196","hashOfConfig":"110"},{"size":1369,"mtime":1719343232356,"results":"197","hashOfConfig":"110"},{"size":157,"mtime":1718180924828,"results":"198","hashOfConfig":"110"},{"size":22382,"mtime":1722244783258,"results":"199","hashOfConfig":"110"},{"size":26407,"mtime":1722244783260,"results":"200","hashOfConfig":"110"},{"size":252575,"mtime":1722244783260,"results":"201","hashOfConfig":"110"},{"size":432562,"mtime":1722244783259,"results":"202","hashOfConfig":"110"},{"size":479573,"mtime":1722244781015,"results":"203","hashOfConfig":"110"},{"size":327970,"mtime":1722244781587,"results":"204","hashOfConfig":"110"},{"size":7736,"mtime":1722244781493,"results":"205","hashOfConfig":"110"},{"size":3616753,"mtime":1722244781142,"results":"206","hashOfConfig":"110"},{"size":681,"mtime":1721314812172,"results":"207","hashOfConfig":"110"},{"size":825,"mtime":1722006705870,"results":"208","hashOfConfig":"110"},{"size":589,"mtime":1718180948149,"results":"209","hashOfConfig":"110"},{"size":55,"mtime":1717855571956,"results":"210","hashOfConfig":"211"},{"size":122,"mtime":1718111330767,"results":"212","hashOfConfig":"211"},{"size":1253,"mtime":1718180948151,"results":"213","hashOfConfig":"211"},{"size":584,"mtime":1718111330767,"results":"214","hashOfConfig":"211"},{"size":255,"mtime":1717855571957,"results":"215","hashOfConfig":"211"},{"size":509,"mtime":1718111330767,"results":"216","hashOfConfig":"211"},{"size":724,"mtime":1718228300643,"results":"217","hashOfConfig":"211"},{"size":343,"mtime":1718180948150,"results":"218","hashOfConfig":"211"},{"filePath":"219","messages":"220","suppressedMessages":"221","errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},"1kgowq3",{"filePath":"222","messages":"223","suppressedMessages":"224","errorCount":5,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"225","messages":"226","suppressedMessages":"227","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"228","messages":"229","suppressedMessages":"230","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"231","messages":"232","suppressedMessages":"233","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"234","messages":"235","suppressedMessages":"236","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"237","messages":"238","suppressedMessages":"239","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"240","messages":"241","suppressedMessages":"242","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"243","messages":"244","suppressedMessages":"245","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"246","messages":"247","suppressedMessages":"248","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"249","messages":"250","suppressedMessages":"251","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"252","messages":"253","suppressedMessages":"254","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"255","messages":"256","suppressedMessages":"257","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"258","messages":"259","suppressedMessages":"260","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"261","messages":"262","suppressedMessages":"263","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"264","messages":"265","suppressedMessages":"266","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"267","messages":"268","suppressedMessages":"269","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"270","messages":"271","suppressedMessages":"272","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"273","messages":"274","suppressedMessages":"275","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"276","messages":"277","suppressedMessages":"278","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"279","messages":"280","suppressedMessages":"281","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"282","messages":"283","suppressedMessages":"284","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"285","messages":"286","suppressedMessages":"287","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"288","messages":"289","suppressedMessages":"290","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"291","messages":"292","suppressedMessages":"293","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"294","messages":"295","suppressedMessages":"296","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"297","messages":"298","suppressedMessages":"299","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"300","messages":"301","suppressedMessages":"302","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"303","messages":"304","suppressedMessages":"305","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"306","messages":"307","suppressedMessages":"308","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"309","messages":"310","suppressedMessages":"311","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"312","messages":"313","suppressedMessages":"314","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"315","messages":"316","suppressedMessages":"317","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"318","messages":"319","suppressedMessages":"320","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"321","messages":"322","suppressedMessages":"323","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"324","messages":"325","suppressedMessages":"326","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"327","messages":"328","suppressedMessages":"329","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"330","messages":"331","suppressedMessages":"332","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"333","messages":"334","suppressedMessages":"335","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"336","messages":"337","suppressedMessages":"338","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"339","messages":"340","suppressedMessages":"341","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"342","messages":"343","suppressedMessages":"344","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"345","messages":"346","suppressedMessages":"347","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"348","messages":"349","suppressedMessages":"350","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"351","messages":"352","suppressedMessages":"353","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"354","messages":"355","suppressedMessages":"356","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"357","messages":"358","suppressedMessages":"359","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"360","messages":"361","suppressedMessages":"362","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"363","messages":"364","suppressedMessages":"365","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"366","messages":"367","suppressedMessages":"368","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"369","messages":"370","suppressedMessages":"371","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"372","messages":"373","suppressedMessages":"374","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"375","messages":"376","suppressedMessages":"377","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"378","messages":"379","suppressedMessages":"380","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"381","messages":"382","suppressedMessages":"383","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"384","messages":"385","suppressedMessages":"386","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"387","messages":"388","suppressedMessages":"389","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"390","messages":"391","suppressedMessages":"392","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"393","messages":"394","suppressedMessages":"395","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"396","messages":"397","suppressedMessages":"398","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"399","messages":"400","suppressedMessages":"401","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"402","messages":"403","suppressedMessages":"404","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"405","messages":"406","suppressedMessages":"407","errorCount":9,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"408","messages":"409","suppressedMessages":"410","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"411","messages":"412","suppressedMessages":"413","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"414","messages":"415","suppressedMessages":"416","errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"417","messages":"418","suppressedMessages":"419","errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"420","messages":"421","suppressedMessages":"422","errorCount":4,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"423","messages":"424","suppressedMessages":"425","errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"426","messages":"427","suppressedMessages":"428","errorCount":3,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"429","messages":"430","suppressedMessages":"431","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"432","messages":"433","suppressedMessages":"434","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"435","messages":"436","suppressedMessages":"437","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"438","messages":"439","suppressedMessages":"440","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"441","messages":"442","suppressedMessages":"443","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"444","messages":"445","suppressedMessages":"446","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"447","messages":"448","suppressedMessages":"449","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"450","messages":"451","suppressedMessages":"452","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"453","messages":"454","suppressedMessages":"455","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"456","messages":"457","suppressedMessages":"458","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"459","messages":"460","suppressedMessages":"461","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"462","messages":"463","suppressedMessages":"464","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"465","messages":"466","suppressedMessages":"467","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"468","messages":"469","suppressedMessages":"470","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"471","messages":"472","suppressedMessages":"473","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"474","messages":"475","suppressedMessages":"476","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"477","messages":"478","suppressedMessages":"479","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"480","messages":"481","suppressedMessages":"482","errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"483","messages":"484","suppressedMessages":"485","errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"486","messages":"487","suppressedMessages":"488","errorCount":34,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"489","messages":"490","suppressedMessages":"491","errorCount":41,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"492","messages":"493","suppressedMessages":"494","errorCount":38,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"495","messages":"496","suppressedMessages":"497","errorCount":303,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"498","messages":"499","suppressedMessages":"500","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"501","messages":"502","suppressedMessages":"503","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"504","messages":"505","suppressedMessages":"506","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"507","messages":"508","suppressedMessages":"509","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"510","messages":"511","suppressedMessages":"512","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"513","messages":"514","suppressedMessages":"515","errorCount":5,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"516","messages":"517","suppressedMessages":"518","errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"519","messages":"520","suppressedMessages":"521","errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},"wmhd7i",{"filePath":"522","messages":"523","suppressedMessages":"524","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"525","messages":"526","suppressedMessages":"527","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"528","messages":"529","suppressedMessages":"530","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"531","messages":"532","suppressedMessages":"533","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"534","messages":"535","suppressedMessages":"536","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"537","messages":"538","suppressedMessages":"539","errorCount":1,"fatalErrorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"540","messages":"541","suppressedMessages":"542","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/.eslintrc.js",["543"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/adapters/application.js",["544","545","546","547","548"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/app.js",["549"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/base-sortable.js",["550"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/basefield.js",["551"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/booleanfield.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/choicefield.js",["552"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/hiddenfield.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/index.js",["553"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/textfield.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields.js",["554"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/index.js",["555"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/rules.js",["556"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/submissions.js",["557"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/form.js",["558"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-checkbox-select-multiple.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-checkbox.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-email.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-full-name.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-hidden.js",["559"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-integer.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-phone-number.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-radio-select.js",["560"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-select-multiple.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-select.js",["561"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-text.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-textarea.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/rule-condition.js",["562"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/rule-result.js",["563"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/sidebar.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-field.js",["564"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-fields.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-rule.js",["565"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-rules.js",["566"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/components/tinymce-editor.js",["567"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/locations/auto.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/basefield.js",["568"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/booleanfield.js",["569"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/choicefield.js",["570"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/field.js",["571"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/form.js",["572"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/hiddenfield.js",["573"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/option.js",["574"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/optiongroup.js",["575"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/optionlist.js",["576"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/privacypolicy.js",["577"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/rule.js",["578"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/rulecondition.js",["579"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/ruleresult.js",["580"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/submission.js",["581"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/submissionsource.js",["582"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/models/textfield.js",["583"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/modifiers/sortable-group.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/resolver.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/router.js",["584"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/fields.js",["585"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/index.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/rules.js",["586"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/submissions.js",["587"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form.js",["588"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/booleanfield.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/choicefield.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/field.js",["589","590","591","592","593","594","595","596","597"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/form.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/hiddenfield.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/option.js",["598","599","600"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/optiongroup.js",["601","602","603"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/optionlist.js",["604","605","606","607"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/privacypolicy.js",["608","609"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/rule.js",["610","611","612"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/textfield.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/services/cookies.js",["613"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/services/field-service.js",["614"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/transforms/boolean.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/transforms/number.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/transforms/string.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/utils/fields.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/utils/slug.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/validators/factories.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/validators/fields/basefield.js",["615"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/validators/fields/booleanfield.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/validators/fields/choicefield.js",["616"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/validators/fields/hiddenfield.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/validators/fields/textfield.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/validators/rules/rule.js",["617"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/validators/rules/rulecondition.js",["618"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/app/validators/rules/ruleresult.js",["619"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/config/environment.js",["620"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/config/targets.js",["621"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/dist/assets/chunk.app.5e38629b8b374693d5ac.js",["622","623","624","625","626","627","628","629","630","631","632","633","634","635","636","637","638","639","640","641","642","643","644","645","646","647","648","649","650","651","652","653","654","655"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/dist/assets/chunk.tests.609240ba01ee46bd0079.js",["656","657","658","659","660","661","662","663","664","665","666","667","668","669","670","671","672","673","674","675","676","677","678","679","680","681","682","683","684","685","686","687","688","689","690","691","692","693","694","695","696"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/dist/assets/chunk.vendors-node_modules_ember-qunit_dist_index_js-node_modules_dom-element-descriptors_dist_es_i-a01131.a66c7f2b824580009561.js",["697","698","699","700","701","702","703","704","705","706","707","708","709","710","711","712","713","714","715","716","717","718","719","720","721","722","723","724","725","726","727","728","729","730","731","732","733","734"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/dist/assets/chunk.vendors-node_modules_popperjs_core_lib_index_js-node_modules_ember-element-helper_dist_helper-87c8c0.ef646b89b449250c4da5.js",["735","736","737","738","739","740","741","742","743","744","745","746","747","748","749","750","751","752","753","754","755","756","757","758","759","760","761","762","763","764","765","766","767","768","769","770","771","772","773","774","775","776","777","778","779","780","781","782","783","784","785","786","787","788","789","790","791","792","793","794","795","796","797","798","799","800","801","802","803","804","805","806","807","808","809","810","811","812","813","814","815","816","817","818","819","820","821","822","823","824","825","826","827","828","829","830","831","832","833","834","835","836","837","838","839","840","841","842","843","844","845","846","847","848","849","850","851","852","853","854","855","856","857","858","859","860","861","862","863","864","865","866","867","868","869","870","871","872","873","874","875","876","877","878","879","880","881","882","883","884","885","886","887","888","889","890","891","892","893","894","895","896","897","898","899","900","901","902","903","904","905","906","907","908","909","910","911","912","913","914","915","916","917","918","919","920","921","922","923","924","925","926","927","928","929","930","931","932","933","934","935","936","937","938","939","940","941","942","943","944","945","946","947","948","949","950","951","952","953","954","955","956","957","958","959","960","961","962","963","964","965","966","967","968","969","970","971","972","973","974","975","976","977","978","979","980","981","982","983","984","985","986","987","988","989","990","991","992","993","994","995","996","997","998","999","1000","1001","1002","1003","1004","1005","1006","1007","1008","1009","1010","1011","1012","1013","1014","1015","1016","1017","1018","1019","1020","1021","1022","1023","1024","1025","1026","1027","1028","1029","1030","1031","1032","1033","1034","1035","1036","1037"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/dist/assets/ember-formulaic.js",["1038"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/dist/assets/test-support.js",["1039"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/dist/assets/tests.js",["1040"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/dist/assets/vendor.js",["1041"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/dist/testem.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/ember-cli-build.js",["1042","1043","1044","1045","1046"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/testem.js",["1047","1048"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/tests/.eslintrc.js",["1049"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/tests/helpers/destroy-app.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/tests/helpers/index.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/tests/helpers/module-for-acceptance.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/tests/helpers/resolver.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/tests/helpers/start-app.js",[],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/tests/integration/components/sidebar-test.js",["1050"],[],"/Users/ronnieodima/PycharmProjects/formulaic/django-formulaic/formulaic/static/admin/formulaic/ember-formulaic/tests/test-helper.js",[],[],{"ruleId":"1051","severity":2,"message":"1052","line":1,"column":1,"nodeType":"1053","messageId":"1054","endLine":1,"endColumn":7},{"ruleId":"1055","severity":2,"message":"1056","line":15,"column":12,"nodeType":"1053","messageId":"1057","endLine":15,"endColumn":21},{"ruleId":"1055","severity":2,"message":"1058","line":15,"column":23,"nodeType":"1053","messageId":"1057","endLine":15,"endColumn":25},{"ruleId":"1055","severity":2,"message":"1059","line":15,"column":27,"nodeType":"1053","messageId":"1057","endLine":15,"endColumn":35},{"ruleId":"1055","severity":2,"message":"1060","line":15,"column":37,"nodeType":"1053","messageId":"1057","endLine":15,"endColumn":48},{"ruleId":"1055","severity":2,"message":"1061","line":15,"column":50,"nodeType":"1053","messageId":"1057","endLine":15,"endColumn":55},{"ruleId":null,"fatal":true,"severity":2,"message":"1062","line":7,"column":16,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":9,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":10,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":10,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":7,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":12,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":10,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":12,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":9,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":7,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":5,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":5,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":5,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":12,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":7,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":17,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":7,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":7,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1062","line":5,"column":10,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":4,"column":5,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":6,"column":5,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":6,"column":5,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":5,"column":5,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":4,"column":5,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":6,"column":5,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":4,"column":5,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":4,"column":5,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":4,"column":5,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":4,"column":5,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":6,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":5,"column":5,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":5,"column":5,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":4,"column":5,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":6,"column":5,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":6,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1062","line":5,"column":12,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":7,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":5,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":8,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":7,"column":3,"nodeType":null},{"ruleId":"1055","severity":2,"message":"1058","line":4,"column":56,"nodeType":"1053","messageId":"1057","endLine":4,"endColumn":58},{"ruleId":"1055","severity":2,"message":"1060","line":4,"column":60,"nodeType":"1053","messageId":"1057","endLine":4,"endColumn":71},{"ruleId":"1051","severity":2,"message":"1064","line":49,"column":30,"nodeType":"1053","messageId":"1054","endLine":49,"endColumn":33},{"ruleId":"1051","severity":2,"message":"1064","line":50,"column":33,"nodeType":"1053","messageId":"1054","endLine":50,"endColumn":36},{"ruleId":"1051","severity":2,"message":"1064","line":51,"column":32,"nodeType":"1053","messageId":"1054","endLine":51,"endColumn":35},{"ruleId":"1051","severity":2,"message":"1064","line":52,"column":32,"nodeType":"1053","messageId":"1054","endLine":52,"endColumn":35},{"ruleId":"1051","severity":2,"message":"1064","line":53,"column":31,"nodeType":"1053","messageId":"1054","endLine":53,"endColumn":34},{"ruleId":"1051","severity":2,"message":"1064","line":54,"column":32,"nodeType":"1053","messageId":"1054","endLine":54,"endColumn":35},{"ruleId":"1051","severity":2,"message":"1064","line":55,"column":27,"nodeType":"1053","messageId":"1054","endLine":55,"endColumn":30},{"ruleId":"1055","severity":2,"message":"1058","line":4,"column":56,"nodeType":"1053","messageId":"1057","endLine":4,"endColumn":58},{"ruleId":"1055","severity":2,"message":"1060","line":4,"column":60,"nodeType":"1053","messageId":"1057","endLine":4,"endColumn":71},{"ruleId":"1055","severity":2,"message":"1065","line":5,"column":15,"nodeType":"1053","messageId":"1057","endLine":5,"endColumn":23},{"ruleId":"1055","severity":2,"message":"1058","line":4,"column":56,"nodeType":"1053","messageId":"1057","endLine":4,"endColumn":58},{"ruleId":"1055","severity":2,"message":"1060","line":4,"column":60,"nodeType":"1053","messageId":"1057","endLine":4,"endColumn":71},{"ruleId":"1051","severity":2,"message":"1064","line":38,"column":27,"nodeType":"1053","messageId":"1054","endLine":38,"endColumn":30},{"ruleId":"1055","severity":2,"message":"1058","line":4,"column":56,"nodeType":"1053","messageId":"1057","endLine":4,"endColumn":58},{"ruleId":"1055","severity":2,"message":"1060","line":4,"column":60,"nodeType":"1053","messageId":"1057","endLine":4,"endColumn":71},{"ruleId":"1051","severity":2,"message":"1064","line":37,"column":27,"nodeType":"1053","messageId":"1054","endLine":37,"endColumn":30},{"ruleId":"1051","severity":2,"message":"1064","line":38,"column":32,"nodeType":"1053","messageId":"1054","endLine":38,"endColumn":35},{"ruleId":"1055","severity":2,"message":"1058","line":4,"column":56,"nodeType":"1053","messageId":"1057","endLine":4,"endColumn":58},{"ruleId":"1055","severity":2,"message":"1060","line":4,"column":60,"nodeType":"1053","messageId":"1057","endLine":4,"endColumn":71},{"ruleId":"1055","severity":2,"message":"1058","line":4,"column":56,"nodeType":"1053","messageId":"1057","endLine":4,"endColumn":58},{"ruleId":"1055","severity":2,"message":"1060","line":4,"column":60,"nodeType":"1053","messageId":"1057","endLine":4,"endColumn":71},{"ruleId":"1055","severity":2,"message":"1066","line":101,"column":23,"nodeType":"1053","messageId":"1057","endLine":101,"endColumn":30},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":5,"column":2,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":10,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":6,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":5,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":4,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":5,"column":3,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1063","line":4,"column":3,"nodeType":null},{"ruleId":"1051","severity":2,"message":"1052","line":3,"column":1,"nodeType":"1053","messageId":"1054","endLine":3,"endColumn":7},{"ruleId":"1051","severity":2,"message":"1052","line":9,"column":1,"nodeType":"1053","messageId":"1054","endLine":9,"endColumn":7},{"ruleId":"1055","severity":2,"message":"1067","line":9,"column":5,"nodeType":"1053","messageId":"1057","endLine":9,"endColumn":26},{"ruleId":"1051","severity":2,"message":"1068","line":20,"column":18,"nodeType":"1053","messageId":"1054","endLine":20,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":31,"column":18,"nodeType":"1053","messageId":"1054","endLine":31,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":42,"column":18,"nodeType":"1053","messageId":"1054","endLine":42,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":53,"column":18,"nodeType":"1053","messageId":"1054","endLine":53,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":64,"column":18,"nodeType":"1053","messageId":"1054","endLine":64,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":75,"column":18,"nodeType":"1053","messageId":"1054","endLine":75,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":86,"column":18,"nodeType":"1053","messageId":"1054","endLine":86,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":97,"column":18,"nodeType":"1053","messageId":"1054","endLine":97,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":108,"column":18,"nodeType":"1053","messageId":"1054","endLine":108,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":119,"column":18,"nodeType":"1053","messageId":"1054","endLine":119,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":130,"column":18,"nodeType":"1053","messageId":"1054","endLine":130,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":141,"column":18,"nodeType":"1053","messageId":"1054","endLine":141,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":152,"column":18,"nodeType":"1053","messageId":"1054","endLine":152,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":163,"column":18,"nodeType":"1053","messageId":"1054","endLine":163,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":174,"column":18,"nodeType":"1053","messageId":"1054","endLine":174,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":185,"column":18,"nodeType":"1053","messageId":"1054","endLine":185,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":196,"column":18,"nodeType":"1053","messageId":"1054","endLine":196,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":207,"column":18,"nodeType":"1053","messageId":"1054","endLine":207,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":218,"column":18,"nodeType":"1053","messageId":"1054","endLine":218,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":229,"column":18,"nodeType":"1053","messageId":"1054","endLine":229,"endColumn":25},{"ruleId":"1055","severity":2,"message":"1069","line":247,"column":9,"nodeType":"1053","messageId":"1057","endLine":247,"endColumn":15},{"ruleId":"1055","severity":2,"message":"1070","line":247,"column":17,"nodeType":"1053","messageId":"1057","endLine":247,"endColumn":41},{"ruleId":"1055","severity":2,"message":"1071","line":247,"column":43,"nodeType":"1053","messageId":"1057","endLine":247,"endColumn":62},{"ruleId":"1055","severity":2,"message":"1069","line":257,"column":17,"nodeType":"1053","messageId":"1057","endLine":257,"endColumn":23},{"ruleId":"1055","severity":2,"message":"1072","line":257,"column":25,"nodeType":"1053","messageId":"1057","endLine":257,"endColumn":32},{"ruleId":"1073","severity":2,"message":"1074","line":304,"column":22,"nodeType":"1053","messageId":"1075","endLine":304,"endColumn":23},{"ruleId":"1073","severity":2,"message":"1076","line":305,"column":19,"nodeType":"1053","messageId":"1075","endLine":305,"endColumn":27},{"ruleId":"1073","severity":2,"message":"1077","line":305,"column":29,"nodeType":"1053","messageId":"1075","endLine":305,"endColumn":31},{"ruleId":"1073","severity":2,"message":"1078","line":305,"column":33,"nodeType":"1053","messageId":"1075","endLine":305,"endColumn":41},{"ruleId":"1051","severity":2,"message":"1079","line":358,"column":49,"nodeType":"1053","messageId":"1054","endLine":358,"endColumn":55},{"ruleId":"1051","severity":2,"message":"1079","line":359,"column":45,"nodeType":"1053","messageId":"1054","endLine":359,"endColumn":51},{"ruleId":"1051","severity":2,"message":"1080","line":413,"column":37,"nodeType":"1053","messageId":"1054","endLine":413,"endColumn":47},{"ruleId":"1051","severity":2,"message":"1080","line":413,"column":85,"nodeType":"1053","messageId":"1054","endLine":413,"endColumn":95},{"ruleId":"1055","severity":2,"message":"1067","line":9,"column":5,"nodeType":"1053","messageId":"1057","endLine":9,"endColumn":26},{"ruleId":"1051","severity":2,"message":"1068","line":20,"column":18,"nodeType":"1053","messageId":"1054","endLine":20,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":31,"column":18,"nodeType":"1053","messageId":"1054","endLine":31,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":42,"column":18,"nodeType":"1053","messageId":"1054","endLine":42,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":53,"column":18,"nodeType":"1053","messageId":"1054","endLine":53,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":64,"column":18,"nodeType":"1053","messageId":"1054","endLine":64,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":75,"column":18,"nodeType":"1053","messageId":"1054","endLine":75,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":86,"column":18,"nodeType":"1053","messageId":"1054","endLine":86,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":97,"column":18,"nodeType":"1053","messageId":"1054","endLine":97,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":108,"column":18,"nodeType":"1053","messageId":"1054","endLine":108,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":119,"column":18,"nodeType":"1053","messageId":"1054","endLine":119,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":130,"column":18,"nodeType":"1053","messageId":"1054","endLine":130,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":141,"column":18,"nodeType":"1053","messageId":"1054","endLine":141,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":152,"column":18,"nodeType":"1053","messageId":"1054","endLine":152,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":163,"column":18,"nodeType":"1053","messageId":"1054","endLine":163,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":174,"column":18,"nodeType":"1053","messageId":"1054","endLine":174,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":185,"column":18,"nodeType":"1053","messageId":"1054","endLine":185,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":196,"column":18,"nodeType":"1053","messageId":"1054","endLine":196,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":207,"column":18,"nodeType":"1053","messageId":"1054","endLine":207,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":218,"column":18,"nodeType":"1053","messageId":"1054","endLine":218,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":229,"column":18,"nodeType":"1053","messageId":"1054","endLine":229,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":240,"column":18,"nodeType":"1053","messageId":"1054","endLine":240,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":251,"column":18,"nodeType":"1053","messageId":"1054","endLine":251,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":262,"column":18,"nodeType":"1053","messageId":"1054","endLine":262,"endColumn":25},{"ruleId":"1051","severity":2,"message":"1068","line":273,"column":18,"nodeType":"1053","messageId":"1054","endLine":273,"endColumn":25},{"ruleId":"1055","severity":2,"message":"1069","line":291,"column":9,"nodeType":"1053","messageId":"1057","endLine":291,"endColumn":15},{"ruleId":"1055","severity":2,"message":"1070","line":291,"column":17,"nodeType":"1053","messageId":"1057","endLine":291,"endColumn":41},{"ruleId":"1055","severity":2,"message":"1071","line":291,"column":43,"nodeType":"1053","messageId":"1057","endLine":291,"endColumn":62},{"ruleId":"1055","severity":2,"message":"1069","line":301,"column":17,"nodeType":"1053","messageId":"1057","endLine":301,"endColumn":23},{"ruleId":"1055","severity":2,"message":"1072","line":301,"column":25,"nodeType":"1053","messageId":"1057","endLine":301,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1069","line":311,"column":9,"nodeType":"1053","messageId":"1057","endLine":311,"endColumn":15},{"ruleId":"1055","severity":2,"message":"1070","line":311,"column":17,"nodeType":"1053","messageId":"1057","endLine":311,"endColumn":41},{"ruleId":"1055","severity":2,"message":"1071","line":311,"column":43,"nodeType":"1053","messageId":"1057","endLine":311,"endColumn":62},{"ruleId":"1073","severity":2,"message":"1074","line":361,"column":22,"nodeType":"1053","messageId":"1075","endLine":361,"endColumn":23},{"ruleId":"1073","severity":2,"message":"1076","line":362,"column":19,"nodeType":"1053","messageId":"1075","endLine":362,"endColumn":27},{"ruleId":"1073","severity":2,"message":"1077","line":362,"column":29,"nodeType":"1053","messageId":"1075","endLine":362,"endColumn":31},{"ruleId":"1073","severity":2,"message":"1078","line":362,"column":33,"nodeType":"1053","messageId":"1075","endLine":362,"endColumn":41},{"ruleId":"1051","severity":2,"message":"1079","line":415,"column":49,"nodeType":"1053","messageId":"1054","endLine":415,"endColumn":55},{"ruleId":"1051","severity":2,"message":"1079","line":416,"column":45,"nodeType":"1053","messageId":"1054","endLine":416,"endColumn":51},{"ruleId":"1051","severity":2,"message":"1080","line":479,"column":37,"nodeType":"1053","messageId":"1054","endLine":479,"endColumn":47},{"ruleId":"1051","severity":2,"message":"1080","line":479,"column":85,"nodeType":"1053","messageId":"1054","endLine":479,"endColumn":95},{"ruleId":"1051","severity":2,"message":"1080","line":9,"column":2,"nodeType":"1053","messageId":"1054","endLine":9,"endColumn":12},{"ruleId":"1051","severity":2,"message":"1080","line":9,"column":50,"nodeType":"1053","messageId":"1054","endLine":9,"endColumn":60},{"ruleId":"1055","severity":2,"message":"1081","line":15,"column":9,"nodeType":"1053","messageId":"1057","endLine":15,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":15,"column":34,"nodeType":"1053","messageId":"1057","endLine":15,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":15,"column":55,"nodeType":"1053","messageId":"1057","endLine":15,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":26,"column":9,"nodeType":"1053","messageId":"1057","endLine":26,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":26,"column":34,"nodeType":"1053","messageId":"1057","endLine":26,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":26,"column":55,"nodeType":"1053","messageId":"1057","endLine":26,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":37,"column":9,"nodeType":"1053","messageId":"1057","endLine":37,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":37,"column":34,"nodeType":"1053","messageId":"1057","endLine":37,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":37,"column":55,"nodeType":"1053","messageId":"1057","endLine":37,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":48,"column":9,"nodeType":"1053","messageId":"1057","endLine":48,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":48,"column":34,"nodeType":"1053","messageId":"1057","endLine":48,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":48,"column":55,"nodeType":"1053","messageId":"1057","endLine":48,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":59,"column":9,"nodeType":"1053","messageId":"1057","endLine":59,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":59,"column":34,"nodeType":"1053","messageId":"1057","endLine":59,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":59,"column":55,"nodeType":"1053","messageId":"1057","endLine":59,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":70,"column":9,"nodeType":"1053","messageId":"1057","endLine":70,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":70,"column":34,"nodeType":"1053","messageId":"1057","endLine":70,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":70,"column":55,"nodeType":"1053","messageId":"1057","endLine":70,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1069","line":81,"column":9,"nodeType":"1053","messageId":"1057","endLine":81,"endColumn":15},{"ruleId":"1055","severity":2,"message":"1072","line":81,"column":17,"nodeType":"1053","messageId":"1057","endLine":81,"endColumn":24},{"ruleId":"1055","severity":2,"message":"1071","line":81,"column":26,"nodeType":"1053","messageId":"1057","endLine":81,"endColumn":45},{"ruleId":"1055","severity":2,"message":"1069","line":91,"column":9,"nodeType":"1053","messageId":"1057","endLine":91,"endColumn":15},{"ruleId":"1055","severity":2,"message":"1082","line":91,"column":17,"nodeType":"1053","messageId":"1057","endLine":91,"endColumn":36},{"ruleId":"1055","severity":2,"message":"1071","line":91,"column":38,"nodeType":"1053","messageId":"1057","endLine":91,"endColumn":57},{"ruleId":"1055","severity":2,"message":"1069","line":102,"column":9,"nodeType":"1053","messageId":"1057","endLine":102,"endColumn":15},{"ruleId":"1055","severity":2,"message":"1082","line":102,"column":17,"nodeType":"1053","messageId":"1057","endLine":102,"endColumn":36},{"ruleId":"1055","severity":2,"message":"1071","line":102,"column":38,"nodeType":"1053","messageId":"1057","endLine":102,"endColumn":57},{"ruleId":"1055","severity":2,"message":"1081","line":113,"column":9,"nodeType":"1053","messageId":"1057","endLine":113,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":113,"column":34,"nodeType":"1053","messageId":"1057","endLine":113,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":113,"column":55,"nodeType":"1053","messageId":"1057","endLine":113,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":124,"column":9,"nodeType":"1053","messageId":"1057","endLine":124,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":124,"column":34,"nodeType":"1053","messageId":"1057","endLine":124,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":124,"column":55,"nodeType":"1053","messageId":"1057","endLine":124,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1083","line":135,"column":9,"nodeType":"1053","messageId":"1057","endLine":135,"endColumn":44},{"ruleId":"1055","severity":2,"message":"1082","line":135,"column":46,"nodeType":"1053","messageId":"1057","endLine":135,"endColumn":65},{"ruleId":"1055","severity":2,"message":"1071","line":135,"column":67,"nodeType":"1053","messageId":"1057","endLine":135,"endColumn":86},{"ruleId":"1051","severity":2,"message":"1080","line":10,"column":2,"nodeType":"1053","messageId":"1054","endLine":10,"endColumn":12},{"ruleId":"1051","severity":2,"message":"1080","line":10,"column":50,"nodeType":"1053","messageId":"1054","endLine":10,"endColumn":60},{"ruleId":"1055","severity":2,"message":"1081","line":16,"column":9,"nodeType":"1053","messageId":"1057","endLine":16,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":16,"column":34,"nodeType":"1053","messageId":"1057","endLine":16,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":16,"column":55,"nodeType":"1053","messageId":"1057","endLine":16,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":26,"column":9,"nodeType":"1053","messageId":"1057","endLine":26,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":26,"column":34,"nodeType":"1053","messageId":"1057","endLine":26,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":26,"column":55,"nodeType":"1053","messageId":"1057","endLine":26,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":36,"column":9,"nodeType":"1053","messageId":"1057","endLine":36,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":36,"column":34,"nodeType":"1053","messageId":"1057","endLine":36,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":36,"column":55,"nodeType":"1053","messageId":"1057","endLine":36,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":46,"column":9,"nodeType":"1053","messageId":"1057","endLine":46,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":46,"column":34,"nodeType":"1053","messageId":"1057","endLine":46,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":46,"column":55,"nodeType":"1053","messageId":"1057","endLine":46,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":56,"column":9,"nodeType":"1053","messageId":"1057","endLine":56,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":56,"column":34,"nodeType":"1053","messageId":"1057","endLine":56,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":56,"column":55,"nodeType":"1053","messageId":"1057","endLine":56,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":66,"column":9,"nodeType":"1053","messageId":"1057","endLine":66,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":66,"column":34,"nodeType":"1053","messageId":"1057","endLine":66,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":66,"column":55,"nodeType":"1053","messageId":"1057","endLine":66,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":76,"column":9,"nodeType":"1053","messageId":"1057","endLine":76,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":76,"column":34,"nodeType":"1053","messageId":"1057","endLine":76,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":76,"column":55,"nodeType":"1053","messageId":"1057","endLine":76,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":86,"column":9,"nodeType":"1053","messageId":"1057","endLine":86,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":86,"column":34,"nodeType":"1053","messageId":"1057","endLine":86,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":86,"column":55,"nodeType":"1053","messageId":"1057","endLine":86,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":96,"column":9,"nodeType":"1053","messageId":"1057","endLine":96,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":96,"column":34,"nodeType":"1053","messageId":"1057","endLine":96,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":96,"column":55,"nodeType":"1053","messageId":"1057","endLine":96,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":106,"column":9,"nodeType":"1053","messageId":"1057","endLine":106,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":106,"column":34,"nodeType":"1053","messageId":"1057","endLine":106,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":106,"column":55,"nodeType":"1053","messageId":"1057","endLine":106,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":116,"column":9,"nodeType":"1053","messageId":"1057","endLine":116,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":116,"column":34,"nodeType":"1053","messageId":"1057","endLine":116,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":116,"column":55,"nodeType":"1053","messageId":"1057","endLine":116,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":126,"column":9,"nodeType":"1053","messageId":"1057","endLine":126,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":126,"column":34,"nodeType":"1053","messageId":"1057","endLine":126,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":126,"column":55,"nodeType":"1053","messageId":"1057","endLine":126,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":136,"column":9,"nodeType":"1053","messageId":"1057","endLine":136,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":136,"column":34,"nodeType":"1053","messageId":"1057","endLine":136,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":136,"column":55,"nodeType":"1053","messageId":"1057","endLine":136,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":146,"column":9,"nodeType":"1053","messageId":"1057","endLine":146,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":146,"column":34,"nodeType":"1053","messageId":"1057","endLine":146,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":146,"column":55,"nodeType":"1053","messageId":"1057","endLine":146,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":156,"column":9,"nodeType":"1053","messageId":"1057","endLine":156,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":156,"column":34,"nodeType":"1053","messageId":"1057","endLine":156,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":156,"column":55,"nodeType":"1053","messageId":"1057","endLine":156,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":166,"column":9,"nodeType":"1053","messageId":"1057","endLine":166,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":166,"column":34,"nodeType":"1053","messageId":"1057","endLine":166,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":166,"column":55,"nodeType":"1053","messageId":"1057","endLine":166,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":176,"column":9,"nodeType":"1053","messageId":"1057","endLine":176,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":176,"column":34,"nodeType":"1053","messageId":"1057","endLine":176,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":176,"column":55,"nodeType":"1053","messageId":"1057","endLine":176,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":186,"column":9,"nodeType":"1053","messageId":"1057","endLine":186,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":186,"column":34,"nodeType":"1053","messageId":"1057","endLine":186,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":186,"column":55,"nodeType":"1053","messageId":"1057","endLine":186,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":196,"column":9,"nodeType":"1053","messageId":"1057","endLine":196,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":196,"column":34,"nodeType":"1053","messageId":"1057","endLine":196,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":196,"column":55,"nodeType":"1053","messageId":"1057","endLine":196,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":206,"column":9,"nodeType":"1053","messageId":"1057","endLine":206,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":206,"column":34,"nodeType":"1053","messageId":"1057","endLine":206,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":206,"column":55,"nodeType":"1053","messageId":"1057","endLine":206,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":216,"column":9,"nodeType":"1053","messageId":"1057","endLine":216,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":216,"column":34,"nodeType":"1053","messageId":"1057","endLine":216,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":216,"column":55,"nodeType":"1053","messageId":"1057","endLine":216,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":226,"column":9,"nodeType":"1053","messageId":"1057","endLine":226,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":226,"column":34,"nodeType":"1053","messageId":"1057","endLine":226,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":226,"column":55,"nodeType":"1053","messageId":"1057","endLine":226,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":236,"column":9,"nodeType":"1053","messageId":"1057","endLine":236,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":236,"column":34,"nodeType":"1053","messageId":"1057","endLine":236,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":236,"column":55,"nodeType":"1053","messageId":"1057","endLine":236,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":246,"column":9,"nodeType":"1053","messageId":"1057","endLine":246,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":246,"column":34,"nodeType":"1053","messageId":"1057","endLine":246,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":246,"column":55,"nodeType":"1053","messageId":"1057","endLine":246,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":256,"column":9,"nodeType":"1053","messageId":"1057","endLine":256,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":256,"column":34,"nodeType":"1053","messageId":"1057","endLine":256,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":256,"column":55,"nodeType":"1053","messageId":"1057","endLine":256,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":266,"column":9,"nodeType":"1053","messageId":"1057","endLine":266,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":266,"column":34,"nodeType":"1053","messageId":"1057","endLine":266,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":266,"column":55,"nodeType":"1053","messageId":"1057","endLine":266,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":276,"column":9,"nodeType":"1053","messageId":"1057","endLine":276,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":276,"column":34,"nodeType":"1053","messageId":"1057","endLine":276,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":276,"column":55,"nodeType":"1053","messageId":"1057","endLine":276,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":286,"column":9,"nodeType":"1053","messageId":"1057","endLine":286,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":286,"column":34,"nodeType":"1053","messageId":"1057","endLine":286,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":286,"column":55,"nodeType":"1053","messageId":"1057","endLine":286,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":296,"column":9,"nodeType":"1053","messageId":"1057","endLine":296,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":296,"column":34,"nodeType":"1053","messageId":"1057","endLine":296,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":296,"column":55,"nodeType":"1053","messageId":"1057","endLine":296,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":306,"column":9,"nodeType":"1053","messageId":"1057","endLine":306,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":306,"column":34,"nodeType":"1053","messageId":"1057","endLine":306,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":306,"column":55,"nodeType":"1053","messageId":"1057","endLine":306,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":316,"column":9,"nodeType":"1053","messageId":"1057","endLine":316,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":316,"column":34,"nodeType":"1053","messageId":"1057","endLine":316,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":316,"column":55,"nodeType":"1053","messageId":"1057","endLine":316,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":326,"column":9,"nodeType":"1053","messageId":"1057","endLine":326,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":326,"column":34,"nodeType":"1053","messageId":"1057","endLine":326,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":326,"column":55,"nodeType":"1053","messageId":"1057","endLine":326,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":336,"column":9,"nodeType":"1053","messageId":"1057","endLine":336,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":336,"column":34,"nodeType":"1053","messageId":"1057","endLine":336,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":336,"column":55,"nodeType":"1053","messageId":"1057","endLine":336,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":346,"column":9,"nodeType":"1053","messageId":"1057","endLine":346,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":346,"column":34,"nodeType":"1053","messageId":"1057","endLine":346,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":346,"column":55,"nodeType":"1053","messageId":"1057","endLine":346,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":356,"column":9,"nodeType":"1053","messageId":"1057","endLine":356,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":356,"column":34,"nodeType":"1053","messageId":"1057","endLine":356,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":356,"column":55,"nodeType":"1053","messageId":"1057","endLine":356,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":366,"column":9,"nodeType":"1053","messageId":"1057","endLine":366,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":366,"column":34,"nodeType":"1053","messageId":"1057","endLine":366,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":366,"column":55,"nodeType":"1053","messageId":"1057","endLine":366,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":376,"column":9,"nodeType":"1053","messageId":"1057","endLine":376,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":376,"column":34,"nodeType":"1053","messageId":"1057","endLine":376,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":376,"column":55,"nodeType":"1053","messageId":"1057","endLine":376,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":386,"column":9,"nodeType":"1053","messageId":"1057","endLine":386,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":386,"column":34,"nodeType":"1053","messageId":"1057","endLine":386,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":386,"column":55,"nodeType":"1053","messageId":"1057","endLine":386,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":396,"column":9,"nodeType":"1053","messageId":"1057","endLine":396,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":396,"column":34,"nodeType":"1053","messageId":"1057","endLine":396,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":396,"column":55,"nodeType":"1053","messageId":"1057","endLine":396,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":406,"column":9,"nodeType":"1053","messageId":"1057","endLine":406,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":406,"column":34,"nodeType":"1053","messageId":"1057","endLine":406,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":406,"column":55,"nodeType":"1053","messageId":"1057","endLine":406,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":416,"column":9,"nodeType":"1053","messageId":"1057","endLine":416,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":416,"column":34,"nodeType":"1053","messageId":"1057","endLine":416,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":416,"column":55,"nodeType":"1053","messageId":"1057","endLine":416,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":426,"column":9,"nodeType":"1053","messageId":"1057","endLine":426,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":426,"column":34,"nodeType":"1053","messageId":"1057","endLine":426,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":426,"column":55,"nodeType":"1053","messageId":"1057","endLine":426,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":436,"column":9,"nodeType":"1053","messageId":"1057","endLine":436,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":436,"column":34,"nodeType":"1053","messageId":"1057","endLine":436,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":436,"column":55,"nodeType":"1053","messageId":"1057","endLine":436,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":446,"column":9,"nodeType":"1053","messageId":"1057","endLine":446,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":446,"column":34,"nodeType":"1053","messageId":"1057","endLine":446,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":446,"column":55,"nodeType":"1053","messageId":"1057","endLine":446,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":456,"column":9,"nodeType":"1053","messageId":"1057","endLine":456,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":456,"column":34,"nodeType":"1053","messageId":"1057","endLine":456,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":456,"column":55,"nodeType":"1053","messageId":"1057","endLine":456,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":466,"column":9,"nodeType":"1053","messageId":"1057","endLine":466,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":466,"column":34,"nodeType":"1053","messageId":"1057","endLine":466,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":466,"column":55,"nodeType":"1053","messageId":"1057","endLine":466,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":476,"column":9,"nodeType":"1053","messageId":"1057","endLine":476,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":476,"column":34,"nodeType":"1053","messageId":"1057","endLine":476,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":476,"column":55,"nodeType":"1053","messageId":"1057","endLine":476,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":486,"column":9,"nodeType":"1053","messageId":"1057","endLine":486,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":486,"column":34,"nodeType":"1053","messageId":"1057","endLine":486,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":486,"column":55,"nodeType":"1053","messageId":"1057","endLine":486,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":496,"column":9,"nodeType":"1053","messageId":"1057","endLine":496,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":496,"column":34,"nodeType":"1053","messageId":"1057","endLine":496,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":496,"column":55,"nodeType":"1053","messageId":"1057","endLine":496,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":506,"column":9,"nodeType":"1053","messageId":"1057","endLine":506,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":506,"column":34,"nodeType":"1053","messageId":"1057","endLine":506,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":506,"column":55,"nodeType":"1053","messageId":"1057","endLine":506,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":516,"column":9,"nodeType":"1053","messageId":"1057","endLine":516,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":516,"column":34,"nodeType":"1053","messageId":"1057","endLine":516,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":516,"column":55,"nodeType":"1053","messageId":"1057","endLine":516,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":526,"column":9,"nodeType":"1053","messageId":"1057","endLine":526,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":526,"column":34,"nodeType":"1053","messageId":"1057","endLine":526,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":526,"column":55,"nodeType":"1053","messageId":"1057","endLine":526,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":536,"column":9,"nodeType":"1053","messageId":"1057","endLine":536,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":536,"column":34,"nodeType":"1053","messageId":"1057","endLine":536,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":536,"column":55,"nodeType":"1053","messageId":"1057","endLine":536,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":546,"column":9,"nodeType":"1053","messageId":"1057","endLine":546,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":546,"column":34,"nodeType":"1053","messageId":"1057","endLine":546,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":546,"column":55,"nodeType":"1053","messageId":"1057","endLine":546,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":556,"column":9,"nodeType":"1053","messageId":"1057","endLine":556,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":556,"column":34,"nodeType":"1053","messageId":"1057","endLine":556,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":556,"column":55,"nodeType":"1053","messageId":"1057","endLine":556,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":566,"column":9,"nodeType":"1053","messageId":"1057","endLine":566,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":566,"column":34,"nodeType":"1053","messageId":"1057","endLine":566,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":566,"column":55,"nodeType":"1053","messageId":"1057","endLine":566,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":576,"column":9,"nodeType":"1053","messageId":"1057","endLine":576,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":576,"column":34,"nodeType":"1053","messageId":"1057","endLine":576,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":576,"column":55,"nodeType":"1053","messageId":"1057","endLine":576,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":586,"column":9,"nodeType":"1053","messageId":"1057","endLine":586,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":586,"column":34,"nodeType":"1053","messageId":"1057","endLine":586,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":586,"column":55,"nodeType":"1053","messageId":"1057","endLine":586,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":596,"column":9,"nodeType":"1053","messageId":"1057","endLine":596,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":596,"column":34,"nodeType":"1053","messageId":"1057","endLine":596,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":596,"column":55,"nodeType":"1053","messageId":"1057","endLine":596,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1069","line":606,"column":9,"nodeType":"1053","messageId":"1057","endLine":606,"endColumn":15},{"ruleId":"1055","severity":2,"message":"1081","line":616,"column":9,"nodeType":"1053","messageId":"1057","endLine":616,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":616,"column":34,"nodeType":"1053","messageId":"1057","endLine":616,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":616,"column":55,"nodeType":"1053","messageId":"1057","endLine":616,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":626,"column":9,"nodeType":"1053","messageId":"1057","endLine":626,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":626,"column":34,"nodeType":"1053","messageId":"1057","endLine":626,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":626,"column":55,"nodeType":"1053","messageId":"1057","endLine":626,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":636,"column":9,"nodeType":"1053","messageId":"1057","endLine":636,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":636,"column":34,"nodeType":"1053","messageId":"1057","endLine":636,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":636,"column":55,"nodeType":"1053","messageId":"1057","endLine":636,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":646,"column":9,"nodeType":"1053","messageId":"1057","endLine":646,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":646,"column":34,"nodeType":"1053","messageId":"1057","endLine":646,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":646,"column":55,"nodeType":"1053","messageId":"1057","endLine":646,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":656,"column":9,"nodeType":"1053","messageId":"1057","endLine":656,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":656,"column":34,"nodeType":"1053","messageId":"1057","endLine":656,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":656,"column":55,"nodeType":"1053","messageId":"1057","endLine":656,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":666,"column":9,"nodeType":"1053","messageId":"1057","endLine":666,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":666,"column":34,"nodeType":"1053","messageId":"1057","endLine":666,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":666,"column":55,"nodeType":"1053","messageId":"1057","endLine":666,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":676,"column":9,"nodeType":"1053","messageId":"1057","endLine":676,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":676,"column":34,"nodeType":"1053","messageId":"1057","endLine":676,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":676,"column":55,"nodeType":"1053","messageId":"1057","endLine":676,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":686,"column":9,"nodeType":"1053","messageId":"1057","endLine":686,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":686,"column":34,"nodeType":"1053","messageId":"1057","endLine":686,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":686,"column":55,"nodeType":"1053","messageId":"1057","endLine":686,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":696,"column":9,"nodeType":"1053","messageId":"1057","endLine":696,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":696,"column":34,"nodeType":"1053","messageId":"1057","endLine":696,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":696,"column":55,"nodeType":"1053","messageId":"1057","endLine":696,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":706,"column":9,"nodeType":"1053","messageId":"1057","endLine":706,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":706,"column":34,"nodeType":"1053","messageId":"1057","endLine":706,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":706,"column":55,"nodeType":"1053","messageId":"1057","endLine":706,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":716,"column":9,"nodeType":"1053","messageId":"1057","endLine":716,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":716,"column":34,"nodeType":"1053","messageId":"1057","endLine":716,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":716,"column":55,"nodeType":"1053","messageId":"1057","endLine":716,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":726,"column":9,"nodeType":"1053","messageId":"1057","endLine":726,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":726,"column":34,"nodeType":"1053","messageId":"1057","endLine":726,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":726,"column":55,"nodeType":"1053","messageId":"1057","endLine":726,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":736,"column":9,"nodeType":"1053","messageId":"1057","endLine":736,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":736,"column":34,"nodeType":"1053","messageId":"1057","endLine":736,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":736,"column":55,"nodeType":"1053","messageId":"1057","endLine":736,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":746,"column":9,"nodeType":"1053","messageId":"1057","endLine":746,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":746,"column":34,"nodeType":"1053","messageId":"1057","endLine":746,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":746,"column":55,"nodeType":"1053","messageId":"1057","endLine":746,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":756,"column":9,"nodeType":"1053","messageId":"1057","endLine":756,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":756,"column":34,"nodeType":"1053","messageId":"1057","endLine":756,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":756,"column":55,"nodeType":"1053","messageId":"1057","endLine":756,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":766,"column":9,"nodeType":"1053","messageId":"1057","endLine":766,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":766,"column":34,"nodeType":"1053","messageId":"1057","endLine":766,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":766,"column":55,"nodeType":"1053","messageId":"1057","endLine":766,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":776,"column":9,"nodeType":"1053","messageId":"1057","endLine":776,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":776,"column":34,"nodeType":"1053","messageId":"1057","endLine":776,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":776,"column":55,"nodeType":"1053","messageId":"1057","endLine":776,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":786,"column":9,"nodeType":"1053","messageId":"1057","endLine":786,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":786,"column":34,"nodeType":"1053","messageId":"1057","endLine":786,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":786,"column":55,"nodeType":"1053","messageId":"1057","endLine":786,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":796,"column":9,"nodeType":"1053","messageId":"1057","endLine":796,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":796,"column":34,"nodeType":"1053","messageId":"1057","endLine":796,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":796,"column":55,"nodeType":"1053","messageId":"1057","endLine":796,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":806,"column":9,"nodeType":"1053","messageId":"1057","endLine":806,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":806,"column":34,"nodeType":"1053","messageId":"1057","endLine":806,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":806,"column":55,"nodeType":"1053","messageId":"1057","endLine":806,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":816,"column":9,"nodeType":"1053","messageId":"1057","endLine":816,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":816,"column":34,"nodeType":"1053","messageId":"1057","endLine":816,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":816,"column":55,"nodeType":"1053","messageId":"1057","endLine":816,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":826,"column":9,"nodeType":"1053","messageId":"1057","endLine":826,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":826,"column":34,"nodeType":"1053","messageId":"1057","endLine":826,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":826,"column":55,"nodeType":"1053","messageId":"1057","endLine":826,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":836,"column":9,"nodeType":"1053","messageId":"1057","endLine":836,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":836,"column":34,"nodeType":"1053","messageId":"1057","endLine":836,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":836,"column":55,"nodeType":"1053","messageId":"1057","endLine":836,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":846,"column":9,"nodeType":"1053","messageId":"1057","endLine":846,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":846,"column":34,"nodeType":"1053","messageId":"1057","endLine":846,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":846,"column":55,"nodeType":"1053","messageId":"1057","endLine":846,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":856,"column":9,"nodeType":"1053","messageId":"1057","endLine":856,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":856,"column":34,"nodeType":"1053","messageId":"1057","endLine":856,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":856,"column":55,"nodeType":"1053","messageId":"1057","endLine":856,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":866,"column":9,"nodeType":"1053","messageId":"1057","endLine":866,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":866,"column":34,"nodeType":"1053","messageId":"1057","endLine":866,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":866,"column":55,"nodeType":"1053","messageId":"1057","endLine":866,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":876,"column":9,"nodeType":"1053","messageId":"1057","endLine":876,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":876,"column":34,"nodeType":"1053","messageId":"1057","endLine":876,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":876,"column":55,"nodeType":"1053","messageId":"1057","endLine":876,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":886,"column":9,"nodeType":"1053","messageId":"1057","endLine":886,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":886,"column":34,"nodeType":"1053","messageId":"1057","endLine":886,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":886,"column":55,"nodeType":"1053","messageId":"1057","endLine":886,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":896,"column":9,"nodeType":"1053","messageId":"1057","endLine":896,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":896,"column":34,"nodeType":"1053","messageId":"1057","endLine":896,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":896,"column":55,"nodeType":"1053","messageId":"1057","endLine":896,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":906,"column":9,"nodeType":"1053","messageId":"1057","endLine":906,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":906,"column":34,"nodeType":"1053","messageId":"1057","endLine":906,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":906,"column":55,"nodeType":"1053","messageId":"1057","endLine":906,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":916,"column":9,"nodeType":"1053","messageId":"1057","endLine":916,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":916,"column":34,"nodeType":"1053","messageId":"1057","endLine":916,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":916,"column":55,"nodeType":"1053","messageId":"1057","endLine":916,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":926,"column":9,"nodeType":"1053","messageId":"1057","endLine":926,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":926,"column":34,"nodeType":"1053","messageId":"1057","endLine":926,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":926,"column":55,"nodeType":"1053","messageId":"1057","endLine":926,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":936,"column":9,"nodeType":"1053","messageId":"1057","endLine":936,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":936,"column":34,"nodeType":"1053","messageId":"1057","endLine":936,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":936,"column":55,"nodeType":"1053","messageId":"1057","endLine":936,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":946,"column":9,"nodeType":"1053","messageId":"1057","endLine":946,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":946,"column":34,"nodeType":"1053","messageId":"1057","endLine":946,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":946,"column":55,"nodeType":"1053","messageId":"1057","endLine":946,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":956,"column":9,"nodeType":"1053","messageId":"1057","endLine":956,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":956,"column":34,"nodeType":"1053","messageId":"1057","endLine":956,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":956,"column":55,"nodeType":"1053","messageId":"1057","endLine":956,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":966,"column":9,"nodeType":"1053","messageId":"1057","endLine":966,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":966,"column":34,"nodeType":"1053","messageId":"1057","endLine":966,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":966,"column":55,"nodeType":"1053","messageId":"1057","endLine":966,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":976,"column":9,"nodeType":"1053","messageId":"1057","endLine":976,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":976,"column":34,"nodeType":"1053","messageId":"1057","endLine":976,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":976,"column":55,"nodeType":"1053","messageId":"1057","endLine":976,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1081","line":986,"column":9,"nodeType":"1053","messageId":"1057","endLine":986,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":986,"column":34,"nodeType":"1053","messageId":"1057","endLine":986,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":986,"column":55,"nodeType":"1053","messageId":"1057","endLine":986,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1069","line":996,"column":9,"nodeType":"1053","messageId":"1057","endLine":996,"endColumn":15},{"ruleId":"1055","severity":2,"message":"1082","line":996,"column":17,"nodeType":"1053","messageId":"1057","endLine":996,"endColumn":36},{"ruleId":"1055","severity":2,"message":"1071","line":996,"column":38,"nodeType":"1053","messageId":"1057","endLine":996,"endColumn":57},{"ruleId":"1055","severity":2,"message":"1081","line":1006,"column":9,"nodeType":"1053","messageId":"1057","endLine":1006,"endColumn":32},{"ruleId":"1055","severity":2,"message":"1082","line":1006,"column":34,"nodeType":"1053","messageId":"1057","endLine":1006,"endColumn":53},{"ruleId":"1055","severity":2,"message":"1071","line":1006,"column":55,"nodeType":"1053","messageId":"1057","endLine":1006,"endColumn":74},{"ruleId":"1055","severity":2,"message":"1069","line":1016,"column":9,"nodeType":"1053","messageId":"1057","endLine":1016,"endColumn":15},{"ruleId":"1055","severity":2,"message":"1070","line":1016,"column":17,"nodeType":"1053","messageId":"1057","endLine":1016,"endColumn":41},{"ruleId":"1055","severity":2,"message":"1071","line":1016,"column":43,"nodeType":"1053","messageId":"1057","endLine":1016,"endColumn":62},{"ruleId":null,"fatal":true,"severity":2,"message":"1084","line":1141,"column":11,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1085","line":424,"column":19,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1086","line":122,"column":42,"nodeType":null},{"ruleId":null,"fatal":true,"severity":2,"message":"1087","line":809,"column":9,"nodeType":null},{"ruleId":"1051","severity":2,"message":"1068","line":3,"column":18,"nodeType":"1053","messageId":"1054","endLine":3,"endColumn":25},{"ruleId":"1055","severity":2,"message":"1088","line":4,"column":8,"nodeType":"1053","messageId":"1057","endLine":4,"endColumn":15},{"ruleId":"1051","severity":2,"message":"1068","line":4,"column":19,"nodeType":"1053","messageId":"1054","endLine":4,"endColumn":26},{"ruleId":"1051","severity":2,"message":"1052","line":6,"column":1,"nodeType":"1053","messageId":"1054","endLine":6,"endColumn":7},{"ruleId":"1051","severity":2,"message":"1068","line":29,"column":21,"nodeType":"1053","messageId":"1054","endLine":29,"endColumn":28},{"ruleId":"1051","severity":2,"message":"1052","line":3,"column":1,"nodeType":"1053","messageId":"1054","endLine":3,"endColumn":7},{"ruleId":"1051","severity":2,"message":"1089","line":13,"column":9,"nodeType":"1053","messageId":"1054","endLine":13,"endColumn":16},{"ruleId":"1051","severity":2,"message":"1052","line":1,"column":1,"nodeType":"1053","messageId":"1054","endLine":1,"endColumn":7},{"ruleId":null,"fatal":true,"severity":2,"message":"1086","line":9,"column":28,"nodeType":null},"no-undef","'module' is not defined.","Identifier","undef","no-unused-vars","'modelName' is defined but never used.","unusedVar","'id' is defined but never used.","'snapshot' is defined but never used.","'requestType' is defined but never used.","'query' is defined but never used.","Parsing error: Unexpected token =","Parsing error: Unexpected character '@'","'Set' is not defined.","'included' is defined but never used.","'options' is defined but never used.","'__ember_auto_import__' is assigned a value but never used.","'require' is not defined.","'module' is defined but never used.","'__unused_webpack_exports' is defined but never used.","'__webpack_require__' is defined but never used.","'exports' is defined but never used.","no-redeclare","'i' is already defined.","redeclared","'chunkIds' is already defined.","'fn' is already defined.","'priority' is already defined.","'Symbol' is not defined.","'globalThis' is not defined.","'__unused_webpack_module' is defined but never used.","'__webpack_exports__' is defined but never used.","'__unused_webpack___webpack_module__' is defined but never used.","Parsing error: Unexpected token saveFields","Parsing error: Unexpected token .","Parsing error: Unexpected token function","Parsing error: Unexpected token ...","'resolve' is assigned a value but never used.","'process' is not defined."] \ No newline at end of file diff --git a/formulaic/static/admin/formulaic/ember-formulaic/.nvmrc b/formulaic/static/admin/formulaic/ember-formulaic/.nvmrc deleted file mode 100644 index 758bb9c..0000000 --- a/formulaic/static/admin/formulaic/ember-formulaic/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -7.10.0 diff --git a/formulaic/static/admin/formulaic/ember-formulaic/.travis.yml b/formulaic/static/admin/formulaic/ember-formulaic/.travis.yml deleted file mode 100644 index 640f5e5..0000000 --- a/formulaic/static/admin/formulaic/ember-formulaic/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ ---- -language: node_js -node_js: - - "6" - -sudo: false - -cache: - directories: - - $HOME/.npm - - $HOME/.cache # includes bowers cache - -before_install: - - npm config set spin false - - npm install -g bower phantomjs-prebuilt - - bower --version - - phantomjs --version - -install: - - npm install - - bower install - -script: - - npm test diff --git a/formulaic/static/admin/formulaic/ember-formulaic/README.md b/formulaic/static/admin/formulaic/ember-formulaic/README.md index e82ba20..cf2c237 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/README.md +++ b/formulaic/static/admin/formulaic/ember-formulaic/README.md @@ -7,51 +7,43 @@ A short introduction of this app could easily go here. You will need the following things properly installed on your computer. -* [Git](https://git-scm.com/) -* [nvm](https://github.com/creationix/nvm) -* [Node.js](https://nodejs.org/) (with NPM) -* [Bower](https://bower.io/) -* [Ember CLI](https://ember-cli.com/) -* [PhantomJS](http://phantomjs.org/) - TK: for testing +- [Git](https://git-scm.com/) +- [Node.js](https://nodejs.org/) (with nvm) +- [Ember CLI](https://cli.emberjs.com/release/) +- [Google Chrome](https://google.com/chrome/) ## Installation +Install nvm +- `curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash` -* `nvm use` -* `npm install` -* `bower install` +(Install node v20 using nvm) +- `nvm install 20` +- `git clone ` this repository +- `cd django-formulaic/formulaic/static/admin/formulaic/ember-formulaic` +- `npm install` +- `ember g ember-cli-sass` ## Running / Development -* `nvm use` -* `ember serve` +- `npm run start` +- Visit your app at [http://localhost:4200](http://localhost:4200). +- Visit your tests at [http://localhost:4200/tests](http://localhost:4200/tests). ### Code Generators Make use of the many generators for code, try `ember help generate` for more details -### Running Tests - TK +### Running Tests -* `ember test` -* `ember test --server` +- `npm run test` +- `npm run test:ember -- --server` -### Building - TK: I generally don't differentiate the build created by `ember serve` from `ember build` +### Linting -* `ember build` (development) -* `ember build --environment production` (production) +- `npm run lint` +- `npm run lint:fix` -### Deploying +### Building +- `npm run build` (production) -Most JavaScript changes can be deployed without any special effort. The templates point -to `/dist/` already. However, if you make a configuration change -(e.g. `config/environment.js`) or anything else that requires a new commit of -`app/index.html`, you may need to update the Django template -(`/templates/admin/formulaic/form/index.html`) with the change. -## Further Reading / Useful Links - -* [GEMG Wiki Entry on Dep Management](https://github.com/Govexec/ge-govexec/wiki/JavaScript-Dependency-Management) -* [ember.js](http://emberjs.com/) -* [ember-cli](https://ember-cli.com/) -* Development Browser Extensions - * [ember inspector for chrome](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi) - * [ember inspector for firefox](https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/) diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/adapters/application.js b/formulaic/static/admin/formulaic/ember-formulaic/app/adapters/application.js index 0ffb87d..46a2104 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/adapters/application.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/adapters/application.js @@ -1,30 +1,49 @@ -import Ember from 'ember'; -import DRFAdapter from './drf'; - -export default DRFAdapter.extend({ - buildURL: function(type, id, snapshot, requestType) { - /** - * Overriding `buildURL` to keep data fresh. Without this, - * I was getting old data on refresh. - */ - - var url = this._super(type, id, snapshot, requestType); - - // TODO: replace this with a global constant that gets changed every time cache should be invalidated? - var cacheBreaker = 'cacheBreaker=' + Math.round(new Date().getTime() / 1000); - cacheBreaker = ((url.indexOf('?') > -1) ? '&' : '?') + cacheBreaker; - - return url + cacheBreaker; - }, - - headers: Ember.computed(function() { - /** - * Adding CSRF header to protect against cross-domain - * forgery attacks. - */ - - return { - "X-CSRFToken": this.cookie.getCookie('csrftoken') - }; - }).volatile() -}); +import RESTAdapter from '@ember-data/adapter/rest'; + + +export default class ApplicationAdapter extends RESTAdapter { + + get host() { + + return ""; + } + + get namespace() { + return "formulaic/api"; + } + + buildURL(modelName, id, snapshot, requestType, query) { + let url = super.buildURL(...arguments); + + // Add cache breaker (if needed) + let cacheBreaker = 'cacheBreaker=' + Math.round(new Date().getTime() / 1000); + cacheBreaker = ((url.indexOf('?') > -1) ? '&' : '?') + cacheBreaker; + + return url + "/" + cacheBreaker; + } + + get headers() { + let csrfToken = this.getCsrfTokenFromCookies(); + return { + 'X-CSRFToken': csrfToken, + 'Accept': 'application/json, text/javascript, */*; q=0.01', + }; + } + + getCsrfTokenFromCookies() { + let csrfToken = null; + const cookies = document.cookie.split(';'); + for (let cookie of cookies) { + const [name, value] = cookie.trim().split('='); + if (name === 'csrftoken') { + csrfToken = value; + break; + } + } + return csrfToken; + } + + handleResponse(status, headers, payload, requestData) { + return super.handleResponse(status, headers, payload, requestData); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/app.js b/formulaic/static/admin/formulaic/ember-formulaic/app/app.js index 3a41392..7d83e06 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/app.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/app.js @@ -1,19 +1,13 @@ -import Ember from 'ember'; +import Application from '@ember/application'; import Resolver from './resolver'; import loadInitializers from 'ember-load-initializers'; -import config from './config/environment'; +import config from 'ember-formulaic/config/environment'; -let App; - -Ember.MODEL_FACTORY_INJECTIONS = true; - -App = Ember.Application.extend({ - modulePrefix: config.modulePrefix, - podModulePrefix: config.podModulePrefix, - rootElement: "#formulaic-container", - Resolver -}); +export default class App extends Application { + modulePrefix = config.modulePrefix; + podModulePrefix = config.podModulePrefix; + rootElement= "#formulaic-container"; + Resolver = Resolver; +} loadInitializers(App, config.modulePrefix); - -export default App; diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/base-sortable.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/base-sortable.js index 4cd03b2..1714da0 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/components/base-sortable.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/base-sortable.js @@ -1,43 +1,80 @@ -import Ember from 'ember'; - -export default Ember.Component.extend({ - templateName: 'sortable', - sortableSelector: '.sortable', - - didInsertElement: function() { - let thisView = this; - - this.sortable = this.$(this.sortableSelector).sortable({ - update: function() { - thisView.updateSortable(this); - }, - containment: 'parent', - tolerance: 'pointer', - cursor: 'move' - }); - - // Listen to controller - // this.get('controller').on('orderInvalidated', this, this.updateSortable); - }, - updateSortable: function() { - let $ = Ember.$; - - this.sortable.find('.item').each(function(index) { - let positionElement = $(this).find('.position'); - positionElement.val(index); - positionElement.trigger('change'); - }); - - this.sortable.sortable("refresh"); - }, - willDestroy: function() { - // Un-register listener - // this.get('controller').off('orderInvalidated', this, this.updateSortable); - }, - actions: { - triggerUpdateSortable: function() { - this.updateSortable(); - } - } -}); +// components/base-sortable.js +import Component from '@glimmer/component'; +import {inject as service} from '@ember/service'; +import {tracked} from '@glimmer/tracking'; +import {action} from "@ember/object"; +export default class BaseSortableComponent extends Component { + + @service store; + @service('field-service') fieldService; + + @tracked items = this.fieldService.currentFormRules; + @tracked formFields = this.fieldService.currentFormFields; + + @tracked draggedItem = null; + @tracked draggedIndex = null; + @tracked placeholderIndex = null; + + @action + dragStart(index, event) { + this.draggedItem = this.items[index]; + this.draggedIndex = index; + this.placeholderIndex = index; + } + + + @action + dragOver(event) { + event.preventDefault(); + } + + + @action + dragDrop(index) { + const items = [...this.items]; + const draggedItem = this.draggedItem; + + items.splice(this.draggedIndex, 1); + items.splice(index, 0, draggedItem); + + this.fieldService.currentFormRules = items; + this.items = items; + + this.draggedItem = null; + this.draggedIndex = null; + this.placeholderIndex = null; + } + + + @action + dragStartField(index, event) { + this.draggedItem = this.formFields[index]; + this.draggedIndex = index; + this.placeholderIndex = index; + } + + + @action + dragOverField(event) { + event.preventDefault(); + } + + + @action + dragDropField(index) { + const items = [...this.formFields]; + const draggedItem = this.draggedItem; + + items.splice(this.draggedIndex, 1); + items.splice(index, 0, draggedItem); + + this.fieldService.currentFormFields = items; + this.formFields = items; + + this.draggedItem = null; + this.draggedIndex = null; + this.placeholderIndex = null; + } + +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/form.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form.js new file mode 100644 index 0000000..2883ff8 --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form.js @@ -0,0 +1,9 @@ +//components/form.js + +import Component from '@glimmer/component'; +import { tracked } from '@glimmer/tracking'; + +export default class FormComponent extends Component { + @tracked isEditing = false; + +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields.js new file mode 100644 index 0000000..72a9a1c --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields.js @@ -0,0 +1,132 @@ +//components/form/field.js + +import Component from '@glimmer/component'; +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import {tracked} from '@glimmer/tracking'; +import { A } from '@ember/array'; +import {allSettled} from 'rsvp'; +import slug from '../../utils/slug'; + +export default class FieldsComponent extends Component { + @service store; + @service router; + @service('field-service') fieldService; + + @tracked model = A(this.fieldService.currentFormFields); + @tracked currentField = this.fieldService.currentField; + @tracked saveActive = false; + @tracked saveContinueActive = false; + @tracked fieldsPendingDeletion = []; + @tracked validators = {}; + + get activeFields() { + return this.model.filter(item => !item.isDeleted); + } + + get controlsDisabled() { + return this.saveActive || this.saveContinueActive; + } + + @action + invalidateOrder() { + if (!this.controlsDisabled) { + this.orderInvalidated(); + } + } + + orderInvalidated() { + // Custom event handler logic + } + + @action + async saveFields(continueEditing) { + this.saveActive = !continueEditing; + this.saveContinueActive = continueEditing; + + let validationErrors = []; + let actualFields = this.model.filter(field => !field.isDeleted).map((field, index) => { + + let actualField = field.get(field.model_class); + actualField.position = index; + + if (!actualField.slug) { + actualField.slug = slug.generateSlug(actualField.data_name); + } + + let validator = this.fieldService.validatorFor(actualField); + + if (validator.isInvalid) { + validationErrors.push(`Field "${actualField.display_name}" is incomplete`); + } + + return actualField; + }); + + if (validationErrors.length > 0) { + toastr.options.positionClass = "toast-top-center"; + toastr.warning(`Unable to save because of these issues:
${validationErrors.join('
')}`); + this.saveActive = false; + this.saveContinueActive = false; + return; + } + + let promises = [ + ...this.fieldsPendingDeletion.map(field => { + field.deleteRecord(); + return field.save(); + }), + ...actualFields.map(field => field.save()) + ]; + + this.fieldsPendingDeletion.length = 0; + + try { + let results = await allSettled(promises); + let saveErrors = results.filter(result => result.state === "rejected"); + + this.saveActive = false; + this.saveContinueActive = false; + + if (saveErrors.length > 0) { + toastr.options.positionClass = "toast-top-center"; + toastr.error('Save failed. Contact administrator.'); + } else { + toastr.options.positionClass = "toast-top-center"; + this.fieldService.refreshCurrentRoute(this.router.currentRouteName); + toastr.success('Fields saved.'); + if (!continueEditing) { + this.router.transitionTo('form'); + } + } + } catch (error) { + console.error(error); + this.saveActive = false; + this.saveContinueActive = false; + } + } + + @action + close() { + this.router.transitionTo('form'); + } + + @action + editField(field) { + + this.fieldService.openEditField(this, field); + } + + @action + deleteField(field, completeField) { + + this.fieldService.removeValidatorFor(completeField); + this.fieldsPendingDeletion.push(completeField); + + if (this.fieldService.currentField === completeField) { + this.fieldService.closeEditField(this); + } + + field.deleteRecord(); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/basefield.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/basefield.js new file mode 100644 index 0000000..96b8187 --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/basefield.js @@ -0,0 +1,82 @@ +//components/form/fields/basefield.js + +import Component from '@glimmer/component'; +import {inject as service} from '@ember/service'; +import {tracked} from '@glimmer/tracking'; +import {action} from '@ember/object'; +import slug from '../../../utils/slug'; + +export default class BaseFieldComponent extends Component { + @service('field-service') fieldService; + + @tracked isDisplayNameWYSIWYGEnabled = false; + + editorOptions = { + height: 120, + force_br_newlines: false, + forced_root_block: '', + menubar: false, + plugins: ['link'], + toolbar: 'bold italic | link' + }; + + constructor() { + super(...arguments); + this.setupModelObserver(); + } + + setupModelObserver() { + if (this.fieldService.currentField) { + this.isDisplayNameWYSIWYGEnabled = this.displayNameHasHtml; + } + } + + get displayNameHasHtml() { + return ( + this.fieldService.currentField.display_name && + this.fieldService.currentField.display_name.match(/<([A-Z][A-Z0-9]*)\b[^>]*>/i) + ); + } + + get subtypeName() { + return this.fieldService.currentField.subtype.replace('_', ' '); + } + + get autoSlug() { + + if(this.fieldService.currentField.model_class === this.fieldService.fieldTypes().HIDDENFIELD) + { + this.fieldService.currentField.display_name = this.fieldService.currentField.data_name; + } + + if (this.fieldService.currentField.slug) + { + return this.fieldService.currentField.slug; + } + return slug.generateSlug(this.fieldService.currentField.data_name); + } + + set autoSlug(value) { + this.fieldService.currentField.slug = value; + return value; + } + + get validator() { + return this.fieldService.validatorFor(this.fieldService.currentField); + } + + @action + toggleDisplayNameWYSIWYG() { + this.isDisplayNameWYSIWYGEnabled = !this.isDisplayNameWYSIWYGEnabled; + } + + @action + updateDisplayName(newValue) { + this.fieldService.currentField.display_name = newValue; + } + + @action + doneEditingField() { + this.fieldService.closeEditField(this); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/booleanfield.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/booleanfield.js new file mode 100644 index 0000000..66d12ac --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/booleanfield.js @@ -0,0 +1,5 @@ +//components/form/fields/boolean.js + +import BaseFieldComponent from './basefield'; + +export default class BooleanFieldComponent extends BaseFieldComponent {} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/choicefield.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/choicefield.js new file mode 100644 index 0000000..459e6b2 --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/choicefield.js @@ -0,0 +1,114 @@ +//components/form/fields/choicefield.js + +import {action} from '@ember/object'; +import {tracked} from '@glimmer/tracking'; +import {inject as service} from '@ember/service'; +import {once} from '@ember/runloop'; +import BaseFieldComponent from './basefield'; + +export default class ChoiceFieldComponent extends BaseFieldComponent { + @service store; + @service('field-service') fieldService; + + @tracked optionlists = null; + @tracked optiongroups = null; + + constructor() { + super(...arguments); + once(this, this.loadOptionLists); + once(this, this.loadOptionGroups); + } + + async loadOptionLists() { + try { + let option_lists = await this.store.query('optionlist', {}); + this.optionlists = option_lists.toArray(); + } catch (error) { + console.error('Error loading option lists:', error); + } + } + + async loadOptionGroups() { + if (this.fieldService.currentField.option_list) { + try { + let option_groups = await this.store.query('optiongroup', { + list: this.fieldService.currentField.option_list.id + }); + this.optiongroups = option_groups.toArray(); + } catch (error) { + console.error('Error loading option groups:', error); + } + } + } + + get hasOptionGroups() { + return this.optiongroups && this.optiongroups.length > 0; + } + + get modelOptions() { + if (this.hasOptionGroups && this.fieldService.currentField.option_group?.options) { + return this.fieldService.currentField.option_group.options; + } else if (this.fieldService.currentField.option_list?.options) { + return this.fieldService.currentField.option_list.options + } + return null; + } + + get defaultOption() { + if (this.fieldService.currentField.default_options.length > 0) { + return this.fieldService.currentField.default_options.firstObject; + } else { + return this.fieldService.currentField.default_option; + } + } + + get defaultOptionList() { + return this.fieldService.currentField.default_options; + } + + get optiongroupsReady() { + return this.optiongroups != null; //&& this.fieldService.currentField.option_group?.isFulfilled; + } + + get optionlistsReady() { + return this.optionlists != null; + } + + async optionsReady() { + return this.modelOptions != null; //&& this.fieldService.currentField.default_options?.isFulfilled; + } + + get supportsMultiValue() { + return ["checkbox_select_multiple", "select_multiple"].includes(this.fieldService.currentField.subtype); + } + + @action + async optionListChanged(event) { + + const selectedOptionListId = event.target.value; + + if (this.fieldService.currentField.option_list?.id !== selectedOptionListId) { + this.fieldService.currentField.option_list = await this.store.peekRecord('optionlist', selectedOptionListId); + this.modelOptions; + await this.loadOptionGroups(); + } + } + + @action + async optionGroupChanged(event) { + const selectedOptionGroupId = event.target.value; + + if (selectedOptionGroupId) { + this.fieldService.currentField.option_group = await this.store.peekRecord('optiongroup', selectedOptionGroupId); + } + } + + @action + async defaultOptionChanged(event) { + const selectedDefaultOptionId = event.target.value; + + if (selectedDefaultOptionId) { + this.fieldService.currentField.default_option = await this.store.findRecord('option', selectedDefaultOptionId); + } + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/hiddenfield.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/hiddenfield.js new file mode 100644 index 0000000..db9b8ea --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/hiddenfield.js @@ -0,0 +1,7 @@ +//components/form/fields/hiddenfield.js + +import BaseFieldComponent from './basefield'; + +export default class HiddenFieldComponent extends BaseFieldComponent { + +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/index.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/index.js new file mode 100644 index 0000000..8c23acc --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/index.js @@ -0,0 +1,40 @@ +import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import { inject as service } from '@ember/service'; +import {tracked} from "@glimmer/tracking"; + +export default class IndexFieldsComponent extends Component { + @service router; + @service store; + @service('field-service') fieldService; + + @action + createTextField(subtype) { + let field = this.fieldService.createField(subtype, 'text'); + this.fieldService.openEditField(this, field); + } + + @action + createChoiceField(subtype) { + let field = this.fieldService.createField(subtype, 'choice'); + this.fieldService.openEditField(this, field); + } + + @action + createBooleanField(subtype) { + let field = this.fieldService.createField(subtype, 'boolean'); + this.fieldService.openEditField(this, field); + } + + @action + createHiddenField(subtype) { + let field = this.fieldService.createField(subtype, 'hidden'); + this.fieldService.openEditField(this, field); + } + + @action + reloadFields() { + this.store.unloadAll('field'); + this.refresh(); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/textfield.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/textfield.js new file mode 100644 index 0000000..a6722a6 --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/fields/textfield.js @@ -0,0 +1,8 @@ +//components/form/fields/textfield.js + +import BaseFieldComponent from './basefield'; + +export default class TextfieldComponent extends BaseFieldComponent { + +} + diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/index.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/index.js new file mode 100644 index 0000000..76b3f64 --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/index.js @@ -0,0 +1,113 @@ +//components/form/index.js + +import Component from '@glimmer/component'; +import {inject as service} from '@ember/service'; +import {action} from '@ember/object'; +import {tracked} from '@glimmer/tracking'; +import { once } from '@ember/runloop'; + +export default class FormIndexComponent extends Component { + @service store; + @service toast; + @service router; + + @tracked inEditMode = false; + @tracked saveActive = false; + @tracked downloadInProgress = false; + @tracked downloadFailed = false; + @tracked privacyPolicies = null; + @tracked model = this.args.model; + + constructor() { + super(...arguments); + once(this, this.loadPrivacyPolicies); + } + + get form() { + return this.model; + } + + get formId() { + return this.model.id; + } + + get privacyPoliciesReady() { + return Array.isArray(this.privacyPolicies); + } + + eq(a, b) { + return a === b; + } + + @action + async loadPrivacyPolicies() { + try { + let policies = await this.store.query('privacypolicy', {}); + this.privacyPolicies = policies.toArray(); + } catch (error) { + console.error('Error loading privacy policies:', error); + } + } + + @action + privacyPolicyChanged(event) { + let selectedPolicyId = event.target.value; + this.model.privacy_policy = this.privacyPolicies.find(policy => policy.id === selectedPolicyId); + } + + @action + editForm() { + this.inEditMode = true; + } + + @action + async saveForm() { + this.saveActive = true; + + try { + await this.model.save(); + this.saveActive = false; + this.toast.success('Form saved.'); + this.inEditMode = false; + } catch (error) { + console.error(error); + this.saveActive = false; + } + } + + @action + close() { + this.inEditMode = false; + } + + @action + editFields() { + this.router.transitionTo('form.fields'); + } + + @action + editRules() { + this.router.transitionTo('form.rules'); + } + + @action + viewSubmissions() { + this.router.transitionTo('form.submissions'); + } + + @action + downloadSubmissions() { + const formElement = document.getElementById(`ld-submissions-dl-${this.formId}`); + + if (!formElement) return; + + this.downloadInProgress = true; + this.downloadFailed = false; + + formElement.addEventListener('handl:form-unlocked', () => { + this.downloadInProgress = false; + }); + + formElement.submit(); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/rules.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/rules.js new file mode 100644 index 0000000..1d2a2c8 --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/rules.js @@ -0,0 +1,245 @@ +//components/form/rule.js + +import Component from '@glimmer/component'; +import {tracked} from '@glimmer/tracking'; +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import {A} from '@ember/array'; +import {allSettled} from 'rsvp'; +import validatorFactory from '../../validators/factories'; + +export default class RulesComponent extends Component { + @service store; + @service router; + @service('field-service') fieldService; + + @tracked ruleModel = this.fieldService.currentFormRules; + + @tracked rulesPendingDeletion = []; + @tracked conditionsPendingDeletion = []; + @tracked resultsPendingDeletion = []; + @tracked saveActive = false; + @tracked saveContinueActive = false; + @tracked validators = {}; + + get activeRules() { + return this.ruleModel.filter(item => !item.isDeleted); + } + + get controlsDisabled() { + return this.saveActive || this.saveContinueActive; + } + + validatorFor(obj) { + let validatorKey = obj.toString(); + let validators = this.validators; + + if (!(validatorKey in validators)) { + validators[validatorKey] = validatorFactory.createRuleValidator(obj, this); + } + + return validators[validatorKey]; + } + + removeValidatorFor(obj) { + let validatorKey = obj.toString(); + let validators = this.validators; + + if (validatorKey in validators) { + validators[validatorKey].destroy(); + delete validators[validatorKey]; + } + } + + _createCondition(rule) { + + const lastCondition = rule.conditions.lastObject; + const nextPosition = (lastCondition?.position + 1) || rule.conditions.length; + + let condition = this.store.createRecord('rulecondition', { + position: nextPosition, + rule: rule, + field: null, + operator: null + }); + rule.conditions.pushObject(condition); + + return condition; + } + + _createResult(rule) { + let result = this.store.createRecord('ruleresult', { + action: null, + field: null, + rule: rule + }); + rule.results.pushObject(result); + + return result; + } + + @action + invalidateOrder() { + if (!this.controlsDisabled) { + this.orderInvalidated(); + } + } + + orderInvalidated() { + // Custom event handler logic + } + + @action + addRule() { + + const lastRule = this.ruleModel.lastObject; + const nextPosition = (lastRule?.position + 1) || this.ruleModel.length; + + + let rule = this.store.createRecord('rule', { + form: this.fieldService.currentForm, + operator: 'and', + position: nextPosition + }); + + this._createCondition(rule); + this._createResult(rule); + + this.ruleModel.pushObject(rule); + } + + @action + deleteRule(rule) { + this.removeValidatorFor(rule); + rule.deleteRecord(); + this.rulesPendingDeletion.push(rule); + } + + @action + addCondition(rule) { + this._createCondition(rule); + } + + @action + deleteCondition(condition) { + this.removeValidatorFor(condition); + condition.deleteRecord(); + this.conditionsPendingDeletion.push(condition); + } + + @action + addResult(rule) { + this._createResult(rule); + } + + @action + deleteResult(result) { + this.removeValidatorFor(result); + result.deleteRecord(); + this.resultsPendingDeletion.push(result); + } + + @action + async saveRules(continueEditing) { + let promises = []; + const thisComponent = this; + + // Set loading/saving state + if (continueEditing) { + this.saveContinueActive = true; + } else { + this.saveActive = true; + } + + // Validate data + const validationErrors = []; + const rules = this.ruleModel; + for (let rule of rules) { + const validator = this.validatorFor(rule); + + if (validator.isInvalidWithChildren) { + validationErrors.push(`Rule ${rule.position} is incomplete`); + } + } + + if (validationErrors.length > 0) { + + // Cancel 'Save'; output error messages + toastr.options.positionClass = "toast-top-center"; + toastr.warning(`Unable to save because of these issues:
${validationErrors.join('
')}`); + + // Reset loading/saving state + thisComponent.saveContinueActive = false; + thisComponent.saveActive = false; + } else { + // Delete rules marked for deletion + + for (let deletedRule of this.rulesPendingDeletion) { + deletedRule.deleteRecord(); + promises.push(deletedRule.save()); + } + + for (let deletedCondition of this.conditionsPendingDeletion) { + deletedCondition.deleteRecord(); + promises.push(deletedCondition.save()); + } + + for (let deletedResult of this.resultsPendingDeletion) { + deletedResult.deleteRecord(); + promises.push(deletedResult.save()); + } + + console.warn("this.ruleMode : ", this.ruleModel); + + for (let [index,actualRule] of this.ruleModel.entries()) { + if (!actualRule.isDeleted) { + + actualRule.setConditions(actualRule.conditions.toArray()); + actualRule.setResults(actualRule.results.toArray()); + actualRule.setPosition(index); + + promises.push(actualRule.save()); + } + } + + // Handle all save completions together + try { + + const results = await allSettled(promises); + + const saveErrors = results.filter(result => result.state === 'rejected'); + + // Reset loading/saving state + thisComponent.saveContinueActive = false; + thisComponent.saveActive = false; + + if (saveErrors.length > 0) { + // Notify user of failure + console.warn("validationErrors : ", saveErrors); + toastr.options.positionClass = "toast-top-center"; + toastr.error('Save failed. Contact administrator.'); + } else { + this.store.unloadAll('rulecondition'); + this.store.unloadAll('ruleresult'); + this.fieldService.refreshCurrentRoute(this.router.currentRouteName); + toastr.options.positionClass = "toast-top-center"; + toastr.success('Rules saved.'); + + // Redirect to form page if appropriate + if (!continueEditing) { + this.router.transitionTo('form'); + } + } + } catch (error) { + console.error(error); + } + } + } + + @action + closeRules() { + this.router.transitionTo('form'); + } +} + + diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/submissions.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/submissions.js new file mode 100644 index 0000000..b7e364f --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/form/submissions.js @@ -0,0 +1,134 @@ +//controllers/form/submissions.js + +import Controller from '@ember/controller'; +import { tracked } from '@glimmer/tracking'; +import { action } from '@ember/object'; +import { inject as service } from '@ember/service'; + +export default class SubmissionsController extends Controller { + @service store; + @service router; // Injecting the router service + + queryParams = ['page', 'source']; + @tracked formId = null; + @tracked source = null; + @tracked page = 1; + + get fields() { + try { + return this.store.query('field', { form: this.formId }); + } catch (error) { + console.error('Error fetching fields:', error); + throw error; + } + } + + get columnHeaders() { + let headers = ['Date/Time', 'Source', 'Promo Source']; + + if (this.fields.isFulfilled) { + this.fields.forEach(field => { + headers.push(field.data_name); + }); + } + + return headers; + } + + get customColumnSlugs() { + let slugs = []; + + if (this.fields.isFulfilled) { + this.fields.forEach(field => { + slugs.push(field.slug); + }); + } + + return slugs; + } + + get submissionDataList() { + let rows = []; + let slugs = this.customColumnSlugs; + + let submissions = this.model; + + submissions.forEach(submission => { + let row = [ + submission.date_created, + submission.source, + submission.promo_source + ]; + slugs.forEach(slug => { + row.push(submission.custom_data[slug]); + }); + rows.push(row); + }); + + return rows; + } + + get hasSubmissions() { + return this.submissionDataList.length > 0; + } + + get metaData() { + return this.model.meta; + } + + get count() { + return this.metaData ? this.metaData.count : null; + } + + get currentPage() { + return this.page || 1; + } + + get nextPage() { + return this.metaData ? this.metaData.next : null; + } + + get previousPage() { + let previousPage = this.page - 1; + return previousPage > 0 ? previousPage : null; + } + + get pageCount() { + return Math.ceil(this.count / this.page_size); + } + + get sources() { + try { + return this.store.query('submissionsource', { form: this.formId }); + } catch (error) { + console.error('Error fetching sources:', error); + throw error; + } + } + + get selectedSource() { + return this.source; + } + + @action + changeSource(value) { + this.source = value; + } + + @action + gotoPreviousPage() { + if (this.page > 1) { + this.page -= 1; + } + } + + @action + gotoNextPage() { + this.page += 1; + } + + @action + closeSubmissions() { + this.router.transitionTo('form'); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-checkbox-select-multiple.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-checkbox-select-multiple.js index 926b613..43c0164 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-checkbox-select-multiple.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-checkbox-select-multiple.js @@ -1,4 +1,4 @@ -import Ember from 'ember'; +import Component from '@glimmer/component'; -export default Ember.Component.extend({ -}); +export default class PreviewCheckboxSelectMultipleComponent extends Component { +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-checkbox.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-checkbox.js index 926b613..bc2162a 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-checkbox.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-checkbox.js @@ -1,4 +1,4 @@ -import Ember from 'ember'; +import Component from '@glimmer/component'; -export default Ember.Component.extend({ -}); +export default class PreviewCheckboxComponent extends Component { +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-email.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-email.js index 926b613..6da52a6 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-email.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-email.js @@ -1,4 +1,4 @@ -import Ember from 'ember'; +import Component from '@glimmer/component'; -export default Ember.Component.extend({ -}); +export default class PreviewEmailComponent extends Component { +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-full-name.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-full-name.js index 926b613..00cfabb 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-full-name.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-full-name.js @@ -1,4 +1,4 @@ -import Ember from 'ember'; +import Component from '@glimmer/component'; -export default Ember.Component.extend({ -}); +export default class PreviewFullNameComponent extends Component { +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-hidden.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-hidden.js index 926b613..1fc349f 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-hidden.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-hidden.js @@ -1,4 +1,15 @@ -import Ember from 'ember'; +import Component from '@glimmer/component'; +import { tracked } from '@glimmer/tracking'; -export default Ember.Component.extend({ -}); +export default class PreviewHiddenComponent extends Component { + @tracked field; + @tracked disabled; + + get placeholderValue() { + return this.field?.completeField?.value || ''; + } + + get isDisabled() { + return this.disabled ?? false; + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-integer.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-integer.js index 926b613..c4a233d 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-integer.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-integer.js @@ -1,4 +1,4 @@ -import Ember from 'ember'; +import Component from '@glimmer/component'; -export default Ember.Component.extend({ -}); +export default class PreviewIntegerComponent extends Component { +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-phone-number.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-phone-number.js index 926b613..c79f408 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-phone-number.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-phone-number.js @@ -1,4 +1,4 @@ -import Ember from 'ember'; +import Component from '@glimmer/component'; -export default Ember.Component.extend({ -}); +export default class PreviewPhoneNumberComponent extends Component { +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-radio-select.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-radio-select.js index 926b613..2a9a5d9 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-radio-select.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-radio-select.js @@ -1,4 +1,16 @@ -import Ember from 'ember'; +import Component from '@glimmer/component'; +import { tracked } from '@glimmer/tracking'; -export default Ember.Component.extend({ -}); +export default class PreviewRadioSelectComponent extends Component { + @tracked field; + + get defaultRadioLabel() { + if (this.field?.completeField?.default_option) { + return this.field.completeField.default_option.name; + } else if (this.field?.completeField?.default_text) { + return this.field.completeField.default_text; + } else { + return 'Lorem ipsum dolor sit amet, leo in, in vivamus.'; + } + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-select-multiple.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-select-multiple.js index 926b613..51ec000 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-select-multiple.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-select-multiple.js @@ -1,4 +1,4 @@ -import Ember from 'ember'; +import Component from '@glimmer/component'; -export default Ember.Component.extend({ -}); +export default class PreviewSelectMultipleComponent extends Component { +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-select.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-select.js index 926b613..487ac48 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-select.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-select.js @@ -1,4 +1,16 @@ -import Ember from 'ember'; +import Component from '@glimmer/component'; +import { tracked } from '@glimmer/tracking'; -export default Ember.Component.extend({ -}); +export default class PreviewSelectComponent extends Component { + @tracked field; + + get defaultOption() { + if (this.field?.completeField?.default_option) { + return this.field.completeField.default_option.name; + } else if (this.field?.completeField?.default_text) { + return this.field.completeField.default_text; + } else { + return '(Choose One)'; + } + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-text.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-text.js index 926b613..f3ea184 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-text.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-text.js @@ -1,4 +1,4 @@ -import Ember from 'ember'; +import Component from '@glimmer/component'; -export default Ember.Component.extend({ -}); +export default class PreviewTextComponent extends Component { +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-textarea.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-textarea.js index 926b613..70913e5 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-textarea.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/preview-textarea.js @@ -1,4 +1,4 @@ -import Ember from 'ember'; +import Component from '@glimmer/component'; -export default Ember.Component.extend({ -}); +export default class PreviewTextareaComponent extends Component { +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/rule-condition.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/rule-condition.js index 1a254fd..a2fc3a3 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/components/rule-condition.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/rule-condition.js @@ -1,127 +1,114 @@ -import Ember from 'ember'; - -var FIELD_TYPE_TEXTFIELD = 'textfield'; -var FIELD_TYPE_CHOICEFIELD = 'choicefield'; -var FIELD_TYPE_BOOLEANFIELD = 'booleanfield'; - -export default Ember.Component.extend({ - store: Ember.inject.service(), - - tagName: 'li', - - _previousFieldType: null, - _fieldTypeInitialized: false, - allOperators: [ - { value: "is", name: "is" }, - { value: "is_not", name: "is not" } - //, TODO: cut from initial scope - // { value: "contains", name: "contains" }, - // { value: "does_not_contain", name: "does not contain" }, - // { value: "begins_with", name: "begins with" }, - // { value: "ends_with", name: "ends with" }, - // { value: "greater_than", name: "greater than" }, - // { value: "less_than", name: "less than" }, - // { value: "any_selected", name: "any selected" }, - // { value: "all_selected", name: "all selected" } - ], - - availableOperators: function() { - return this.allOperators; - }.property(), - - fieldType: function() { - let field = this.get('condition.field'); - - if (field.get('isFulfilled')) { - if (field.get('content.textfield')) { - return FIELD_TYPE_TEXTFIELD; - } else if (field.get('content.choicefield')) { - return FIELD_TYPE_CHOICEFIELD; - } else if (field.get('content.booleanfield')) { - return FIELD_TYPE_BOOLEANFIELD; - } else { - return null; - } - } else { - return null; - } - }.property('condition.field.content', 'condition.field.isFulfilled'), - - - allFieldsReady: function() { - // TODO: find another way to look for updates other than length; as is this - // will never be "ready" if there aren't any fields. - return (this.get('allFields').get('length')); - }.property('allFields.length'), - - fieldOptions: function() { - return this.get('condition.field.content.choicefield.option_list.options'); - }.property('condition.field.content'), - - useTextWidget: function() { - return (this.get('fieldType') === FIELD_TYPE_TEXTFIELD); - }.property('fieldType'), - - useSelectWidget: function() { - return (this.get('fieldType') === FIELD_TYPE_CHOICEFIELD); - }.property('fieldType'), - - useNoWidget: function() { - return (this.get('fieldType') === FIELD_TYPE_BOOLEANFIELD); - }.property('fieldType'), - - // selectValue: function(key, value) { - // if (this.get('field.content.choicefield.option_list.isFulfilled')) { - // // setter - // if (typeof value !== 'undefined' && value !== this.get('value')) { - // this.set('value', value); - // } - - // // getter - // return this.get('value'); - // } else { - // return null; - // } - // }.property('fieldOptions', 'field.content.choicefield.option_list.isFulfilled', 'value'), - - selectValue: Ember.computed( - 'fieldOptions', - 'field.content.choicefield.option_list.isFulfilled', - 'value', - { - get() { - return this.get('condition.value'); - } - } - ), - - watchFieldChanges: function() { - if (this.get('field.isFulfilled')) { - if (!this._fieldTypeInitialized) { - // init fieldType - this._previousFieldType = this.get('fieldType'); - this._fieldTypeInitialized = true; - } else { - if (this._previousFieldType !== this.get('fieldType')) { - this._previousFieldType = this.get('fieldType'); - this.set('value', null); - } - } - } - }.observes('fieldType'), - - actions: { - conditionFieldChanged: function(value) { - this.set('condition.field', value); - }, - conditionOperatorChanged: function(value) { - this.set('condition.operator', value); - }, - conditionSelectValueChanged: function(value) { - this.set('condition.value', value); - }, - clickedDeleteCondition: function(condition) { - this.sendAction('onDeleteClick', condition); - } +import Component from '@glimmer/component'; +import {tracked} from '@glimmer/tracking'; +import {inject as service} from '@ember/service'; +import {action, computed} from '@ember/object'; +import {once} from '@ember/runloop'; + +const FIELD_TYPE_TEXTFIELD = 'textfield'; +const FIELD_TYPE_CHOICEFIELD = 'choicefield'; +const FIELD_TYPE_BOOLEANFIELD = 'booleanfield'; + +export default class RuleConditionComponent extends Component { + @service store; + @service('field-service') fieldService; + + @tracked condition = this.args.condition; + @tracked allFields = this.fieldService.currentFormFields; + @tracked value; + _previousFieldType = null; + _fieldTypeInitialized = false; + + allOperators = [ + {value: "is", name: "is"}, + {value: "is_not", name: "is not"} + // Other operators can be added here + ]; + + @computed('allOperators') + get availableOperators() { + return this.allOperators; + } + + @computed('condition.field') + get fieldType() { + const field = this.condition.field; + if (field.content?.textfield) { + return FIELD_TYPE_TEXTFIELD; + } else if (field.content?.choicefield) { + return FIELD_TYPE_CHOICEFIELD; + } else if (field.content?.booleanfield) { + return FIELD_TYPE_BOOLEANFIELD; + } else { + return null; } -}); + } + + @computed('allFields.length') + get allFieldsReady() { + return this.allFields?.length; + } + + get fieldOptions() { + return this.condition.field.content?.choicefield?.option_list?.options.toArray() || []; + } + + @computed('fieldType') + get useTextWidget() { + return this.fieldType === FIELD_TYPE_TEXTFIELD; + } + + @computed('fieldType') + get useSelectWidget() { + return this.fieldType === FIELD_TYPE_CHOICEFIELD; + } + + @computed('fieldType') + get useNoWidget() { + return this.fieldType === FIELD_TYPE_BOOLEANFIELD; + } + + @computed('fieldOptions', 'condition.value') + get selectValue() { + return this.condition.value; + } + + @action + watchFieldChanges() { + if (this.fieldType && !this._fieldTypeInitialized) { + this._previousFieldType = this.fieldType; + this._fieldTypeInitialized = true; + } else if (this._previousFieldType !== this.fieldType) { + this._previousFieldType = this.fieldType; + this.value = null; + } + } + + @action + async conditionFieldChanged(event) { + const selectedOptionId = event.target.value; + + if (this.condition.field.content?.id !== selectedOptionId) { + this.condition.field = await this.store.peekRecord('field', selectedOptionId); + } + } + + @action + async conditionOperatorChanged(event) { + this.condition.operator = event.target.value; + } + + @action + conditionSelectValueChanged(event) { + this.condition.value = event.target.value; + } + + @action + conditionInputValueChanged(event) { + this.condition.value = event.target.value; + } + + @action + clickedDeleteCondition(condition) { + this.args.onDeleteClick(condition); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/rule-result.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/rule-result.js index 10a8ed9..6f1bff1 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/components/rule-result.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/rule-result.js @@ -1,88 +1,88 @@ -import Ember from 'ember'; - -export default Ember.Component.extend({ - store: Ember.inject.service(), - - allActions: [ - { value: 'show', name: 'Show' }, - { value: 'hide', name: 'Hide' }, - { value: 'change-option-group', name: 'Change Option Group'} - // , TODO: cut from initial scope - // { value: "require", name: "Require (Override)" }, - // { value: "optional", name: "Optional (Override)" } - ], - - choiceFieldActions: [ - 'change-option-group' - ], - - availableActions: function() { - return this.allActions; - }.property(), - - availableFields: function() { - // TODO: observing `allFields.length` doesn't handle "no fields" situation - - if (this.get('choiceFieldActions').indexOf(this.get('result.action')) !== -1) { - // Action only applies to Choice Fields - return this.get('allFields').filter(function (field) { - return (field.get('choicefield')); - }); - } else { - // Action applies to any field - return this.get('allFields'); - } - }.property('allFields.length', 'result.action'), - - - allFieldsReady: function() { - return (this.get('allFields.length')); - }.property('allFields.length'), - - showOptionGroups: function() { - if (this.get('result.action') === 'change-option-group') { - if (this.get('result.field.content.choicefield')) { - return true; - } - } - - return false; - }.property( - 'result.action', - 'optionGroups', - 'result.field.content', - 'result.field.content.choicefield.option_list.content', - 'result.field.content.choicefield.option_list.content.groups.content' - ), - - fieldHasOptionGroups: function() { - return (this.get('optionGroups.length') > 0); - }.property('optionGroups'), - - optionGroups: function() { - return this.get('result.field.content.choicefield.option_list.content.groups.content'); - }.property( - 'result.action', - 'result.field.content', - 'result.field.content.choicefield.option_list.content', - 'result.field.content.choicefield.option_list.content.groups.content' - ), - - actions: { - resultActionChanged: function(value) { - this.set('result.action', value); - }, - resultFieldChanged: function(value) { - this.set('result.field', value); - - // Clear option group when affected field changes - this.set('result.option_group', null); - }, - resultOptionGroupChanged: function(value) { - this.set('result.option_group', value); - }, - clickedDeleteResult: function(result) { - this.sendAction('onDeleteClick', result); - } +import Component from '@glimmer/component'; +import {tracked} from '@glimmer/tracking'; +import {inject as service} from '@ember/service'; +import {action, computed} from '@ember/object'; + +export default class RuleResultComponent extends Component { + @service store; + @service('field-service') fieldService; + + @tracked result = this.args.result; + @tracked allFields = this.fieldService.currentFormFields; + + allActions = [ + {value: 'show', name: 'Show'}, + {value: 'hide', name: 'Hide'}, + {value: 'change-option-group', name: 'Change Option Group'} + ]; + + choiceFieldActions = [ + 'change-option-group' + ]; + + @computed('allActions') + get availableActions() { + return this.allActions; + } + + @computed('allFields.length', 'result.action') + get availableFields() { + if (this.choiceFieldActions.includes(this.result.action)) { + return this.allFields.filter(field => field.choicefield); + } else { + return this.allFields; + } + } + + @computed('allFields.length') + get allFieldsReady() { + return this.allFields.length; + } + + + get showOptionGroups() { + return ( + this.result.action === 'change-option-group' && + this.result.field.content?.choicefield + ); + } + + @computed('optionGroups') + get fieldHasOptionGroups() { + return this.optionGroups.length > 0; + } + + @computed('result.field') + get optionGroups() { + return this.result.field.content?.choicefield?.option_list?.groups.toArray() || []; + } + + @action + resultActionChanged(event) { + this.result.action = event.target.value; + } + + @action + async resultFieldChanged(event) { + + const selectedOptionId = event.target.value; + + if (this.result.field?.content?.id !== selectedOptionId) { + this.result.field = await this.store.peekRecord('field', selectedOptionId); } -}); + } + + @action + async resultOptionGroupChanged(event) { + const selectedOptionId = event.target.value; + + if (this.result.option_group?.id !== selectedOptionId) { + this.result.option_group = await this.store.peekRecord('optiongroup', selectedOptionId); + } + } + + @action + clickedDeleteResult(result) { + this.args.onDeleteClick(result); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/sidebar.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/sidebar.js new file mode 100644 index 0000000..2d948e4 --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/sidebar.js @@ -0,0 +1,7 @@ +import Component from '@glimmer/component'; +import {inject as service} from '@ember/service'; + +export default class SidebarComponent extends Component { + + @service('field-service') fieldService; +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-field.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-field.js index af4ccc5..b84e479 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-field.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-field.js @@ -1,88 +1,97 @@ -import Ember from 'ember'; - -export default Ember.Component.extend({ - tagName: 'div', - classNames: [ - 'field-preview', - 'single-line-text', - 'form-group', - 'col-xs-12', - 'item' - ], - classNameBindings: [ - 'isEditing:editing', - 'completeField.validator.isInvalid:warning' - ], - - needs: 'fields', - - previewComponent: function() { - let viewName = 'preview-' + this.get('field.subtype').replace("_", "-"); - return viewName; - }.property(), - - completeField: function() { - let field = this.get('field'); - - if (field.get('textfield')) { - return field.get('textfield'); - } else if (field.get('choicefield')) { - return field.get('choicefield'); - } else if (field.get('booleanfield')) { - return field.get('booleanfield'); - } else if (field.get('hiddenfield')) { - return field.get('hiddenfield'); - } else { - // Raise exception - throw new Error("Field type not implemented"); - } - }.property(), - - invalidateOrder: function () { - this.get('controllers.fields').invalidateOrder(); - }, - - displayNameChanged: Ember.observer('completeField.display_name', function() { - this.set('display_name', this.get('completeField.display_name')); - }), - - dataNameChanged: Ember.observer('completeField.data_name', function() { - this.set('data_name', this.get('completeField.data_name')); - }), - - slugChanged: Ember.observer('completeField.slug', function() { - this.set('slug', this.get('completeField.slug')); - }), - - positionChanged: Ember.observer('field.position', function() { - this.set('completeField.position', this.get('field.position')); - }), - - isEditing: function() { - return (this.get('currentField') === this.get('field')); - }.property('currentField'), - - showDisplayName: function() { - return !(this.get('field.booleanfield')); - }.property('field.booleanfield'), - - click() { - this.sendAction('onClick', this.get('field')); - }, - - destroy: function () { - /** - * Invalidate order after destroy - */ - - this._super(...arguments); - - this.sendAction('onOrderInvalidated'); - }, - - actions: { - clickedDeleteField: function(field, completeField) { - this.sendAction('onDeleteClick', field, completeField); - } +//components/sortable-field.js + +import Component from '@glimmer/component'; +import {tracked} from '@glimmer/tracking'; +import {inject as service} from '@ember/service'; +import {action, computed} from '@ember/object'; + +const FIELD_TYPES = { + TEXTFIELD: 'textfield', + CHOICEFIELD: 'choicefield', + BOOLEANFIELD: 'booleanfield', + HIDDENFIELD: 'hiddenfield' +}; + +export default class SortableFieldComponent extends Component { + + @service('field-service') fieldService; + + @tracked display_name; + @tracked data_name; + @tracked slug; + @tracked field; + + constructor() { + super(...arguments); + this.field = this.args.field; + } + + get previewComponent() { + if (this.field && this.field.subtype) { + return `preview-${this.field.subtype.replace('_', '-')}`; + } else { + return ''; } -}); + } + + get completeField() { + if (!this.field) { + return null; + } + + return this.field.get(this.field.model_class); + } + + @computed('fieldService.currentField.field') + get isEditing() { + return this.fieldService.currentField?.field === this.field; + } + + @computed('field.hiddenfield') + get showDisplayName() { + return this.field.model_class !== FIELD_TYPES.HIDDENFIELD + } + + get isHiddenField() { + return this.field.model_class === FIELD_TYPES.HIDDENFIELD + } + + @action + handleDisplayNameChange() { + this.display_name = this.completeField.display_name; + } + + @action + handleDataNameChange() { + this.data_name = this.completeField.data_name; + + if(this.completeField.model_class === FIELD_TYPES.HIDDENFIELD) + { + this.display_name = this.completeField.data_name; + } + } + + @action + handleSlugChange() { + this.slug = this.completeField.slug; + } + + @action + handlePositionChange() { + this.completeField.position = this.field.position; + } + + @action + handleEditClick(event) { + this.args.onEditClick(this.field); + } + + willDestroy() { + super.willDestroy(...arguments); + } + + @action + clickedDeleteField(field, completeField) { + this.args.onDeleteClick(field, completeField); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-fields.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-fields.js index a782751..5808ae3 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-fields.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-fields.js @@ -1,6 +1,7 @@ -import BaseSortable from "./base-sortable"; +//components/sortable-fields.js -export default BaseSortable.extend({ - templateName: 'sortable/fields', - sortableSelector: '.field-sortable' -}); +import BaseSortableComponent from './base-sortable'; + +export default class SortableFieldsComponent extends BaseSortableComponent { + +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-rule.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-rule.js index 6a3f7fa..296b4b9 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-rule.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-rule.js @@ -1,55 +1,74 @@ -import Ember from "ember"; - -export default Ember.Component.extend({ - store: Ember.inject.service(), - - tagName: 'div', - classNames: [ - 'field-preview', - 'single-line-text', - 'form-group', - 'col-xs-12', - 'item' - ], - classNameBindings: [ - 'rule.validator.isInvalid:warning' - ], - - activeConditions: Ember.computed('rule.conditions.@each.isDeleted', { - get() { - return this.get('rule.conditions').filter(function(item) { - return !item.get('isDeleted'); - }); - } - }), - - activeResults: Ember.computed('rule.results.@each.isDeleted', { - get() { - return this.get('rule.results').filter(function(item) { - return !item.get('isDeleted'); - }); - } - }), - - destroy() { - /** - * Invalidate order after destroy - */ - - this._super(...arguments); - - this.sendAction('onOrderInvalidated'); - }, - - actions: { - clickedDeleteRule: function(rule) { - this.sendAction('onDeleteClick', rule); - }, - clickedAddCondition: function(rule) { - this.sendAction('onAddConditionClick', rule); - }, - clickedAddResult: function(rule) { - this.sendAction('onAddResultClick', rule); - } - } -}); +import Component from '@glimmer/component'; +import { inject as service } from '@ember/service'; +import { tracked } from '@glimmer/tracking'; +import { action, computed } from '@ember/object'; + +export default class SortableRuleComponent extends Component { + @service store; + + tagName = 'div'; + classNames = [ + 'field-preview', + 'single-line-text', + 'form-group', + 'col-xs-12', + 'item' + ]; + + @tracked rule = this.args.rule; + + get classNameBindings() { + return { + 'warning': this.rule.validator.isInvalid + }; + } + + @computed('rule.conditions.@each.isDeleted') + get activeConditions() { + return this.rule.conditions.filter(item => !item.isDeleted); + } + + @computed('rule.results.@each.isDeleted') + get activeResults() { + return this.rule.results.filter(item => !item.isDeleted); + } + + get hasActiveConditions() + { + return this.activeConditions.length > 0 + } + + willDestroy() { + super.willDestroy(...arguments); + } + + @action + clickedDeleteRule(rule) { + this.args.onDeleteRuleClick(rule); + } + + @action + setOperator(operator) { + this.rule.operator = operator; + } + + @action + clickedAddCondition(rule) { + this.args.onAddConditionClick(rule); + } + + @action + deleteCondition(condition) { + this.args.onDeleteConditionClick(condition); + } + + @action + clickedAddResult(rule) { + this.args.onAddResultClick(rule); + } + + @action + deleteResult(result) { + this.args.onDeleteResultClick(result); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-rules.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-rules.js index fb5d782..b0f4a16 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-rules.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/sortable-rules.js @@ -1,12 +1,5 @@ -import BaseSortable from "./base-sortable"; -import Ember from "ember"; +import BaseSortableComponent from './base-sortable'; -export default BaseSortable.extend({ - templateName: 'sortable/rules', - sortableSelector: '.rule-sortable', - store: Ember.inject.service(), +export default class SortableRulesComponent extends BaseSortableComponent { - allFields: function() { - return this.get('store').peekAll('field'); - }.property() -}); +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/components/tinymce-editor.js b/formulaic/static/admin/formulaic/ember-formulaic/app/components/tinymce-editor.js new file mode 100644 index 0000000..c26d2a0 --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/components/tinymce-editor.js @@ -0,0 +1,31 @@ +import Component from '@glimmer/component'; +import { action } from '@ember/object'; + +export default class TinymceEditorComponent extends Component { + editor = null; + + @action + setupEditor(element) { + const options = { + target: element, + ...this.args.options, + setup: (editor) => { + this.editor = editor; + editor.on('Change', () => { + if (this.args.onChange) { + this.args.onChange(editor.getContent()); + } + }); + }, + }; + + tinymce.init(options); + } + + willDestroy() { + super.willDestroy(...arguments); + if (this.editor) { + tinymce.remove(this.editor); // Use tinymce.remove to clean up the editor + } + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/.gitkeep b/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form.js b/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form.js deleted file mode 100644 index 8a2a407..0000000 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form.js +++ /dev/null @@ -1,5 +0,0 @@ -import Ember from 'ember'; - -export default Ember.Controller.extend({ - isEditing: false -}); diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields.js b/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields.js deleted file mode 100644 index 22cf904..0000000 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields.js +++ /dev/null @@ -1,167 +0,0 @@ -/* global toastr */ - -import Ember from 'ember'; -import FieldHelpers from '../../utils/fields'; -import slug from '../../utils/slug'; - -export default Ember.Controller.extend(Ember.Evented, { - sortProperties: ['position'], - saveActive: false, - saveContinueActive: false, - validators: {}, - fieldsPendingDeletion: [], - currentField: null, - - activeFields: Ember.computed('model', 'model.@each.isDeleted', { - get() { - return this.get('model').filter(function(item) { - return !item.get('isDeleted'); - }); - } - }), - - validatorFor: function(field) { - // I moved validators to models (for better or worse) - // TODO: simplify how validators are accessed based on that change - let actualField = FieldHelpers.getActualField(field); - let validatorKey = actualField.toString(); - - let validators = this.get('validators'); - - if (!(validatorKey in validators)) { - validators[validatorKey] = actualField.validator; - } - - return validators[validatorKey]; - }, - - removeValidatorFor: function (field) { - let actualField = FieldHelpers.getActualField(field); - let validatorKey = actualField.toString(); - - let validators = this.get('validators'); - - if (validatorKey in validators) { - validators[validatorKey].destroy(); - delete validators[validatorKey]; - } - }, - - invalidateOrder: function() { - if (!this.get('controlsDisabled')) { - this.trigger('orderInvalidated'); - } - }, - - controlsDisabled: function() { - return (this.saveActive || this.saveContinueActive); - }.property('saveActive', 'saveContinueActive'), - - actions: { - saveFields: function(continueEditing) { - let thisController = this; - let promises = []; - let i; - - // Set loading/saving state - if (continueEditing) { - this.set('saveContinueActive', true); - } else { - this.set('saveActive', true); - } - - // Save current fields - let validationErrors = []; - let actualFields = []; - let fields = this.get('model').toArray(); - for (i = 0; i < fields.length; i++) { - if (!fields[i].get('isDeleted')) { - // fields array contains partials; get full fields - let actualField = FieldHelpers.getActualField(fields[i]); - - // Set slug if not set explicitly - if (!actualField.get('slug')) { - let newSlug = slug.generateSlug(actualField.get('data_name')); - actualField.set('slug', newSlug); - } - - // Validate data - let validator = this.validatorFor(actualField); - if (validator.get('isInvalid')) { - validationErrors.push('Field "' + actualField.get('data_name') + '" is incomplete'); - } - - actualFields.push(actualField); - } - } - - if (validationErrors.length > 0) { - // Cancel 'Save'; output error messages - toastr.options.positionClass = "toast-bottom-center"; - toastr.warning('Unable to save because of these issues:
' + validationErrors.join('
')); - - // Reset loading/saving state - thisController.set('saveContinueActive', false); - thisController.set('saveActive', false); - } else { - // Delete fields marked for deletion - for (i = 0; i < this.fieldsPendingDeletion.length; i++) { - this.fieldsPendingDeletion[i].deleteRecord(); - promises.push(this.fieldsPendingDeletion[i].save()); - } - // Clear array - this.fieldsPendingDeletion.length = 0; - - // Begin save - for (i = 0; i < actualFields.length; i++) { - promises.push(actualFields[i].save()); - } - - // Handle all save completions together - Ember.RSVP.allSettled(promises).then(function (results) { - let saveErrors = []; - for (let i = 0; i < results.length; i++) { - if (results[i].state === "rejected") { - saveErrors.push(results[i]); - } - } - - // Reset loading/saving state - thisController.set('saveContinueActive', false); - thisController.set('saveActive', false); - - if (saveErrors.length > 0) { - // Notify user of success - toastr.options.positionClass = "toast-bottom-center"; - toastr.error('Save failed. Contact administrator.'); - } else { - // Reload fields from store - thisController.send('reloadFields'); - - // Notify user of success - toastr.options.positionClass = "toast-bottom-center"; - toastr.success('Fields saved.'); - - // Redirect to form page if appropriate - if (!continueEditing) { - thisController.transitionToRoute('form'); - } - } - }, function (error) { - Ember.Logger.error(error); - }); - } - }, - - close: function() { - this.transitionToRoute('form'); - }, - - editField: function(field) { - this.send('editFieldToRoute', field); - }, - deleteField: function(field, completeField) { - this.send('deleteFieldToRoute', field, completeField); - } - } -}); diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields/basefield.js b/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields/basefield.js deleted file mode 100644 index ccc4a16..0000000 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields/basefield.js +++ /dev/null @@ -1,64 +0,0 @@ -import Ember from 'ember'; -import slug from '../../../utils/slug'; - -export default Ember.Controller.extend({ - fieldsController: Ember.inject.controller('form.fields'), - - modelChanged: Ember.observer('model', function() { - if (this.get('model')) { - this.set('isDisplayNameWYSIWYGEnabled', this.get('displayNameHasHtml')); - } - }), - - editorOptions: { - height: 120, - force_br_newlines : false, - force_p_newlines : false, - forced_root_block : '', - menubar: false, - plugins: ['link'], - toolbar: 'bold italic | link' - }, - - displayNameHasHtml: Ember.computed('model.display_name', { - get() { - return ( - this.get('model.display_name') && - this.get('model.display_name').match(/<([A-Z][A-Z0-9]*)\b[^>]*>/i) - ); - } - }), - - subtypeName: function () { - return this.get('model.subtype').replace('_', ' '); - }.property('model.subtype'), - - autoSlug: Ember.computed('model.data_name', 'model.slug', { - get() { - // if slug is set, return it - if (this.get('model.slug')) { - return this.get('model.slug'); - } - - // if not, display the generated slug - return slug.generateSlug(this.get('model.data_name')); - }, - set(key, value) { - this.set('model.slug', value); - return value; - } - }), - - validator: function() { - return this.get('fieldsController').validatorFor(this.get('model')); - }.property('fieldsController', 'model'), - - actions: { - toggleDisplayNameWYSIWYG: function() { - this.set( - 'isDisplayNameWYSIWYGEnabled', - !this.get('isDisplayNameWYSIWYGEnabled') - ); - } - } -}); diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields/booleanfield.js b/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields/booleanfield.js deleted file mode 100644 index aac9e11..0000000 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields/booleanfield.js +++ /dev/null @@ -1,3 +0,0 @@ -import BaseField from './basefield'; - -export default BaseField.extend(); diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields/choicefield.js b/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields/choicefield.js deleted file mode 100644 index d9602b7..0000000 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields/choicefield.js +++ /dev/null @@ -1,84 +0,0 @@ -import BaseField from './basefield'; -import Ember from 'ember'; - -export default BaseField.extend({ - optionlists: function() { - return this.store.query('optionlist', {}); - }.property(), - - optiongroups: Ember.computed( - 'model.option_list', - { - get() { - return this.store.query('optiongroup', { - list: this.get('model.option_list.id') - }); - } - } - ), - - hasOptionGroups: function() { - return (this.get('optiongroups.content.length') > 0); - }.property('optiongroups.content.length'), - - options: function() { - if (this.get('model.option_group.content')) { - return this.get('model.option_group.options'); - } else if (this.get('model.option_list.content')) { - return this.get('model.option_list.options'); - } - return null; - }.property('model.option_list', 'model.option_group.id'), - - defaultOption: function() { - // reduces default_options to single value - if (this.get('model.default_options').get('length') > 0) { - return this.get('model.default_options').get('firstObject'); - } else { - return null; - } - }.property('model.default_options'), - - defaultOptionList: function() { - return this.get('model.default_options'); - }.property('model.default_options'), - - optiongroupsReady: function() { - return (this.get('optiongroups.isFulfilled') && this.get('model.option_group.isFulfilled')); - }.property('optiongroups.isFulfilled', 'model.option_group.isFulfilled'), - - optionlistsReady: function() { - return (this.get('optionlists.isFulfilled') && - this.get('model.option_list.isFulfilled') && - this.get('optiongroups.isFulfilled') && - this.get('model.option_group.isFulfilled')); - }.property( - 'optionlists.isFulfilled', - 'model.option_list.isFulfilled', - 'optiongroups.isFulfilled', - 'model.option_group.isFulfilled' - ), - - optionsReady: function() { - return (this.get('options') != null && this.get('model.default_options').get('isFulfilled')); - }.property('options', 'model.default_options.isFulfilled'), - - supportsMultiValue: function() { - return (["checkbox_select_multiple", "select_multiple"].indexOf(this.get('model.subtype')) !== -1); - }.property('model.subtype'), - - actions: { - optionListChanged: function(value) { - if (this.get('model.option_list.content') !== value) { - this.set('model.option_list', value); - } - }, - optionGroupChanged: function(value) { - this.set('model.option_group', value); - }, - defaultOptionChanged: function(value) { - this.set('model.default_option', value); - } - } -}); - diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields/hiddenfield.js b/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields/hiddenfield.js deleted file mode 100644 index 89910b4..0000000 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields/hiddenfield.js +++ /dev/null @@ -1,9 +0,0 @@ -import BaseField from './basefield'; -import Ember from 'ember'; - -export default BaseField.extend({ - dataNameChanged: Ember.observer('model.data_name', function() { - // auto-populate `display_name`; doesn't display anywhere - this.set('model.display_name', this.get('model.data_name')); - }) -}); diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields/index.js b/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields/index.js deleted file mode 100644 index 3e6aeb9..0000000 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import Ember from 'ember'; - -var FieldsController = Ember.Controller.extend(); - -export default FieldsController; diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields/textfield.js b/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields/textfield.js deleted file mode 100644 index aac9e11..0000000 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/fields/textfield.js +++ /dev/null @@ -1,3 +0,0 @@ -import BaseField from './basefield'; - -export default BaseField.extend(); diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/index.js b/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/index.js deleted file mode 100644 index cb4e7c5..0000000 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/index.js +++ /dev/null @@ -1,23 +0,0 @@ -import Ember from 'ember'; - -export default Ember.Controller.extend({ - privacyPolicies: function() { - return this.store.query('privacypolicy', {}); - }.property(), - - privacyPoliciesReady: function() { - return ( - this.get('privacyPolicies.isFulfilled') && - this.get('model.privacy_policy.isFulfilled') - ); - }.property( - 'privacyPolicies.isFulfilled', - 'model.privacy_policy.isFulfilled' - ), - - actions: { - privacyPolicyChanged: function(value) { - this.set('model.privacy_policy', value); - } - } -}); diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/rules.js b/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/rules.js deleted file mode 100644 index 41e3777..0000000 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/rules.js +++ /dev/null @@ -1,69 +0,0 @@ -import Ember from 'ember'; -import validatorFactory from '../../validators/factories'; - -export default Ember.Controller.extend(Ember.Evented, { - rulesPendingDeletion: [], - saveActive: false, - saveContinueActive: false, - validators: {}, - - activeRules: Ember.computed('model', 'model.@each.isDeleted', { - get() { - return this.get('model').filter(function(item) { - return !item.get('isDeleted'); - }); - } - }), - - controlsDisabled: function () { - return (this.saveActive || this.saveContinueActive); - }.property('saveActive', 'saveContinueActive'), - - invalidateOrder: function () { - if (!this.get('controlsDisabled')) { - this.trigger('orderInvalidated'); - } - }, - - validatorFor: function(obj) { - var validatorKey = obj.toString(); - var validators = this.get('validators'); - - if (!(validatorKey in validators)) { - validators[validatorKey] = validatorFactory.createRuleValidator(obj, this); - } - - return validators[validatorKey]; - }, - - removeValidatorFor: function(obj) { - var validatorKey = obj.toString(); - var validators = this.get('validators'); - - if (validatorKey in validators) { - validators[validatorKey].destroy(); - delete validators[validatorKey]; - } - }, - - actions: { - addRule: function(rule) { - this.send('addRuleToRoute', rule); - }, - deleteRule: function(rule) { - this.send('deleteRuleToRoute', rule); - }, - addCondition: function(rule) { - this.send('addConditionToRoute', rule); - }, - deleteCondition: function(condition) { - this.send('deleteConditionToRoute', condition); - }, - addResult: function(rule) { - this.send('addResultToRoute', rule); - }, - deleteResult: function(result) { - this.send('deleteResultToRoute', result); - } - } -}); diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/submissions.js b/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/submissions.js deleted file mode 100644 index 909c7c9..0000000 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/controllers/form/submissions.js +++ /dev/null @@ -1,113 +0,0 @@ -import Ember from 'ember'; - -export default Ember.Controller.extend({ - queryParams: [ - 'page', - 'source' - ], - formId: null, - source: null, - page: 1, - - fields: function() { - return this.store.query('field', {form: this.get('formId')}); - }.property(), - - columnHeaders: function() { - // base column headers - var headers = ['Date/Time', 'Source', 'Promo Source']; - - if (this.get('fields.isFulfilled')) { - this.get('fields').forEach(function(field) { - headers.push(field.get('data_name')); - }); - } - - return headers; - }.property('fields.isFulfilled'), - - customColumnSlugs: function() { - var slugs = []; - - if (this.get('fields.isFulfilled')) { - this.get('fields').forEach(function(field) { - slugs.push(field.get('slug')); - }); - } - - return slugs; - }.property('fields.isFulfilled'), - - submissionDataList: function() { - var rows = []; - var slugs = this.get('customColumnSlugs'); - - var submissions = this.get('model'); - - submissions.forEach(function(submission) { - let row = [ - submission.get('date_created'), - submission.get('source'), - submission.get('promo_source') - ]; - for (var j = 0; j < slugs.length; j++) { - var slug = slugs[j]; - row.push(submission.get('custom_data')[slug]); - } - rows.push(row); - }); - - return rows; - }.property('page', 'model.isFulfilled', 'customColumnSlugs', 'source'), - - hasSubmissions: function() { - return this.get('submissionDataList').length > 0; - }.property('submissionDataList'), - - metaData: Ember.computed('model', function() { - var meta = this.get('model.meta'); - return meta; - }), - - count: function() { - if (this.get('metaData')) { - return this.get('metaData').count; - } else { - return null; - } - }.property('metaData'), - - currentPage: function() { - return this.getWithDefault('page', 1); - }.property('metaData'), - - nextPage: function() { - return this.get('metaData').next; - }.property('metaData'), - - previousPage: function() { - var previous_page = this.get('page') - 1; - return (previous_page > 0) ? previous_page : null; - }.property('metaData'), - - pageCount: function() { - return Math.ceil(this.get('count') / this.get('page_size')); - }.property('count', 'page_size'), - - sources: function() { - var source_objs = this.store.query('submissionsource', { - form: this.get('formId') - }); - return source_objs; - }.property(), - - selectedSource: function(key, value, previousValue) { - if (value !== previousValue) { - this.send('changeSource', value); - } - - return this.get('source'); - }.property('source'), - - actions: {} -}); diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/index.html b/formulaic/static/admin/formulaic/ember-formulaic/app/index.html index 319b587..3bf4045 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/index.html +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/index.html @@ -2,23 +2,23 @@ - - Formulaic + EmberFormulaic {{content-for "head"}} - - + + {{content-for "head-footer"}} +
{{content-for "body"}} - - + + {{content-for "body-footer"}} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/initializers/cookie-initializer.js b/formulaic/static/admin/formulaic/ember-formulaic/app/initializers/cookie-initializer.js deleted file mode 100644 index 0d78604..0000000 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/initializers/cookie-initializer.js +++ /dev/null @@ -1,11 +0,0 @@ -export function initialize(application) { - application.inject('route', 'cookie', 'cookie:main'); - application.inject('controller', 'cookie', 'cookie:main'); - application.inject('adapter', 'cookie', 'cookie:main'); -} - -export default { - name: 'cookie-initializer', - before: ['ember-data'], - initialize: initialize -}; diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/locations/auto.js b/formulaic/static/admin/formulaic/ember-formulaic/app/locations/auto.js new file mode 100644 index 0000000..22b8b5f --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/locations/auto.js @@ -0,0 +1,8 @@ +import HistoryLocation from '@ember/routing/history-location'; + +export default class CustomAutoLocation extends HistoryLocation { + constructor() { + super(...arguments); + console.log('CustomAutoLocation initialized'); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/models/basefield.js b/formulaic/static/admin/formulaic/ember-formulaic/app/models/basefield.js index 8ce6cb2..f4591bf 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/models/basefield.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/models/basefield.js @@ -1,16 +1,16 @@ -import DS from 'ember-data'; +import Model, { attr, belongsTo } from '@ember-data/model'; -export default DS.Model.extend({ - name: DS.attr('string'), - display_name: DS.attr('string'), - data_name: DS.attr('string'), - slug: DS.attr('string'), - required: DS.attr('boolean'), - help_text: DS.attr('string'), - model_class: DS.attr('string'), - position: DS.attr('number'), - css_class: DS.attr('string'), - form: DS.belongsTo('form'), - enabled: DS.attr('boolean'), - subtype: DS.attr('string') -}); +export default class BaseFieldModel extends Model { + @attr('string') name; + @attr('string') display_name; + @attr('string') data_name; + @attr('string') slug; + @attr('boolean') required; + @attr('string') help_text; + @attr('string') model_class; + @attr('number') position; + @attr('string') css_class; + @belongsTo('form', { async: false, inverse: 'fields', as: 'field' }) form; + @attr('boolean') enabled; + @attr('string') subtype; +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/models/booleanfield.js b/formulaic/static/admin/formulaic/ember-formulaic/app/models/booleanfield.js index 95c7a56..19675fe 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/models/booleanfield.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/models/booleanfield.js @@ -1,13 +1,13 @@ -import DS from 'ember-data'; -import BaseField from './basefield'; +import { belongsTo, attr } from '@ember-data/model'; +import BaseFieldModel from './basefield'; import BooleanFieldValidator from '../validators/fields/booleanfield'; -export default BaseField.extend({ - field: DS.belongsTo('field'), - default_checked: DS.attr('boolean'), +export default class BooleanFieldModel extends BaseFieldModel { + @belongsTo('field', { async: false, inverse: 'booleanfield' }) field; + @attr('boolean') default_checked; - init() { - this._super(...arguments); - this.validator = BooleanFieldValidator.create({field: this}); + constructor() { + super(...arguments); + this.validator = BooleanFieldValidator.create({ field: this }); } -}); +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/models/choicefield.js b/formulaic/static/admin/formulaic/ember-formulaic/app/models/choicefield.js index cbefa31..bcb5b33 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/models/choicefield.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/models/choicefield.js @@ -1,19 +1,19 @@ -import DS from 'ember-data'; -import BaseField from './basefield'; +import { belongsTo, attr, hasMany } from '@ember-data/model'; +import BaseFieldModel from './basefield'; import ChoiceFieldValidator from '../validators/fields/choicefield'; -export default BaseField.extend({ - field: DS.belongsTo('field', { async: false }), - minimum_selections: DS.attr('string'), - maximum_selections: DS.attr('string'), - option_list: DS.belongsTo('optionlist', { async: true }), - option_group: DS.belongsTo('optiongroup', { async: true }), - default_option: DS.belongsTo('option', {async: true }), - default_options: DS.hasMany('option', { async: true }), - default_text: DS.attr('string'), +export default class ChoiceFieldModel extends BaseFieldModel { + @belongsTo('field', { async: false, inverse: 'choicefield' }) field; + @attr('string') minimum_selections; + @attr('string') maximum_selections; + @belongsTo('optionlist', { async: false, inverse: 'choicefield' }) option_list; + @belongsTo('optiongroup', { async: false, inverse: null }) option_group; + @belongsTo('option', { async: false, inverse: null }) default_option; + @hasMany('option', { async: false, inverse: null }) default_options; + @attr('string') default_text; - init() { - this._super(...arguments); - this.validator = ChoiceFieldValidator.create({field: this}); + constructor() { + super(...arguments); + this.validator = ChoiceFieldValidator.create({ field: this }); } -}); +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/models/field.js b/formulaic/static/admin/formulaic/ember-formulaic/app/models/field.js index cf65796..0228b26 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/models/field.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/models/field.js @@ -1,10 +1,10 @@ -import DS from 'ember-data'; -import BaseField from './basefield'; +import { belongsTo, attr } from '@ember-data/model'; +import BaseFieldModel from './basefield'; -export default BaseField.extend({ - textfield: DS.belongsTo('textfield', {async: false}), - choicefield: DS.belongsTo('choicefield', {async: false}), - booleanfield: DS.belongsTo('booleanfield', {async: false}), - hiddenfield: DS.belongsTo('hiddenfield', {async: false}), - content_type: DS.attr('number') -}); +export default class FieldModel extends BaseFieldModel { + @belongsTo('textfield', { async: false, inverse: 'field' }) textfield; + @belongsTo('choicefield', { async: false, inverse: 'field' }) choicefield; + @belongsTo('booleanfield', { async: false, inverse: 'field' }) booleanfield; + @belongsTo('hiddenfield', { async: false, inverse: 'field' }) hiddenfield; + @attr('number') content_type; +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/models/form.js b/formulaic/static/admin/formulaic/ember-formulaic/app/models/form.js index 870e330..6caddb7 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/models/form.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/models/form.js @@ -1,8 +1,10 @@ -import DS from 'ember-data'; +import Model, { attr, belongsTo, hasMany } from '@ember-data/model'; -export default DS.Model.extend({ - name: DS.attr('string'), - slug: DS.attr('string'), - success_message: DS.attr('string'), - privacy_policy: DS.belongsTo('privacypolicy', {async:true}) -}); +export default class FormModel extends Model { + @attr('string') name; + @attr('string') slug; + @attr('string') success_message; + @belongsTo('privacypolicy', { async: true, inverse: 'forms' }) privacy_policy; + @hasMany('field', { async: false, polymorphic: true, inverse: 'form'}) fields; + @hasMany('rule', { async: false, inverse: 'form' }) rules; +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/models/hiddenfield.js b/formulaic/static/admin/formulaic/ember-formulaic/app/models/hiddenfield.js index 50c9308..09df1fd 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/models/hiddenfield.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/models/hiddenfield.js @@ -1,13 +1,13 @@ -import BaseField from './basefield'; -import DS from 'ember-data'; +import { belongsTo, attr } from '@ember-data/model'; +import BaseFieldModel from './basefield'; import HiddenFieldValidator from '../validators/fields/hiddenfield'; -export default BaseField.extend({ - field: DS.belongsTo('field'), - value: DS.attr('string'), +export default class HiddenFieldModel extends BaseFieldModel { + @belongsTo('field', { async: false, inverse: 'hiddenfield' }) field; + @attr('string') value; - init() { - this._super(...arguments); - this.validator = HiddenFieldValidator.create({field: this}); + constructor() { + super(...arguments); + this.validator = HiddenFieldValidator.create({ field: this }); } -}); +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/models/option.js b/formulaic/static/admin/formulaic/ember-formulaic/app/models/option.js index f4647fc..0fce42e 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/models/option.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/models/option.js @@ -1,8 +1,9 @@ -import DS from 'ember-data'; +import Model, { attr, belongsTo } from '@ember-data/model'; -export default DS.Model.extend({ - name: DS.attr('string'), - value: DS.attr('string'), - position: DS.attr('number'), - list: DS.belongsTo('optionlist') -}); \ No newline at end of file +export default class OptionModel extends Model { + @attr('string') name; + @attr('string') value; + @attr('number') position; + @belongsTo('optionlist', { async: false, inverse: 'options' }) list; + @belongsTo('optiongroup', { async: false, inverse: 'options' }) group; +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/models/optiongroup.js b/formulaic/static/admin/formulaic/ember-formulaic/app/models/optiongroup.js index 31a130f..63eb4c3 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/models/optiongroup.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/models/optiongroup.js @@ -1,8 +1,8 @@ -import DS from 'ember-data'; +import Model, { attr, belongsTo, hasMany } from '@ember-data/model'; -export default DS.Model.extend({ - name: DS.attr('string'), - position: DS.attr('number'), - list: DS.belongsTo('optionlist'), - options: DS.hasMany('option') -}); \ No newline at end of file +export default class OptionGroupModel extends Model { + @attr('string') name; + @attr('number') position; + @belongsTo('optionlist', { async: false, inverse: 'groups' }) list; + @hasMany('option', { async: false, inverse: 'group' }) options; +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/models/optionlist.js b/formulaic/static/admin/formulaic/ember-formulaic/app/models/optionlist.js index 3807f33..c676f9c 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/models/optionlist.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/models/optionlist.js @@ -1,7 +1,8 @@ -import DS from 'ember-data'; +import Model, { attr, hasMany } from '@ember-data/model'; -export default DS.Model.extend({ - name: DS.attr('string'), - options: DS.hasMany('option', {async: true}), - groups: DS.hasMany('optiongroup', {async: true}), -}); \ No newline at end of file +export default class OptionListModel extends Model { + @attr('string') name; + @hasMany('option', { async: false, inverse: 'list' }) options; + @hasMany('optiongroup', { async: false, inverse: 'list' }) groups; + @hasMany('choicefield', { async: false, inverse: 'option_list' }) choicefield; +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/models/privacypolicy.js b/formulaic/static/admin/formulaic/ember-formulaic/app/models/privacypolicy.js index a8336ad..33abe56 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/models/privacypolicy.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/models/privacypolicy.js @@ -1,6 +1,7 @@ -import DS from 'ember-data'; +import Model, { attr, hasMany } from '@ember-data/model'; -export default DS.Model.extend({ - name: DS.attr('string'), - text: DS.attr('string') -}); +export default class PrivacyPolicyModel extends Model { + @attr('string') name; + @attr('string') text; + @hasMany('form', { async: false, inverse: 'privacy_policy' }) forms; +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/models/rule.js b/formulaic/static/admin/formulaic/ember-formulaic/app/models/rule.js index 178f0b5..9af70e1 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/models/rule.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/models/rule.js @@ -1,9 +1,27 @@ -import DS from 'ember-data'; - -export default DS.Model.extend({ - form: DS.belongsTo('form', { async:true }), - operator: DS.attr('string'), - position: DS.attr('number'), - conditions: DS.hasMany('rulecondition'), - results: DS.hasMany('ruleresult') -}); \ No newline at end of file +import Model, {belongsTo, attr, hasMany} from '@ember-data/model'; + +import {tracked} from '@glimmer/tracking'; + +export default class RuleModel extends Model { + @belongsTo('form', {async: false, inverse: 'rules'}) form; + @attr('string') operator; + @attr('number') position; + @hasMany('rulecondition', {async: false, inverse: 'rule'}) conditions; + @hasMany('ruleresult', {async: false, inverse: 'rule'}) results; + + @tracked conditionsArray = []; + @tracked resultsArray = []; + @tracked rulePosition = null + + setPosition(position) { + this.rulePosition = position; + } + + setConditions(conditions) { + this.conditionsArray = [...conditions]; + } + + setResults(results) { + this.resultsArray = [...results]; + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/models/rulecondition.js b/formulaic/static/admin/formulaic/ember-formulaic/app/models/rulecondition.js index 5c7254c..3b768f2 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/models/rulecondition.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/models/rulecondition.js @@ -1,16 +1,15 @@ -import DS from 'ember-data'; +import Model, { attr, belongsTo } from '@ember-data/model'; import validatorFactory from '../validators/factories'; -export default DS.Model.extend({ - position: DS.attr('number'), - rule: DS.belongsTo('rule'), - field: DS.belongsTo('field', {async:true}), - operator: DS.attr('string'), - //value_type: DS.attr('string'), - value: DS.attr('json'), +export default class RuleConditionModel extends Model { + @attr('number') position; + @belongsTo('rule', { async: false, inverse: 'conditions' }) rule; + @belongsTo('field', { async: true, inverse: null }) field; + @attr('string') operator; + @attr('json') value; - init() { - this._super(...arguments); + constructor() { + super(...arguments); this.validator = validatorFactory.createRuleValidator(this); } -}); +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/models/ruleresult.js b/formulaic/static/admin/formulaic/ember-formulaic/app/models/ruleresult.js index c1f990f..f05f1a7 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/models/ruleresult.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/models/ruleresult.js @@ -1,14 +1,14 @@ -import DS from 'ember-data'; +import Model, { attr, belongsTo } from '@ember-data/model'; import validatorFactory from '../validators/factories'; -export default DS.Model.extend({ - action: DS.attr('string'), - field: DS.belongsTo('field', {async:true}), - rule: DS.belongsTo('rule'), - option_group: DS.belongsTo('optiongroup', {async:true}), +export default class RuleResultModel extends Model { + @attr('string') action; + @belongsTo('field', { async: true, inverse: null }) field; + @belongsTo('rule', { async: false, inverse: 'results' }) rule; + @belongsTo('optiongroup', { async: false, inverse: null }) option_group; - init() { - this._super(...arguments); + constructor() { + super(...arguments); this.validator = validatorFactory.createRuleValidator(this); } -}); +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/models/submission.js b/formulaic/static/admin/formulaic/ember-formulaic/app/models/submission.js index fd75957..f8280ee 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/models/submission.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/models/submission.js @@ -1,9 +1,9 @@ -import DS from 'ember-data'; +import Model, { attr, belongsTo } from '@ember-data/model'; -export default DS.Model.extend({ - date_created: DS.attr('string'), - source: DS.attr('string'), - promo_source: DS.attr('string'), - form: DS.belongsTo('form', { async:true }), - custom_data: DS.attr('json') -}); +export default class SubmissionModel extends Model { + @attr('string') date_created; + @attr('string') source; + @attr('string') promo_source; + @belongsTo('form', { async: false, inverse: 'submission' }) form; + @attr('json') custom_data; +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/models/submissionsource.js b/formulaic/static/admin/formulaic/ember-formulaic/app/models/submissionsource.js index 15c902b..c6d170e 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/models/submissionsource.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/models/submissionsource.js @@ -1,7 +1,7 @@ -import DS from 'ember-data'; +import Model, { attr } from '@ember-data/model'; // Note: `source` name is the primary key; see serializer -export default DS.Model.extend({ - count: DS.attr('number') -}); +export default class SubmissionSourceModel extends Model { + @attr('number') count; +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/models/textfield.js b/formulaic/static/admin/formulaic/ember-formulaic/app/models/textfield.js index 9b8ee96..28c66c2 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/models/textfield.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/models/textfield.js @@ -1,12 +1,12 @@ -import DS from 'ember-data'; -import BaseField from './basefield'; +import {belongsTo} from '@ember-data/model'; +import BaseFieldModel from './basefield'; import TextFieldValidator from '../validators/fields/textfield'; -export default BaseField.extend({ - field: DS.belongsTo('field'), +export default class TextFieldModel extends BaseFieldModel { + @belongsTo('field', {async: false, inverse: 'textfield'}) field; - init() { - this._super(...arguments); - this.validator = TextFieldValidator.create({field: this}); - } -}); + constructor() { + super(...arguments); + this.validator = TextFieldValidator.create({field: this}); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/router.js b/formulaic/static/admin/formulaic/ember-formulaic/app/router.js index d45f2ef..6b40600 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/router.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/router.js @@ -1,41 +1,20 @@ -import Ember from 'ember'; -import config from './config/environment'; +import EmberRouter from '@ember/routing/router'; +import config from 'ember-formulaic/config/environment'; -const Router = Ember.Router.extend({ - location: config.locationType, - rootURL: config.rootURL -}); +export default class Router extends EmberRouter { + location = config.locationType; + rootURL = config.rootURL; + + constructor() { + super(...arguments); + console.log('Router initialized'); + } +} Router.map(function() { - this.route('form', { - path: '/:form_id/change/' - }, function() { - this.route('fields', function() { - //this.route('field', { path: '/fields/:field_id' }); - }); - this.route('rules'); - this.route('submissions'); - }); + this.route('form', { path: '/:form_id/change' }, function() { + this.route('fields'); + this.route('rules'); + this.route('submissions'); + }); }); - -// var Router = Ember.Router.extend({ -// location: config.locationType // ??? -// }); - -// Router.map(function() { -// this.resource('form', { path: '/:form_id/' }, function() { -// this.route('edit'); -// this.resource('fields', function() { -// //this.route('field', { path: '/fields/:field_id' }); -// }); -// this.resource('rules', function() { - -// }); -// this.resource('submissions', function() { - -// }); -// }); - -// }); - -export default Router; diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form.js b/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form.js index 071da70..191cbed 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form.js @@ -1,12 +1,12 @@ -import Ember from 'ember'; +//routes/form.js -export default Ember.Route.extend({ - model: function(params) { - let formId = params.form_id; +import Route from '@ember/routing/route'; +import {inject as service} from '@ember/service'; - return this.store.find('form', formId); - }, - actions: { - - } -}); +export default class FormRoute extends Route { + @service store; + + async model(params) { + return await this.store.findRecord('form', params.form_id); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/fields.js b/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/fields.js index 3d20948..314467b 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/fields.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/fields.js @@ -1,267 +1,32 @@ -import Ember from "ember"; - -export default Ember.Route.extend({ - needs: 'fields', - - form: function() { - return this.modelFor('form'); - }.property(), - - formId: function() { - return this.get('form.id'); - }.property('form'), - - model: function() { - let formId = this.get('formId'); - - // Fetch fields for store - this.store.query('field', { - form: formId - }); - - return this.store.peekAll('field'); - }, - - setupController: function(controller, model) { - this._super(controller, model); - - // re-enable buttons; necessary after save - controller.set('saveActive', false); - controller.set('saveContinueActive', false); - }, - - renderTemplate: function() { - this.render('form.fields'); - this.renderDefaultSidebar(); - }, - - renderDefaultSidebar: function() { - this.render('form.fields.index', { - into: 'form.fields', - outlet: 'sidebar' - }); - }, - - renderFieldSidebar: function(field) { - if (field.get("textfield")) { - // render TextField edit template - this.render('form/fields/textfield', { - into: 'form.fields', - outlet: 'sidebar', - model: field.get('textfield'), - controller: 'form/fields/textfield' - }); - } else if (field.get("choicefield")) { - // render ChoiceField edit template - this.render('form/fields/choicefield', { - into: 'form.fields', - outlet: 'sidebar', - model: field.get('choicefield'), - controller: 'form/fields/choicefield' - }); - } else if (field.get("booleanfield")) { - // render BooleanField edit template - this.render('form/fields/booleanfield', { - into: 'form.fields', - outlet: 'sidebar', - model: field.get('booleanfield'), - controller: 'form/fields/booleanfield' - }); - } else if (field.get("hiddenfield")) { - // render BooleanField edit template - this.render('form/fields/hiddenfield', { - into: 'form.fields', - outlet: 'sidebar', - model: field.get('hiddenfield'), - controller: 'form/fields/hiddenfield' - }); - } else { - // Raise exception: field type not implemented - throw new Error("Formulaic: field type not implemented"); - } - }, - - _createBaseField: function(subtype) { - let $ = Ember.$; - - // Create the new Field model - let field = this.store.createRecord('field', { - display_name: null, - data_name: null, - slug: null, - required: false, - help_text: null, - model_class: 'textfield', - position: $('.field-sortable').find('.item').length, // TODO: get highest position - css_class: null, - subtype: subtype, - form: this.get('form') - }); - - $('.field-sortable').sortable('refresh'); - - return field; - }, - - openEditField: function(field) { - this.controller.set('currentField', field); - this.renderFieldSidebar(field); - }, - - closeEditField: function() { - this.controller.set('currentField', null); - this.renderDefaultSidebar(); - }, - - invalidateOrder: function() { - this.controller.invalidateOrder(); - }, - - actions: { - editFieldToRoute: function(field) { - this.openEditField(field); - }, - - deleteFieldToRoute: function(field, completeField) { - /** - * Delete both partial and complete field. Deleting completeField - * via fieldsPendingDeletion is necessary because sometimes it is - * the only one that has an ID. - */ - - this.controller.removeValidatorFor(field); - field.deleteRecord(); - - var fieldsPendingDeletion = this.controller.get('fieldsPendingDeletion'); - fieldsPendingDeletion.push(completeField); - - this.invalidateOrder(); - - if (this.controller.get('currentField', null) === field) { - this.closeEditField(); - } - }, - - doneEditingField: function() { - this.closeEditField(); - }, - - createTextField: function(subtype) { - if (["text", "textarea", "email", "phone_number", "integer", "full_name"].indexOf(subtype) === -1) { - // Raise exception: field subtype not implemented - throw new Error("Formulaic: text field subtype `" + subtype + "` not implemented"); - } - - let field = this._createBaseField(subtype); - - let textfield = this.store.createRecord('textfield', { - display_name: field.get('display_name'), - data_name: field.get('data_name'), - slug: field.get('slug'), - required: field.get('required'), - help_text: field.get('help_text'), - model_class: field.get('model_class'), - position: field.get('position'), - css_class: field.get('css_class'), - form: field.get('form'), - subtype: subtype - }); - - field.set('textfield', textfield); - - this.openEditField(field); - }, - - createChoiceField: function(subtype) { - if (["select", "radio_select", "checkbox_select_multiple", "select_multiple"].indexOf(subtype) === -1) { - // Raise exception: field subtype not implemented - throw new Error("Formulaic: choice field subtype `" + subtype + "` not implemented"); - } - - let field = this._createBaseField(subtype); - - let choicefield = this.store.createRecord('choicefield', { - display_name: field.get('display_name'), - data_name: field.get('data_name'), - slug: field.get('slug'), - required: field.get('required'), - help_text: field.get('help_text'), - model_class: field.get('model_class'), - position: field.get('position'), - css_class: field.get('css_class'), - form: field.get('form'), - subtype: subtype, - minimum_selections: null, - maximum_selections: null, - option_list: null, - default_option: null - }); - - field.set('choicefield', choicefield); - - this.openEditField(field); - }, - - createBooleanField: function(subtype) { - if (subtype !== "checkbox") { - // Raise exception: field subtype not implemented - throw new Error("Formulaic: boolean field subtype `" + subtype + "` not implemented"); - } - - let field = this._createBaseField(subtype); - - let booleanfield = this.store.createRecord('booleanfield', { - display_name: field.get('display_name'), - data_name: field.get('data_name'), - slug: field.get('slug'), - required: field.get('required'), - help_text: field.get('help_text'), - model_class: field.get('model_class'), - position: field.get('position'), - css_class: field.get('css_class'), - form: field.get('form'), - subtype: subtype - }); - - field.set('booleanfield', booleanfield); - - this.openEditField(field); - }, - - createHiddenField: function (subtype) { - if (subtype !== "hidden") { - // Raise exception: field subtype not implemented - throw new Error("Formulaic: hidden field subtype `" + subtype + "` not implemented"); - } - - let field = this._createBaseField(subtype); - - let hiddenfield = this.store.createRecord('hiddenfield', { - display_name: field.get('display_name'), - data_name: field.get('data_name'), - slug: field.get('slug'), - required: field.get('required'), - help_text: field.get('help_text'), - model_class: field.get('model_class'), - position: field.get('position'), - css_class: field.get('css_class'), - form: field.get('form'), - subtype: subtype, - value: "" - }); - - field.set('hiddenfield', hiddenfield); - - this.openEditField(field); - }, - - reloadFields: function() { - /** - * Unloads all fields and refreshes the route, triggering a - * new API request. - */ - this.store.unloadAll('field'); - this.refresh(); - } +//routes/form/field.js + +import Route from '@ember/routing/route'; +import {inject as service} from '@ember/service'; + +export default class FieldsRoute extends Route { + @service store; + @service('field-service') fieldService; + + get form() { + return this.modelFor('form'); + } + + get formId() { + return this.form.id; + } + + async model() { + try { + let fieldRecords = await this.store.query('field', {form: this.formId}); + this.fieldService.currentForm = this.form; + this.fieldService.currentFormFields = fieldRecords.toArray(); + return this.fieldService.currentFormFields; + } catch (error) { + throw error; } -}); + } + + renderTemplate() { + this.render('form.fields'); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/index.js b/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/index.js index 8503bd3..cb70c9b 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/index.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/index.js @@ -1,75 +1,9 @@ -import Ember from 'ember'; +//routes/form/index.js -export default Ember.Route.extend({ - form: function() { - return this.modelFor('form'); - }.property(), +import Route from '@ember/routing/route'; - formId: function() { - return this.get('form.id'); - }.property('form'), - - actions: { - editForm: function() { - // go into edit mode - this.controller.set('inEditMode', true); - }, - - saveForm: function() { - var thisRoute = this; - var promises = []; - - // Set loading/saving state - this.controller.set('saveActive', true); - - promises.push(this.modelFor('form').save()); - - // Handle all save completions together - Ember.RSVP.allSettled(promises).then(function () { - // Reset loading/saving state - thisRoute.controller.set('saveActive', false); - - // Notify user of success - // thisRoute.toast.options.positionClass = "toast-bottom-center"; - thisRoute.toast.success('Form saved.'); - - // exit edit mode - thisRoute.controller.set('inEditMode', false); - }, function () { - // console.error(error); - }); - }, - - close: function() { - // exit edit mode - this.controller.set('inEditMode', false); - }, - - editFields: function() { - this.transitionTo('form.fields'); - }, - - editRules: function() { - this.transitionTo('form.rules'); - }, - - viewSubmissions: function() { - this.transitionTo('form.submissions'); - }, - - downloadSubmissions: function() { - let $ = Ember.$; - let thisRoute = this; - let $form = $('#ld-submissions-dl-' + this.get('form.id')); - - this.controller.set('downloadInProgress', true); - this.controller.set('downloadFailed', false); - - $form.on('handl:form-unlocked', function() { - thisRoute.controller.set('downloadInProgress', false); - }); - - $form.submit(); - } - } -}); +export default class IndexRoute extends Route { + model() { + return this.modelFor('form'); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/rules.js b/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/rules.js index eadeb01..a62334b 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/rules.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/rules.js @@ -1,189 +1,35 @@ -/* global toastr */ +import Route from '@ember/routing/route'; +import {inject as service} from '@ember/service'; -import Ember from "ember"; +export default class RulesRoute extends Route { + @service store; + @service('field-service') fieldService; -export default Ember.Route.extend({ - form: function() { - return this.modelFor('form'); - }.property(), + get form() { + return this.modelFor('form'); + } - formId: function() { - return this.get('form.id'); - }.property('form'), + get formId() { + return this.form.id; + } - model: function() { - let formId = this.get('formId'); + async model() { - // Pre-fetch rules - this.store.query('rule', { - form: formId - }); + try { - // Fetch fields - this.store.query('field', { - form: formId - }); + let formRules = await this.store.query('rule', {form: this.form.id}); + let formFields = await this.store.query('field', {form: this.form.id}); + await this.store.query('optionlist', {}); + await this.store.query('optiongroup', {}); - return this.store.peekAll('rule'); + this.fieldService.currentForm = this.form; + this.fieldService.currentFormFields = formFields.toArray(); + this.fieldService.currentFormRules = formRules.toArray(); - // return this.store.filter('rule', { - // form: this.get('formId') - // }, function(rule) { - // return rule; - // }); - }, - - setupController: function (controller, model) { - this._super(controller, model); - - // re-enable buttons; necessary after save - controller.set('saveActive', false); - controller.set('saveContinueActive', false); - }, - - _createCondition: function(rule) { - var condition = this.store.createRecord('rulecondition', { - position: rule.get('conditions').content.length, - rule: rule, - field: null, - operator: null - }); - rule.get('conditions').pushObject(condition); - - return condition; - }, - - _createResult: function(rule) { - var result = this.store.createRecord('ruleresult', { - action: null, - field: null, - rule: rule - }); - rule.get('results').pushObject(result); - - return result; - }, - - actions: { - addRuleToRoute: function() { - var rule = this.store.createRecord('rule', { - form: this.get('form'), - operator: 'and', - position: this.controller.get('model').content.length - }); - - this._createCondition(rule); - - this._createResult(rule); - }, - - deleteRuleToRoute: function(rule) { - this.controller.removeValidatorFor(rule); - rule.deleteRecord(); - - var rulesPendingDeletion = this.controller.get('rulesPendingDeletion'); - rulesPendingDeletion.push(rule); - }, - - saveRules: function(continueEditing) { - var i = 0; - var thisRoute = this; - var promises = []; - - // Set loading/saving state - if (continueEditing) { - this.controller.set('saveContinueActive', true); - } else { - this.controller.set('saveActive', true); - } - - // Validate data - var validationErrors = []; - var rules = this.controller.get('model').toArray(); - for (i = 0; i < rules.length; i++) { - var validator = this.controller.validatorFor(rules[i]); - if (validator.get('isInvalidWithChildren')) { - validationErrors.push('Rule is incomplete'); - } - } - - if (validationErrors.length > 0) { - // Cancel 'Save'; output error messages - toastr.options.positionClass = "toast-bottom-center"; - toastr.warning('Unable to save because of these issues:
' + validationErrors.join('
')); - - // Reset loading/saving state - thisRoute.controller.set('saveContinueActive', false); - thisRoute.controller.set('saveActive', false); - } else { - // Delete rules marked for deletion - var rulesPendingDeletion = this.controller.get('rulesPendingDeletion'); - for (i = 0; i < rulesPendingDeletion.length; i++) { - promises.push(rulesPendingDeletion[i].save()); - } - - // Save Rule objects - promises.push(this.controller.get('model').save()); - - // Handle all save completions together - Ember.RSVP.allSettled(promises).then(function (results) { - var saveErrors = []; - for (i = 0; i < results.length; i++) { - if (results[i].state === "rejected") { - saveErrors.push(results[i]); - } - } - - // Reset loading/saving state - thisRoute.controller.set('saveContinueActive', false); - thisRoute.controller.set('saveActive', false); - - if (saveErrors.length > 0) { - // Notify user of failure - toastr.options.positionClass = "toast-bottom-center"; - toastr.error('Save failed. Contact administrator.'); - } else { - // Reload from store (obscures bug causing duplicate rules) - thisRoute.store.unloadAll('rule'); - thisRoute.store.unloadAll('ruleresult'); - thisRoute.store.unloadAll('rulecondition'); - thisRoute.refresh(); - - // Notify user of success - toastr.options.positionClass = "toast-bottom-center"; - toastr.success('Rules saved.'); - - // Redirect to form page if appropriate - if (!continueEditing) { - thisRoute.transitionTo('form'); - } - } - }, function (error) { - Ember.Logger.error(error); - }); - } - }, - - closeRules: function() { - this.transitionTo('form'); - }, - - addConditionToRoute: function(rule) { - this._createCondition(rule); - }, - - deleteConditionToRoute: function(condition) { - this.controller.removeValidatorFor(condition); - condition.deleteRecord(); - }, - - addResultToRoute: function(rule) { - this._createResult(rule); - }, - - deleteResultToRoute: function(result) { - this.controller.removeValidatorFor(result); - result.deleteRecord(); - } + return this.fieldService.currentFormRules; + } catch (error) { + console.error('Error fetching rules:', error); + throw error; } -}); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/submissions.js b/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/submissions.js index b00d32c..54ca5bb 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/submissions.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/routes/form/submissions.js @@ -1,89 +1,93 @@ -import Ember from "ember"; +//routes/form/submissions.js -export default Ember.Route.extend({ - page_size: 25, - page: null, - source: null, +import { action, computed } from '@ember/object'; +import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; - queryParams: { - page: { - refreshModel: false - }, - source: { - refreshModel: false - } +export default class SubmissionsRoute extends Route { + @service store; + + page_size = 25; + page = null; + source = null; + + queryParams = { + page: { + refreshModel: false }, + source: { + refreshModel: false + } + }; - form: function() { - return this.modelFor('form'); - }.property(), + get form() { + return this.modelFor('form'); + } - formId: function() { - return this.get('form.id'); - }.property('form'), + get formId() { + return this.form.id; + } + + async model(params) { + try { + return await this.store.query('submission', { + form: this.formId, + page: params.page || 1, + page_size: this.page_size, + source: params.source || null + }); + } catch (error) { + console.error('Error fetching submissions:', error); + throw error; + } + } - model: function(params) { - var page = (params.page) ? params.page : 1; + setupController(controller, model) { + super.setupController(controller, model); + controller.setProperties({ + page_size: this.page_size, + formId: this.formId + }); + } - var requestParams = { - form: this.get('formId'), - page_size: this.page_size, - page: page - }; + gotoPage(page) { + if (page == null) { + page = 1; + } - if (params.source) { - requestParams["source"] = params.source; - } + this.transitionTo('form.submissions', { + queryParams: { page: page } + }); + this.refresh(); + } - let promise = this.store.query( - 'submission', - requestParams - ); + @action + closeSubmissions() { + this.transitionTo('form'); + } - return promise; - }, + @action + gotoNextPage(model) { + let meta = model.meta; + this.gotoPage(meta.next); + } - setupController: function(controller, model) { - this._super(controller, model); - controller.setProperties({ - page_size: this.get('page_size'), - formId: this.get('formId') - }); - }, - gotoPage: function(page) { - if (page == null) { - page = 1; - } + @action + gotoPreviousPage(model) { + let meta = model.meta; + this.gotoPage(meta.previous); + } - this.transitionTo('form.submissions', { - queryParams: { - page: page - } - }); - this.refresh(); - }, - actions: { - closeSubmissions: function() { - this.transitionTo('form'); - }, - gotoNextPage: function(model) { - var meta = model.get('meta'); - this.gotoPage(meta.next); - }, - gotoPreviousPage: function(model) { - var meta = model.get('meta'); - this.gotoPage(meta.previous); - }, - changeSource: function(value) { - var queryParams = { - page: 1, - source: value - }; + @action + changeSource(value) { + let queryParams = { + page: 1, + source: value + }; - this.transitionTo('form.submissions', { - queryParams: queryParams - }); - this.refresh(); - } - } -}); + this.transitionTo('form.submissions', { + queryParams: queryParams + }); + this.refresh(); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/booleanfield.js b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/booleanfield.js new file mode 100644 index 0000000..367140d --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/booleanfield.js @@ -0,0 +1,8 @@ +// serializers/text-field.js +import JSONSerializer from '@ember-data/serializer/json'; + +export default class BooleanFieldSerializer extends JSONSerializer { + normalizeResponse(store, primaryModelClass, payload, id, requestType) { + return super.normalizeResponse(store, primaryModelClass, payload, id, requestType); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/choicefield.js b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/choicefield.js new file mode 100644 index 0000000..403063e --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/choicefield.js @@ -0,0 +1,8 @@ +// serializers/text-field.js +import JSONSerializer from '@ember-data/serializer/json'; + +export default class ChoiceFieldSerializer extends JSONSerializer { + normalizeResponse(store, primaryModelClass, payload, id, requestType) { + return super.normalizeResponse(store, primaryModelClass, payload, id, requestType); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/field.js b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/field.js index f7e0301..38b2d0e 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/field.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/field.js @@ -1,11 +1,129 @@ -import DRFSerializer from './drf'; -import DS from 'ember-data'; - -export default DRFSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - textfield: { embedded: 'always' }, - choicefield: { embedded: 'always' }, - booleanfield: { embedded: 'always' }, - hiddenfield: { embedded: 'always' } +import JSONSerializer from '@ember-data/serializer/json'; + +export default class FieldSerializer extends JSONSerializer { + normalizeResponse(store, primaryModelClass, payload, id, requestType) { + let data, included; + + if (Array.isArray(payload)) { + data = payload.map((item) => this._normalizeItem(item)); + included = this._extractIncluded(payload); + } else { + data = this._normalizeItem(payload); + included = this._extractIncluded([payload]); } -}); + + included.forEach(record => { + store.push({ data: record }); + }); + + return { data }; + } + + _normalizeItem(item) { + let attributes = { + display_name: item.display_name, + data_name: item.data_name, + slug: item.slug, + required: item.required, + model_class: item.model_class, + position: item.position, + form: item.form, + subtype: item.subtype, + enabled: item.enabled, + content_type: item.content_type + }; + + let relationships = { + textfield: item.textfield ? { data: { type: 'textfield', id: String(item.textfield.id) } } : null, + booleanfield: item.booleanfield ? { data: { type: 'booleanfield', id: String(item.booleanfield.id) } } : null, + choicefield: item.choicefield ? { data: { type: 'choicefield', id: String(item.choicefield.id) } } : null, + hiddenfield: item.hiddenfield ? { data: { type: 'hiddenfield', id: String(item.hiddenfield.id) } } : null, + form: item.form ? { data: { type: 'form', id: String(item.form) } } : null, + }; + + return { id: String(item.id), type: 'field', attributes, relationships }; + } + + _extractIncluded(payload) { + let included = []; + let seenTextfields = new Set(); + let seenBooleanfields = new Set(); + let seenChoicefields = new Set(); + let seenHiddenfields = new Set(); + let seenOptionLists = new Set(); + let seenOptionGroups = new Set(); + let seenOptions = new Set(); + + payload.forEach((item) => { + if (item.textfield && !seenTextfields.has(item.textfield.id)) { + seenTextfields.add(item.textfield.id); + included.push(this._createIncludedRecord('textfield', item.textfield, item)); + } + + if (item.booleanfield && !seenBooleanfields.has(item.booleanfield.id)) { + seenBooleanfields.add(item.booleanfield.id); + included.push(this._createIncludedRecord('booleanfield', item.booleanfield, item)); + } + + if (item.choicefield && !seenChoicefields.has(item.choicefield.id)) { + seenChoicefields.add(item.choicefield.id); + included.push(this._createIncludedRecord('choicefield', item.choicefield, item)); + + if (item.choicefield.option_list && !seenOptionLists.has(item.choicefield.option_list)) { + seenOptionLists.add(item.choicefield.option_list); + included.push(this._createIncludedRecord('optionlist', { id: item.choicefield.option_list }, item.choicefield)); + } + + if (item.choicefield.option_group && !seenOptionGroups.has(item.choicefield.option_group)) { + seenOptionGroups.add(item.choicefield.option_group); + included.push(this._createIncludedRecord('optiongroup', { id: item.choicefield.option_group }, item.choicefield)); + } + + if (item.choicefield.default_option && !seenOptions.has(item.choicefield.default_option)) { + seenOptions.add(item.choicefield.default_option); + included.push(this._createIncludedRecord('option', { id: item.choicefield.default_option }, item.choicefield)); + } + + if (item.choicefield.default_options && item.choicefield.default_options.length) { + item.choicefield.default_options.forEach(option => { + if (!seenOptions.has(option.id)) { + seenOptions.add(option.id); + included.push(this._createIncludedRecord('option', option, item.choicefield)); + } + }); + } + } + + if (item.hiddenfield && !seenHiddenfields.has(item.hiddenfield.id)) { + seenHiddenfields.add(item.hiddenfield.id); + included.push(this._createIncludedRecord('hiddenfield', item.hiddenfield, item)); + } + + }); + + return included; + } + + _createIncludedRecord(type, item, parentItem) { + let attributes = item; + + let relationships = { + field: { data: { type: 'field', id: String(parentItem.id) } }, + form: { data: { type: 'form', id: String(item.form) } } + }; + + if (type === 'choicefield') { + relationships.option_list = item.option_list ? { data: { type: 'optionlist', id: String(item.option_list) } } : null; + relationships.option_group = item.option_group ? { data: { type: 'optiongroup', id: String(item.option_group) } } : null; + relationships.default_option = item.default_option ? { data: { type: 'option', id: String(item.default_option) } } : null; + relationships.default_options = item.default_options ? item.default_options.map(option => ({ data: { type: 'option', id: String(option) } })) : []; + } + + return { + id: String(item.id), + type: type, + attributes, + relationships + }; + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/form.js b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/form.js new file mode 100644 index 0000000..9b4147f --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/form.js @@ -0,0 +1,8 @@ +// serializers/form.js +import JSONSerializer from '@ember-data/serializer/json'; + +export default class FormSerializer extends JSONSerializer { + normalizeResponse(store, primaryModelClass, payload, id, requestType) { + return super.normalizeResponse(store, primaryModelClass, payload, id, requestType); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/hiddenfield.js b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/hiddenfield.js new file mode 100644 index 0000000..ad60a45 --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/hiddenfield.js @@ -0,0 +1,8 @@ +// serializers/text-field.js +import JSONSerializer from '@ember-data/serializer/json'; + +export default class HiddenFieldSerializer extends JSONSerializer { + normalizeResponse(store, primaryModelClass, payload, id, requestType) { + return super.normalizeResponse(store, primaryModelClass, payload, id, requestType); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/option.js b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/option.js new file mode 100644 index 0000000..273cb90 --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/option.js @@ -0,0 +1,29 @@ +import JSONSerializer from '@ember-data/serializer/json'; + +export default class OptionSerializer extends JSONSerializer { + normalizeResponse(store, primaryModelClass, payload, id, requestType) { + let data, included; + + if (Array.isArray(payload)) { + data = payload.map((item) => this._normalizeItem(item)); + } else { + data = this._normalizeItem(payload); + } + + return { data }; + } + + _normalizeItem(item) { + let attributes = { + name: item.name, + value: item.value, + position: item.position + }; + + let relationships = { + list: item.list ? { data: { type: 'optionlist', id: String(item.list) } } : null + }; + + return { id: String(item.id), type: 'option', attributes, relationships }; + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/optiongroup.js b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/optiongroup.js index 6f3d53f..c119358 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/optiongroup.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/optiongroup.js @@ -1,8 +1,73 @@ -import DRFSerializer from './drf'; -import DS from 'ember-data'; +import JSONSerializer from '@ember-data/serializer/json'; -export default DRFSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - options: { embedded: 'always' } +export default class OptionGroupSerializer extends JSONSerializer { + normalizeResponse(store, primaryModelClass, payload, id, requestType) { + let data, included; + + if (Array.isArray(payload)) { + data = payload.map((item) => this._normalizeItem(item)); + included = this._extractIncluded(payload); + } else { + data = this._normalizeItem(payload); + included = this._extractIncluded([payload]); } -}); + + included.forEach(record => { + store.push({ data: record }); + }); + + return { data }; + } + + _normalizeItem(item) { + let attributes = { + name: item.name, + position: item.position + }; + + let relationships = { + options: item.options ? item.options.map(option => ({ data: { type: 'option', id: String(option.id) } })) : [], + list: item.list ? { data: { type: 'optionlist', id: String(item.list) } } : null + }; + + return { id: String(item.id), type: 'optiongroup', attributes, relationships }; + } + + _extractIncluded(payload) { + let included = []; + let seenOptions = new Set(); + + payload.forEach((item) => { + if (item.options && item.options.length) { + item.options.forEach(option => { + if (!seenOptions.has(option.id)) { + seenOptions.add(option.id); + included.push(this._createIncludedRecord('option', option, item)); + } + }); + } + }); + + return included; + } + + _createIncludedRecord(type, item, parentItem) { + let attributes = { + name: item.name, + value: item.value, + position: item.position + }; + + let relationships = { + group: { data: { type: 'optiongroup', id: String(parentItem.id) } }, + list: { data: { type: 'optionlist', id: String(item.list) } } + }; + + return { + id: String(item.id), + type: type, + attributes, + relationships + }; + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/optionlist.js b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/optionlist.js index de59dc7..2b01e52 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/optionlist.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/optionlist.js @@ -1,8 +1,82 @@ -import DRFSerializer from './drf'; -import DS from 'ember-data'; +import JSONSerializer from '@ember-data/serializer/json'; -export default DRFSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - options: { embedded: 'always' } +export default class OptionListSerializer extends JSONSerializer { + normalizeResponse(store, primaryModelClass, payload, id, requestType) { + let data, included; + + if (Array.isArray(payload)) { + data = payload.map((item) => this._normalizeItem(item)); + included = this._extractIncluded(payload); + } else { + data = this._normalizeItem(payload); + included = this._extractIncluded([payload]); } -}); \ No newline at end of file + + included.forEach(record => { + store.push({ data: record }); + }); + + return { data }; + } + + _normalizeItem(item) { + let attributes = { + name: item.name + }; + + let relationships = { + options: item.options ? item.options.map(option => ({ data: { type: 'option', id: String(option.id) } })) : [], + groups: item.groups ? item.groups.map(group => ({ data: { type: 'optiongroup', id: String(group.id) } })) : [] + }; + + return { id: String(item.id), type: 'optionlist', attributes, relationships }; + } + + _extractIncluded(payload) { + let included = []; + let seenOptions = new Set(); + let seenOptionGroups = new Set(); + + payload.forEach((item) => { + if (item.options && item.options.length) { + item.options.forEach(option => { + if (!seenOptions.has(option.id)) { + seenOptions.add(option.id); + included.push(this._createIncludedRecord('option', option, item)); + } + }); + } + + if (item.groups && item.groups.length) { + item.groups.forEach(group => { + if (!seenOptionGroups.has(group.id)) { + seenOptionGroups.add(group.id); + included.push(this._createIncludedRecord('optiongroup', group, item)); + } + }); + } + }); + + return included; + } + + _createIncludedRecord(type, item, parentItem) { + let attributes = { + name: item.name, + value: item.value, + position: item.position, + list: item.list + }; + + let relationships = { + list: { data: { type: 'optionlist', id: String(parentItem.id) } } + }; + + return { + id: String(item.id), + type: type, + attributes, + relationships + }; + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/privacypolicy.js b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/privacypolicy.js new file mode 100644 index 0000000..3bd609f --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/privacypolicy.js @@ -0,0 +1,17 @@ +import JSONSerializer from '@ember-data/serializer/json'; + +export default class PrivacyPolicySerializer extends JSONSerializer { + normalizeResponse(store, primaryModelClass, payload, id, requestType) { + + let data = payload.map(policy => ({ + id: String(policy.id), + type: 'privacypolicy', + attributes: { + name: policy.name, + text: policy.text + } + })); + + return { data } + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/rule.js b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/rule.js index b9e2368..e08d451 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/rule.js +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/rule.js @@ -1,9 +1,139 @@ -import DRFSerializer from './drf'; -import DS from 'ember-data'; +import JSONSerializer from '@ember-data/serializer/json'; -export default DRFSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - conditions: { embedded: 'always' }, - results: { embedded: 'always' } +export default class RuleSerializer extends JSONSerializer { + normalizeResponse(store, primaryModelClass, payload, id, requestType) { + let data, included; + + if (Array.isArray(payload)) { + data = payload.map((item) => this._normalizeItem(item)); + included = this._extractIncluded(payload); + } else { + data = this._normalizeItem(payload); + included = this._extractIncluded([payload]); + } + + included.forEach(record => { + store.push({data: record}); + }); + + return {data}; + } + + _normalizeItem(item) { + let attributes = { + operator: item.operator, + position: item.position + }; + + let relationships = { + form: item.form ? {data: {type: 'form', id: String(item.form)}} : null, + conditions: item.conditions ? { + data: item.conditions.map(condition => ({ + type: 'rulecondition', + id: String(condition.id) + })) + } : [], + results: item.results ? {data: item.results.map(result => ({type: 'ruleresult', id: String(result.id)}))} : [] + }; + + return {id: String(item.id), type: 'rule', attributes, relationships}; + } + + _extractIncluded(payload) { + let included = []; + + payload.forEach((item) => { + if (item.conditions && Array.isArray(item.conditions)) { + item.conditions.forEach(condition => { + included.push(this._createConditionRecord(condition, item.id)); + }); + } + + if (item.results && Array.isArray(item.results)) { + item.results.forEach(result => { + included.push(this._createResultRecord(result, item.id)); + }); + } + }); + + return included; + } + + _createConditionRecord(condition, ruleId) { + let attributes = { + position: condition.position, + operator: condition.operator, + value: condition.value + }; + + let relationships = { + rule: {data: {type: 'rule', id: String(ruleId)}}, + field: condition.field ? {data: {type: 'field', id: String(condition.field)}} : null + }; + + return { + id: String(condition.id), + type: 'rulecondition', + attributes, + relationships + }; + } + + _createResultRecord(result, ruleId) { + let attributes = { + action: result.action + }; + + let relationships = { + rule: {data: {type: 'rule', id: String(ruleId)}}, + field: result.field ? {data: {type: 'field', id: String(result.field)}} : null, + option_group: result.option_group ? {data: {type: 'optiongroup', id: String(result.option_group)}} : null + }; + + return { + id: String(result.id), + type: 'ruleresult', + attributes, + relationships + }; + } + + serialize(snapshot, options) { + let json = super.serialize(...arguments); + + json.conditions = json.conditions || []; + json.results = json.results || []; + json.position = json.position || null; + + json.conditions = snapshot.record.conditionsArray.map(condition => this._serializeCondition(condition)); + json.results = snapshot.record.resultsArray.map(result => this._serializeResult(result)); + json.position = snapshot.record.rulePosition; + + return json; + } + + _serializeCondition(condition) { + let serializedCondition = { + position: condition.position, + operator: condition.operator, + value: condition.value ? condition.value : null, + field: condition.field ? String(condition.field.id) : null + }; + if (condition.id) { + serializedCondition.id = String(condition.id); + } + return serializedCondition; + } + + _serializeResult(result) { + let serializedResult = { + action: result.action, + field: result.field ? String(result.field.id) : null, + option_group: result.option_group ? String(result.option_group.id) : null + }; + if (result.id) { + serializedResult.id = String(result.id); } -}); + return serializedResult; + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/submissionsource.js b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/submissionsource.js deleted file mode 100644 index cee1124..0000000 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/submissionsource.js +++ /dev/null @@ -1,5 +0,0 @@ -import DRFSerializer from './drf'; - -export default DRFSerializer.extend({ - primaryKey: 'source' -}); diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/textfield.js b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/textfield.js new file mode 100644 index 0000000..2bfda6f --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/serializers/textfield.js @@ -0,0 +1,8 @@ +// serializers/text-field.js +import JSONSerializer from '@ember-data/serializer/json'; + +export default class TextFieldSerializer extends JSONSerializer { + normalizeResponse(store, primaryModelClass, payload, id, requestType) { + return super.normalizeResponse(store, primaryModelClass, payload, id, requestType); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/services/cookies.js b/formulaic/static/admin/formulaic/ember-formulaic/app/services/cookies.js new file mode 100644 index 0000000..c3948ce --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/services/cookies.js @@ -0,0 +1,33 @@ +import Service from '@ember/service'; +import { inject as service } from '@ember/service'; + +export default class CookieService extends Service { + @service('cookies') emberCookies; + + read(name) { + return this.emberCookies.read(name); + } + + write(name, value, options = {}) { + this.emberCookies.write(name, value, options); + } + + clear(name, options = {}) { + this.emberCookies.clear(name, options); + } + + exists(name) { + return this.read(name) !== undefined; + } + + readAll() { + return this.emberCookies.read(); + } + + clearAll(options = {}) { + let allCookies = this.readAll(); + for (let name in allCookies) { + this.clear(name, options); + } + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/services/field-service.js b/formulaic/static/admin/formulaic/ember-formulaic/app/services/field-service.js new file mode 100644 index 0000000..310932f --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/services/field-service.js @@ -0,0 +1,144 @@ +//services/field-service.js + +import {tracked} from '@glimmer/tracking'; +import Service from '@ember/service'; +import {action} from '@ember/object'; +import {inject as service} from '@ember/service'; +import {A} from '@ember/array'; + +export default class FieldService extends Service { + @service store; + @service router; + + @tracked currentFormRules = A([]); + @tracked currentFormFields = A([]); + @tracked currentForm = null; + @tracked currentField = null; + @tracked validators = {}; + + fieldTypes() { + return { + TEXTFIELD: 'textfield', + CHOICEFIELD: 'choicefield', + BOOLEANFIELD: 'booleanfield', + HIDDENFIELD: 'hiddenfield' + }; + } + + eq(a, b) { + return a === b; + } + + validatorFor(field) { + let validatorKey = field.toString(); + if (!this.validators[validatorKey]) { + this.validators[validatorKey] = field.validator; + } + return this.validators[validatorKey]; + } + + removeValidatorFor(field) { + let validatorKey = field.toString(); + if (this.validators[validatorKey]) { + this.validators[validatorKey].destroy(); + delete this.validators[validatorKey]; + } + } + + openEditField(context, field) { + this.currentField = field.get(field.model_class); + } + + closeEditField() { + this.currentField = null; + } + + createBaseField(subtype, model_class) { + const position = document.querySelectorAll('.field-sortable .item').length; + let field = this.store.createRecord('field', { + display_name: null, + data_name: null, + slug: null, + required: false, + help_text: null, + model_class: model_class, + position: position + 1, + css_class: null, + subtype: subtype, + form: this.currentForm, + }); + + return field; + } + + // this will return generic FieldModel ::: not specific model + createField(subtype, type) { + const validSubtypes = { + text: ["text", "textarea", "email", "phone_number", "integer", "full_name"], + choice: ["select", "radio_select", "checkbox_select_multiple", "select_multiple"], + boolean: ["checkbox"], + hidden: ["hidden"] + }; + + if (!validSubtypes[type].includes(subtype)) { + throw new Error(`Formulaic: ${type} field subtype \`${subtype}\` not implemented`); + } + + let field = this.createBaseField(subtype, (type + "field")); + + const commonProperties = { + display_name: field.display_name, + data_name: field.data_name, + slug: field.slug, + required: field.required, + help_text: field.help_text, + model_class: field.model_class, + position: field.position, + css_class: field.css_class, + subtype: field.subtype, + form: field.form + }; + + let specificField; + + switch (type) { + case 'text': + specificField = this.store.createRecord('textfield', commonProperties); + break; + case 'choice': + specificField = this.store.createRecord('choicefield', { + ...commonProperties, + minimum_selections: null, + maximum_selections: null, + option_list: null, + default_option: null, + default_options: [] + }); + break; + case 'boolean': + specificField = this.store.createRecord('booleanfield', commonProperties); + break; + case 'hidden': + specificField = this.store.createRecord('hiddenfield', {...commonProperties, value: ""}); + break; + } + + field[type + 'field'] = specificField; + + this.currentFormFields.pushObject(field); + + return field; + } + + @action + refreshCurrentRoute(currentRouteName) { + let route = this.router._router._routerMicrolib.getRoute(currentRouteName); + if (route) { + route.refresh(); + } + } + + clearFields() { + this.currentFormFields.clear(); + } +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/styles/_cutsom_bootstrap.scss b/formulaic/static/admin/formulaic/ember-formulaic/app/styles/_cutsom_bootstrap.scss new file mode 100644 index 0000000..6990cee --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/styles/_cutsom_bootstrap.scss @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.4.1 (https://getbootstrap.com/) + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;-moz-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:"Glyphicons Halflings";src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format("embedded-opentype"),url(../fonts/glyphicons-halflings-regular.woff2) format("woff2"),url(../fonts/glyphicons-halflings-regular.woff) format("woff"),url(../fonts/glyphicons-halflings-regular.ttf) format("truetype"),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format("svg")}.glyphicon{position:relative;top:1px;display:inline-block;font-family:"Glyphicons Halflings";font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:"\2014 \00A0"}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:""}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:"\00A0 \2014"}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.row-no-gutters{margin-right:0;margin-left:0}.row-no-gutters [class*=col-]{padding-right:0;padding-left:0}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;appearance:none}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s,-webkit-box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],.input-group-sm input[type=time],input[type=date].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm,input[type=time].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],.input-group-lg input[type=time],input[type=date].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg,input[type=time].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);opacity:.65;-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;background-image:none;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;background-image:none;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;background-image:none;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;background-image:none;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;background-image:none;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;background-image:none;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-right:15px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-right:-15px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out,-o-transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:400;line-height:1.42857143;line-break:auto;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;font-size:12px;filter:alpha(opacity=0);opacity:0}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:400;line-height:1.42857143;line-break:auto;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;font-size:14px;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover>.arrow{border-width:11px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out,-o-transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);left:0}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);left:0}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;outline:0;filter:alpha(opacity=90);opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:"\2039"}.carousel-control .icon-next:before{content:"\203a"}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} +/*# sourceMappingURL=bootstrap.min.css.map */ diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/styles/app.less b/formulaic/static/admin/formulaic/ember-formulaic/app/styles/app.less deleted file mode 100644 index ee2ef3c..0000000 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/styles/app.less +++ /dev/null @@ -1,306 +0,0 @@ -.formulaic-bootstrap { - @import 'bootstrap'; -} - -.formulaic-bootstrap { - /* Basic Overrides */ - h1, h2, h3, h4 { - padding:0; - } - button { - width:auto; - height:auto; - } - - - h1 { - margin: 20px 0px 10px; - font-weight: bold; - line-height: 24px; - font-size:20px; - } - - .formulaic-main { - margin: 0px; - } - - .formulaic-row { - //overflow:hidden; - } - .formulaic-row + .formulaic-row { - padding-top: 20px; - clear:both; - } - - .preview-column { - border: 1px solid #ccc; - border-radius: 5px; - //overflow: hidden; - background-color: #eee; - padding-bottom:20px; - } - - .preview-column table { - background-color:#fff; - } - - .preview-column h2, - .edit-column h2 { - padding: 5px 20px 4px; - margin: 0 -15px 20px; - font-size:13px; - line-height:18px; - font-weight:bold; - text-shadow: 0px 1px 0px #F5F5F5; - border-bottom: 1px solid #CCC; - border-top-left-radius: 3px; - border-top-right-radius: 3px; - background-size: 100% auto; - background-image: linear-gradient(#E5E5E5, #DBDBDB); - } - .edit-column h2 { - margin: 0 -20px 20px; - } - - .edit-fields { - min-height: 640px; - } - - .edit-rules .preview-column, - .edit-fields .preview-column { - padding-bottom:0; - } - - .edit-column { - border: 1px solid #ccc; - border-radius: 5px; - overflow: hidden; - background-color: #eee; - padding: 0 20px 20px; - width:300px; - } - .edit-column h2 { -// background-image: linear-gradient(#c7c7c7, #666666); - } - .edit-column label { - display: block; - } - .edit-column .btn { - margin-top:10px; - } - .edit-column .extras { - padding: 0 20px 10px; - border: 1px solid #ccc; - border-radius: 3px; - margin: 10px 0px 0px; - } - .edit-column .extras h4 { - //font-size: 12px; - //margin: 0 0 10px; - //font-weight: bold; - color: #aaa; - padding: 5px 20px 4px; - margin: 0 -20px 10px; - font-size: 13px; - line-height: 18px; - font-weight: bold; - text-shadow: 0px 1px 0px #F5F5F5; - border-bottom: 1px solid #CCC; - border-top-left-radius: 3px; - border-top-right-radius: 3px; - //background-size: 100% auto; - //background-image: linear-gradient(#E5E5E5, #DBDBDB); - } - .edit-column .extras label { - font-weight:normal; - color: #aaa; - } - .edit-column.affix { - top: 80px; - } - .edit-column.affix-bottom { - position:fixed; - top:80px; - } - - /* form index */ - .edit-menu { - padding-bottom:0; - } - .edit-menu h2 { - margin-bottom: 0; - } - .edit-menu.loading { - min-height:300px; - } - .edit-menu-item { - padding-top: 5px; - padding-bottom: 4px; - //margin: 0; - font-weight: bold; - box-sizing: border-box; - border-top: 1px solid #FFF; - border-bottom: 1px solid #DDD; - clear:both; - overflow:hidden; - } - .edit-menu-item label { - line-height: 18px; - margin:0; - padding-top: 6px; - } - .edit-menu-item a { - display:inline-block; - } - .edit-menu-item a:hover { - color:#000; - text-decoration: none; - } - .edit-menu-controls { - float:right; - } - .edit-menu-controls a + a { - margin-left:10px; - } - - .formulaic-controls { - background-color: #dfdfdf; - border-top: 1px solid #FFF; - border-bottom-left-radius: 3px; - border-bottom-right-radius: 3px; - overflow: hidden; - padding-top: 5px; - padding-bottom: 5px; - clear:both; - } - - .custom-edit-block { - border-bottom: 1px solid #CCC; - margin: 0px -15px; - overflow: hidden; - } - .edit-fields .custom-edit-block { - padding: 0 20px; - } - - .rule-list { - overflow:hidden; - float:none; - } - - .empty { - color:#aaa; - } - - .field-preview { - border: 1px solid #ccc; - padding-top: 10px; - padding-bottom: 15px; - position: relative; - } - .field-preview.editing, - .field-preview.editing:hover { - border: 1px solid #999; - background-color: #ccc; - } - - .field-preview.warning, - .field-preview.warning:hover { - background-color: #FCF8E3; - } - - .rule-conditions li + li::before { - display: block; - text-align: center; - color: #aaa; - } - .rule-conditions li + li::before { - content: 'and'; - } - .rule-conditions.or li + li::before { - content: 'or'; - } - .rule-conditions li > div, - .rule-results li > div { - padding:3px; - } - .rule-conditions li > div.warning, - .rule-results li > div.warning { - background-color: #FCF8E3; - } - - .form-control.text-block { - height: auto; - } - - .formulaic-navbar .navbar-text { - padding-right:10px; - } - .formulaic-filters { - padding-top:9px; - } - .formulaic-filters-select { - width: 200px; - display: inline-block; - } - .formulaic-next-prev { - padding:0 10px 0 0; - } - - .edit-column .wysiwyg-toggle { - font-size: 10px; - position: absolute; - right: 0; - margin: 0; - padding: 0; - font-weight: bold; - } - - .textfield-container { - position: relative; - } - - .link-disabled, - .link-disabled:focus { - color: #999; - cursor: not-allowed; - text-decoration: none; - } -} - - -.preview-column .item { - background-color:#eee; - cursor:pointer; -} -.preview-column .item:hover { - background-color:#e0e0e0; -} -.field-selector { - -} -.ui-sortable-placeholder { - background:url('images/bg-stripes.png') repeat !important; - visibility: visible !important; - /*opacity: 0.1;*/ - /*min-height:100px;*/ -} - -.controls .glyphicon { - font-size:21px; -} - -.field-preview .controls { - position:absolute; - right:15px; - top:15px; - z-index: 10; -} - -.data-name { - display: inline-block; - margin-left: 50px; - color: #aaa; - position: absolute; - right: 80px; -} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/styles/app.scss b/formulaic/static/admin/formulaic/ember-formulaic/app/styles/app.scss new file mode 100644 index 0000000..dec9b88 --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/styles/app.scss @@ -0,0 +1,346 @@ +.formulaic-bootstrap { + @import 'cutsom_bootstrap'; +} + +.formulaic-bootstrap { + /* Basic Overrides */ + h1, h2, h3, h4 { + padding: 0; + } + + button { + width: auto; + height: auto; + } + + + h1 { + margin: 20px 0px 10px; + font-weight: bold; + line-height: 24px; + font-size: 20px; + } + + .formulaic-main { + margin: 0px; + } + + .formulaic-row { + //overflow:hidden; + } + + .formulaic-row + .formulaic-row { + padding-top: 20px; + clear: both; + } + + .preview-column { + border: 1px solid #ccc; + border-radius: 5px; + //overflow: hidden; + background-color: #eee; + padding-bottom: 20px; + } + + .preview-column table { + background-color: #fff; + } + + .preview-column h2, + .edit-column h2 { + padding: 5px 20px 4px; + margin: 0 -15px 20px; + font-size: 13px; + line-height: 18px; + font-weight: bold; + text-shadow: 0px 1px 0px #F5F5F5; + border-bottom: 1px solid #CCC; + border-top-left-radius: 3px; + border-top-right-radius: 3px; + background-size: 100% auto; + background-image: linear-gradient(#E5E5E5, #DBDBDB); + } + + .edit-column h2 { + margin: 0 -20px 20px; + } + + .edit-fields { + min-height: 640px; + } + + .edit-rules .preview-column, + .edit-fields .preview-column { + padding-bottom: 0; + } + + .edit-column { + border: 1px solid #ccc; + border-radius: 5px; + overflow: hidden; + background-color: #eee; + padding: 0 20px 20px; + width: 300px; + } + + .edit-column h2 { + // background-image: linear-gradient(#c7c7c7, #666666); + } + + .edit-column label { + display: block; + } + + .edit-column .btn { + margin-top: 10px; + } + + .edit-column .extras { + padding: 0 20px 10px; + border: 1px solid #ccc; + border-radius: 3px; + margin: 10px 0px 0px; + } + + .edit-column .extras h4 { + //font-size: 12px; + //margin: 0 0 10px; + //font-weight: bold; + color: #aaa; + padding: 5px 20px 4px; + margin: 0 -20px 10px; + font-size: 13px; + line-height: 18px; + font-weight: bold; + text-shadow: 0px 1px 0px #F5F5F5; + border-bottom: 1px solid #CCC; + border-top-left-radius: 3px; + border-top-right-radius: 3px; + //background-size: 100% auto; + //background-image: linear-gradient(#E5E5E5, #DBDBDB); + } + + .edit-column .extras label { + font-weight: normal; + color: #aaa; + } + + .edit-column.affix { + top: 80px; + } + + .edit-column.affix-bottom { + position: fixed; + top: 80px; + } + + /* form index */ + .edit-menu { + padding-bottom: 0; + } + + .edit-menu h2 { + margin-bottom: 0; + } + + .edit-menu.loading { + min-height: 300px; + } + + .edit-menu-item { + padding-top: 5px; + padding-bottom: 4px; + //margin: 0; + font-weight: bold; + box-sizing: border-box; + border-top: 1px solid #FFF; + border-bottom: 1px solid #DDD; + clear: both; + overflow: hidden; + } + + .edit-menu-item label { + line-height: 18px; + margin: 0; + padding-top: 6px; + } + + .edit-menu-item a { + display: inline-block; + } + + .edit-menu-item a:hover { + color: #000; + text-decoration: none; + } + + .edit-menu-controls { + float: right; + } + + .edit-menu-controls a + a { + margin-left: 10px; + } + + .formulaic-controls { + background-color: #dfdfdf; + border-top: 1px solid #FFF; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + overflow: hidden; + padding-top: 5px; + padding-bottom: 5px; + clear: both; + } + + .custom-edit-block { + border-bottom: 1px solid #CCC; + margin: 0px -15px; + overflow: hidden; + } + + .edit-fields .custom-edit-block { + padding: 0 20px; + } + + .rule-list { + overflow: hidden; + float: none; + } + + .empty { + color: #aaa; + } + + .field-preview { + border: 1px solid #ccc; + padding-top: 10px; + padding-bottom: 15px; + position: relative; + } + + .field-preview.editing, + .field-preview.editing:hover { + border: 1px solid #999; + background-color: #ccc; + } + + .field-preview.warning, + .field-preview.warning:hover { + background-color: #FCF8E3; + } + + .rule-conditions li + li::before { + display: block; + text-align: center; + color: #aaa; + } + + .rule-conditions li + li::before { + content: 'and'; + } + + .rule-conditions.or li + li::before { + content: 'or'; + } + + .rule-conditions li > div, + .rule-results li > div { + padding: 3px; + } + + .rule-conditions li > div.warning, + .rule-results li > div.warning { + background-color: #FCF8E3; + } + + .form-control.text-block { + height: auto; + } + + .formulaic-navbar .navbar-text { + padding-right: 10px; + } + + .formulaic-filters { + padding-top: 9px; + } + + .formulaic-filters-select { + width: 200px; + display: inline-block; + } + + .formulaic-next-prev { + padding: 0 10px 0 0; + } + + .edit-column .wysiwyg-toggle { + font-size: 10px; + position: absolute; + right: 0; + margin: 0; + padding: 0; + font-weight: bold; + } + + .textfield-container { + position: relative; + } + + .link-disabled, + .link-disabled:focus { + color: #999; + cursor: not-allowed; + text-decoration: none; + } +} + + +.preview-column .item { + background-color: #eee; + cursor: pointer; +} + +.preview-column .item:hover { + background-color: #e0e0e0; +} + +.field-selector { + +} + +.ui-sortable-placeholder { + background: url('images/bg-stripes.png') repeat !important; + visibility: visible !important; + height: auto; +} + +.controls .glyphicon { + font-size: 21px; +} + +.field-preview .controls { + position: absolute; + right: 15px; + top: 15px; + z-index: 10; +} + +.data-name { + display: inline-block; + margin-left: 50px; + color: #aaa; + position: absolute; + right: 80px; +} + +ul > li +{ + list-style-type: none; +} + +.field-preview .dragging { + background-color: #000000; /* Change this to your preferred color */ + opacity: 1; /* Slightly transparent */ +} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/base-sortable.hbs b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/base-sortable.hbs index cc95f24..dc8cb6e 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/base-sortable.hbs +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/base-sortable.hbs @@ -1,2 +1,12 @@ -{{yield}} -base-sortable.hbs + +
+ + {{#each @items as |item|}} + +
+ {{yield item}} +
+
+ {{/each}} +
+
diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields.hbs b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields.hbs new file mode 100644 index 0000000..1de73cd --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields.hbs @@ -0,0 +1,42 @@ + + +
+
+

Editing Fields

+
+ {{!-- Ensure SortableFields component is available --}} + +
+ +
+
+ {{!-- Save & Continue Editing Button --}} + + {{!-- Save Button --}} + + {{!-- Close Button --}} + +
+
+
+ +
+
+ +
+
+
diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields/booleanfield.hbs b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields/booleanfield.hbs new file mode 100644 index 0000000..ce2fe0e --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields/booleanfield.hbs @@ -0,0 +1,54 @@ + + +

Edit '{{this.subtypeName}}' field

+
+ + +
+
+ +
+
+ +
+ + + +
+

Extras

+ + +
+ + diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields/choicefield.hbs b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields/choicefield.hbs new file mode 100644 index 0000000..17bbed1 --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields/choicefield.hbs @@ -0,0 +1,137 @@ + + +

Edit '{{this.subtypeName}}' field

+
+ + +
+
+ +
+
+ +
+ + +
+ +
+{{#if this.hasOptionGroups}} + +{{/if}} + + +{{#if this.supportsMultiValue}} + + +{{else}} + +{{/if}} + +
+

Extras

+ + +
+ + diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields/field.hbs b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields/field.hbs new file mode 100644 index 0000000..28521d5 --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields/field.hbs @@ -0,0 +1,69 @@ + + +{{#each this.model as |rule|}} +
+ +
    +
  • + +
  • +
+
+ {{#if rule.hasMultipleConditions}} +
+ + +
+ {{/if}} + + +

+ Conditions + +

+
    + {{#each rule.conditions as |condition|}} +
  • + + + {{#if condition.allFieldsReady}} + + + +
  • + {{/each}} +
+ + +

+ Results + +

+
    + {{#each rule.results as |result|}} +
  • + + + {{else}} + Loading + {{/if}} +
  • + {{/each}} +
+
+
+{{/each}} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields/hiddenfield.hbs b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields/hiddenfield.hbs new file mode 100644 index 0000000..d3fdd99 --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields/hiddenfield.hbs @@ -0,0 +1,23 @@ + + +

Edit '{{this.subtypeName}}' field

+
+ +
+
+ +
+ + + diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields/index.hbs b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields/index.hbs new file mode 100644 index 0000000..1c402cf --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields/index.hbs @@ -0,0 +1,18 @@ + + +

Add Fields

+

Basic

+ + + + + + + + + +

Typed

+ + + + diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields/textfield.hbs b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields/textfield.hbs new file mode 100644 index 0000000..b3c93b4 --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/fields/textfield.hbs @@ -0,0 +1,54 @@ + + +

Edit '{{this.subtypeName}}' field

+
+ + +
+
+ +
+
+ +
+ + +
+

Extras

+ + +
+ + diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/index.hbs b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/index.hbs new file mode 100644 index 0000000..c9f86a5 --- /dev/null +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/components/form/index.hbs @@ -0,0 +1,100 @@ + + +
+
+

Modify Form

+ {{#if this.inEditMode}} +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ {{#if this.privacyPoliciesReady}} + + {{else}} +

Loading ...

+ {{/if}} +
+ +
+
+
+ +
+
+ diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form.hbs b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form.hbs index bb5e64f..01cc3f9 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form.hbs +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form.hbs @@ -1,7 +1,10 @@ + +
-

{{model.name}}

-

{{model.slug}}

-
+

{{this.model.name}}

+

{{this.model.slug}}

+
{{outlet}} + diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields.hbs b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields.hbs index e13b48e..61fa76a 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields.hbs +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields.hbs @@ -1,26 +1,3 @@ -
-
-

Editing Fields

-
- {{sortable-fields items=activeFields targetController=this}} -
+ -
-
- - - -
-
-
- -
-
- {{outlet "sidebar"}} -
-
-
+ \ No newline at end of file diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/booleanfield.hbs b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/booleanfield.hbs index 8b1f9d9..9258150 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/booleanfield.hbs +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/booleanfield.hbs @@ -1,7 +1,9 @@ -

Edit '{{subtypeName}}' field

-
-
-
+
-
+
@@ -41,12 +43,12 @@

Extras

- + diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/choicefield.hbs b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/choicefield.hbs index be72e61..32d1c90 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/choicefield.hbs +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/choicefield.hbs @@ -1,7 +1,9 @@ -

Edit '{{subtypeName}}' field

-
-
-
+
-
+
-
+
-{{#if hasOptionGroups}} +{{#if this.hasOptionGroups}}
- + diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/field.hbs b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/field.hbs index 4d6732d..28521d5 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/field.hbs +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/field.hbs @@ -1,9 +1,11 @@ -{{#each rule in model itemController="rule"}} -
- {{input type="hidden" value=rule.position class="position"}} + + +{{#each this.model as |rule|}} +
+
  • -
  • @@ -11,45 +13,31 @@
    {{#if rule.hasMultipleConditions}}
    - - + +
    {{/if}}

    Conditions -

    -
      - {{#each condition in rule.conditions itemController="rulecondition"}} +
        + {{#each rule.conditions as |condition|}}
      • - - - - {{input type="hidden" value=condition.position class="condition-position"}} + {{#if condition.allFieldsReady}} - {{view "select" - selection=condition.field.content - content=condition.allFields - prompt="Choose Field" - optionValuePath="content" - optionLabelPath="content.name" - class="form-control input-sm"}} + + +
      • @@ -59,28 +47,17 @@

        Results -

          - {{#each result in rule.results itemController="ruleresult"}} + {{#each rule.results as |result|}}
        • - {{view "select" - value=result.action - content=result.availableActions - optionValuePath="content.value" - optionLabelPath="content.name" - class="form-control input-sm"}} + {{else}} Loading {{/if}} @@ -89,4 +66,4 @@
-{{/each}} \ No newline at end of file +{{/each}} diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/hiddenfield.hbs b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/hiddenfield.hbs index c19e0ec..f325dcf 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/hiddenfield.hbs +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/hiddenfield.hbs @@ -1,19 +1,21 @@ -

Edit '{{subtypeName}}' field

-
+ + +

Edit '{{this.subtypeName}}' field

+
-
+
- + diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/index.hbs b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/index.hbs index e7dbf89..b536e33 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/index.hbs +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/index.hbs @@ -1,16 +1,18 @@ + +

Add Fields

Basic

- - - - - - - - + + + + + + + +

Typed

- - - - + + + + diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/textfield.hbs b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/textfield.hbs index 7e287f5..10cd815 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/textfield.hbs +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/fields/textfield.hbs @@ -1,48 +1,3 @@ -

Edit '{{subtypeName}}' field

-
- - -
-
- -
-
- -
- + -
-

Extras

- - -
- - + \ No newline at end of file diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/index.hbs b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/index.hbs index 43fb934..2c2cde1 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/index.hbs +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/index.hbs @@ -1,102 +1,2 @@ -
-
-

Modify Form

- {{#if inEditMode}} -
-
- -
-
- {{input type="text" id="form-name" placeholder="" value=model.name class="form-control input-sm"}} -
-
-
-
- -
-
- {{input type="text" id="form-slug" placeholder="" value=model.slug class="form-control input-sm"}} -
-
-
-
- -
-
- {{#if privacyPoliciesReady}} - {{#x-select value=model.privacy_policy.content action=(action 'privacyPolicyChanged') id="form-privacy-policy" class="form-control input-sm" as |xs|}} - - {{#each privacyPolicies as |policy|}} - {{#xs.option value=policy}}{{policy.name}}{{/xs.option}} - {{/each}} - {{/x-select}} - {{else}} - Loading - {{/if}} -
-
-
-
- -
-
- {{textarea id="form-success-message" placeholder="" value=model.success_message rows=6 class="form-control input-sm text-block"}} -
-
- -
-
- - -
-
- {{else}} - - {{/if}} -
-
+{{!-- app/templates/form/index.hbs --}} + diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/rules.hbs b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/rules.hbs index 2c66ad9..94bf0fd 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/rules.hbs +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/rules.hbs @@ -1,26 +1,4 @@ -
-
-

Editing Rules

+ - {{sortable-rules items=activeRules targetController=this}} + -
- -
- -
-
- - - -
-
-
-
diff --git a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/submissions.hbs b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/submissions.hbs index 9fa29b6..f0f1b75 100644 --- a/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/submissions.hbs +++ b/formulaic/static/admin/formulaic/ember-formulaic/app/templates/form/submissions.hbs @@ -1,28 +1,30 @@ + +

View Submissions

- {{#if hasSubmissions}} + {{#if this.hasSubmissions}}
+ {{/let}} + */ + { + "id": "fnLsQzYK", + "block": "[[[44,[[50,[28,[37,2],[[28,[37,3],[[30,1],[50,\"bs-accordion/item/title\",0,null,null]],null]],null],0,null,[[\"collapsed\",\"disabled\",\"onClick\"],[[30,0,[\"collapsed\"]],[30,2],[28,[37,4],[[28,[37,3],[[30,3],[28,[37,5],null,null]],null],[30,0,[\"value\"]]],null]]]],[50,[28,[37,2],[[28,[37,3],[[30,4],[50,\"bs-accordion/item/body\",0,null,null]],null]],null],0,null,[[\"collapsed\"],[[30,0,[\"collapsed\"]]]]],[28,[37,6],null,null],[28,[37,6],null,null]],[[[1,\" \"],[11,0],[16,0,[29,[[52,[30,2],\"disabled\"],\" \",[30,0,[\"typeClass\"]],\" \",[27],\" \",\"accordion-item\"]]],[17,9],[12],[1,\"\\n\"],[41,[49,[30,11]],[[[1,\" \"],[18,11,[[28,[37,11],null,[[\"title\",\"body\"],[[30,5],[30,6]]]]]],[1,\"\\n\"]],[]],[[[1,\" \"],[8,[30,5],[[16,1,[30,7]]],[[\"@controls\"],[[30,8]]],[[\"default\"],[[[[1,\"\\n \"],[1,[30,10]],[1,\"\\n \"]],[]]]]],[1,\"\\n \"],[8,[30,6],null,[[\"@collapsableId\",\"@describedby\"],[[30,8],[30,7]]],[[\"default\"],[[[[1,\"\\n \"],[18,11,null],[1,\"\\n \"]],[]]]]],[1,\"\\n\"]],[]]],[1,\" \"],[13],[1,\"\\n\"]],[5,6,7,8]]]],[\"@titleComponent\",\"@disabled\",\"@onClick\",\"@bodyComponent\",\"Title\",\"Body\",\"titleId\",\"collapsableId\",\"&attrs\",\"@title\",\"&default\"],false,[\"let\",\"component\",\"ensure-safe-component\",\"bs-default\",\"fn\",\"bs-noop\",\"unique-id\",\"div\",\"if\",\"has-block-params\",\"yield\",\"hash\"]]", + "moduleName": "ember-bootstrap/components/bs-accordion/item.hbs", + "isStrictMode": false + }); + /** + A collapsible/expandable item within an accordion + + See [Components.Accordion](Components.Accordion.html) for examples. + + @class AccordionItem + @namespace Components + @extends Ember.Component + @public + */ + let AccordionItem = _exports.default = (_class = class AccordionItem extends _component2.default { + constructor(...args) { + super(...args); + /** + * The title of the accordion item, displayed as a .panel-title element + * + * @property title + * @type string + * @public + */ + /** + * The value of the accordion item, which is used as the value of the `selected` property of the parent [Components.Accordion](Components.Accordion.html) component + * + * @property value + * @public + */ + _initializerDefineProperty(this, "value", _descriptor, this); + /** + * @property disabled + * @type boolean + * @public + */ + /** + * Property for type styling + * + * For the available types see the [Bootstrap docs](https://getbootstrap.com/docs/4.3/components/navbar/#color-schemes) + * + * @property type + * @type String + * @default 'default' + * @public + */ + _initializerDefineProperty(this, "type", _descriptor2, this); + } /** - For symmetry, a record can be deleted via the store. - Example - ```javascript - let post = store.createRecord('post', { - title: 'Rails is omakase' - }); - store.deleteRecord(post); - ``` - @method deleteRecord - @param {DS.Model} record - */ - deleteRecord: function deleteRecord(record) { - record.deleteRecord(); - }, - + * @property selected + * @private + */ /** - For symmetry, a record can be unloaded via the store. - This will cause the record to be destroyed and freed up for garbage collection. - Example - ```javascript - store.findRecord('post', 1).then(function(post) { - store.unloadRecord(post); - }); - ``` - @method unloadRecord - @param {DS.Model} record - */ - unloadRecord: function unloadRecord(record) { - record.unloadRecord(); - }, - + * @property titleComponent + * @type {String} + * @private + */ - // ................ - // . FIND RECORDS . - // ................ + /** + * @property bodyComponent + * @type {String} + * @private + */ /** - @method find - @param {String} modelName - @param {String|Integer} id - @param {Object} options - @return {Promise} promise - @private - */ - find: function find(modelName, id, options) { - // The default `model` hook in Ember.Route calls `find(modelName, id)`, - // that's why we have to keep this method around even though `findRecord` is - // the public way to get a record by modelName and id. - (0, _debug.assert)('Using store.find(type) has been removed. Use store.findAll(modelName) to retrieve all records for a given type.', arguments.length !== 1); - (0, _debug.assert)('Calling store.find(modelName, id, { preload: preload }) is no longer supported. Use store.findRecord(modelName, id, { preload: preload }) instead.', !options); - (0, _debug.assert)('You need to pass the model name and id to the store\'s find method', arguments.length === 2); - (0, _debug.assert)('You cannot pass \'' + id + '\' as id to the store\'s find method', typeof id === 'string' || typeof id === 'number'); - (0, _debug.assert)('Calling store.find() with a query object is no longer supported. Use store.query() instead.', (typeof id === 'undefined' ? 'undefined' : _typeof(id)) !== 'object'); - (0, _debug.assert)('Passing classes to store methods has been removed. Please pass a dasherized string instead of ' + modelName, typeof modelName === 'string'); - - var normalizedModelName = (0, _normalizeModelName.default)(modelName); - - return this.findRecord(normalizedModelName, id); - }, + * @property collapsed + * @type boolean + * @readonly + * @private + */ + get collapsed() { + return this.value !== this.args.selected; + } + get typeClass() { + return `bg-${this.type}`; + } + /** + * Reference to the parent `Components.Accordion` class. + * + * @property accordion + * @private + */ /** - This method returns a record for a given type and id combination. - The `findRecord` method will always resolve its promise with the same - object for a given type and `id`. - The `findRecord` method will always return a **promise** that will be - resolved with the record. - Example - ```app/routes/post.js - import Ember from 'ember'; - export default Ember.Route.extend({ - model(params) { - return this.store.findRecord('post', params.post_id); - } - }); - ``` - If the record is not yet available, the store will ask the adapter's `find` - method to find the necessary data. If the record is already present in the - store, it depends on the reload behavior _when_ the returned promise - resolves. - ### Preloading - You can optionally `preload` specific attributes and relationships that you know of - by passing them via the passed `options`. - For example, if your Ember route looks like `/posts/1/comments/2` and your API route - for the comment also looks like `/posts/1/comments/2` if you want to fetch the comment - without fetching the post you can pass in the post to the `findRecord` call: - ```javascript - store.findRecord('comment', 2, { preload: { post: 1 } }); - ``` - If you have access to the post model you can also pass the model itself: - ```javascript - store.findRecord('post', 1).then(function (myPostModel) { - store.findRecord('comment', 2, { post: myPostModel }); - }); - ``` - ### Reloading - The reload behavior is configured either via the passed `options` hash or - the result of the adapter's `shouldReloadRecord`. - If `{ reload: true }` is passed or `adapter.shouldReloadRecord` evaluates - to `true`, then the returned promise resolves once the adapter returns - data, regardless if the requested record is already in the store: - ```js - store.push({ - data: { - id: 1, - type: 'post', - revision: 1 - } - }); - // adapter#findRecord resolves with - // [ - // { - // id: 1, - // type: 'post', - // revision: 2 - // } - // ] - store.findRecord('post', 1, { reload: true }).then(function(post) { - post.get('revision'); // 2 - }); - ``` - If no reload is indicated via the abovementioned ways, then the promise - immediately resolves with the cached version in the store. - ### Background Reloading - Optionally, if `adapter.shouldBackgroundReloadRecord` evaluates to `true`, - then a background reload is started, which updates the records' data, once - it is available: - ```js - // app/adapters/post.js - import ApplicationAdapter from "./application"; - export default ApplicationAdapter.extend({ - shouldReloadRecord(store, snapshot) { - return false; - }, - shouldBackgroundReloadRecord(store, snapshot) { - return true; - } - }); - // ... - store.push({ - data: { - id: 1, - type: 'post', - revision: 1 - } - }); - let blogPost = store.findRecord('post', 1).then(function(post) { - post.get('revision'); // 1 - }); - // later, once adapter#findRecord resolved with - // [ - // { - // id: 1, - // type: 'post', - // revision: 2 - // } - // ] - blogPost.get('revision'); // 2 - ``` - If you would like to force or prevent background reloading, you can set a - boolean value for `backgroundReload` in the options object for - `findRecord`. - ```app/routes/post/edit.js - import Ember from 'ember'; - export default Ember.Route.extend({ - model(params) { - return this.store.findRecord('post', params.post_id, { backgroundReload: false }); - } - }); - ``` - If you pass an object on the `adapterOptions` property of the options - argument it will be passed to you adapter via the snapshot - ```app/routes/post/edit.js - import Ember from 'ember'; - export default Ember.Route.extend({ - model(params) { - return this.store.findRecord('post', params.post_id, { - adapterOptions: { subscribe: false } - }); - } - }); - ``` - ```app/adapters/post.js - import MyCustomAdapter from './custom-adapter'; - export default MyCustomAdapter.extend({ - findRecord(store, type, id, snapshot) { - if (snapshot.adapterOptions.subscribe) { - // ... - } - // ... - } - }); - ``` - See [peekRecord](#method_peekRecord) to get the cached version of a record. - ### Retrieving Related Model Records - If you use an adapter such as Ember's default - [`JSONAPIAdapter`](http://emberjs.com/api/data/classes/DS.JSONAPIAdapter.html) - that supports the [JSON API specification](http://jsonapi.org/) and if your server - endpoint supports the use of an - ['include' query parameter](http://jsonapi.org/format/#fetching-includes), - you can use `findRecord()` to automatically retrieve additional records related to - the one you request by supplying an `include` parameter in the `options` object. - For example, given a `post` model that has a `hasMany` relationship with a `comment` - model, when we retrieve a specific post we can have the server also return that post's - comments in the same request: - ```app/routes/post.js - import Ember from 'ember'; - export default Ember.Route.extend({ - model(params) { - return this.store.findRecord('post', params.post_id, { include: 'comments' }); - } - }); - ``` - In this case, the post's comments would then be available in your template as - `model.comments`. - Multiple relationships can be requested using an `include` parameter consisting of a - comma-separated list (without white-space) while nested relationships can be specified - using a dot-separated sequence of relationship names. So to request both the post's - comments and the authors of those comments the request would look like this: - ```app/routes/post.js - import Ember from 'ember'; - export default Ember.Route.extend({ - model(params) { - return this.store.findRecord('post', params.post_id, { include: 'comments,comments.author' }); - } - }); - ``` - @since 1.13.0 - @method findRecord - @param {String} modelName - @param {(String|Integer)} id - @param {Object} options - @return {Promise} promise - */ - findRecord: function findRecord(modelName, id, options) { - (0, _debug.assert)('You need to pass a model name to the store\'s findRecord method', isPresent(modelName)); - (0, _debug.assert)('Passing classes to store methods has been removed. Please pass a dasherized string instead of ' + modelName, typeof modelName === 'string'); - (0, _debug.assert)(badIdFormatAssertion, typeof id === 'string' && id.length > 0 || typeof id === 'number' && !isNaN(id)); + * @event onClick + * @public + */ + }, (_descriptor = _applyDecoratedDescriptor(_class.prototype, "value", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return (0, _internals.guidFor)(this); + } + }), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "type", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return 'default'; + } + })), _class); + (0, _component.setComponentTemplate)(__COLOCATED_TEMPLATE__, AccordionItem); +}); +;define("ember-bootstrap/components/bs-accordion/item/body", ["exports", "@ember/component", "@ember/component/template-only", "@ember/template-factory"], function (_exports, _component, _templateOnly, _templateFactory) { + "use strict"; - var normalizedModelName = (0, _normalizeModelName.default)(modelName); + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + 0; //eaimeta@70e063a35619d71f0,"@ember/component/template-only",0,"@ember/template-factory",0,"@ember/component"eaimeta@70e063a35619d71f + const __COLOCATED_TEMPLATE__ = (0, _templateFactory.createTemplateFactory)( + /* + {{! @glint-nocheck }} + +
+ {{yield}} +
+
+ */ + { + "id": "4wRvHc6x", + "block": "[[[8,[39,0],[[24,0,\"accordion-collapse\"],[16,1,[30,1]],[16,\"aria-describedby\",[30,2]]],[[\"@collapsed\"],[[30,3]]],[[\"default\"],[[[[1,\"\\n \"],[10,0],[15,0,[29,[[27],\" \",\"accordion-body\"]]],[12],[1,\"\\n \"],[18,4,null],[1,\"\\n \"],[13],[1,\"\\n\"]],[]]]]]],[\"@collapsableId\",\"@describedby\",\"@collapsed\",\"&default\"],false,[\"bs-collapse\",\"div\",\"yield\"]]", + "moduleName": "ember-bootstrap/components/bs-accordion/item/body.hbs", + "isStrictMode": false + }); + /** + Component for an accordion item body. + + See [Components.Accordion](Components.Accordion.html) for examples. + + @class AccordionItemBody + @namespace Components + @extends Ember.Component + @public + */ - var internalModel = this._internalModelForId(normalizedModelName, id); - options = options || {}; + /** + * @property collapsed + * @type boolean + * @public + */ + var _default = _exports.default = (0, _component.setComponentTemplate)(__COLOCATED_TEMPLATE__, (0, _templateOnly.default)()); +}); +;define("ember-bootstrap/components/bs-accordion/item/title", ["exports", "@ember/component", "@ember/object", "@glimmer/component", "@ember/template-factory"], function (_exports, _component, _object, _component2, _templateFactory) { + "use strict"; - if (!this.hasRecordForId(normalizedModelName, id)) { - return this._findByInternalModel(internalModel, options); - } + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + var _class; + 0; //eaimeta@70e063a35619d71f0,"@ember/object",0,"@glimmer/component",0,"@ember/template-factory",0,"@ember/component"eaimeta@70e063a35619d71f + function _applyDecoratedDescriptor(i, e, r, n, l) { var a = {}; return Object.keys(n).forEach(function (i) { a[i] = n[i]; }), a.enumerable = !!a.enumerable, a.configurable = !!a.configurable, ("value" in a || a.initializer) && (a.writable = !0), a = r.slice().reverse().reduce(function (r, n) { return n(i, e, r) || r; }, a), l && void 0 !== a.initializer && (a.value = a.initializer ? a.initializer.call(l) : void 0, a.initializer = void 0), void 0 === a.initializer && (Object.defineProperty(i, e, a), a = null), a; } + const __COLOCATED_TEMPLATE__ = (0, _templateFactory.createTemplateFactory)( + /* + {{! @glint-nocheck }} + {{!-- template-lint-disable no-nested-interactive --}} + {{!-- @todo fix this, see https://github.com/kaliber5/ember-bootstrap/issues/999 --}} + {{#if (macroCondition (macroGetOwnConfig "isBS5"))}} +

+ +

+ {{else}} +
+

+ +

+
+ {{/if}} + + */ + { + "id": "vikJDvAP", + "block": "[[[1,\" \"],[11,\"h2\"],[24,0,\"accordion-header\"],[17,1],[12],[1,\"\\n \"],[11,\"button\"],[16,0,[29,[\"accordion-button \",[52,[30,2],\"disabled\"],\" \",[52,[30,3],\"collapsed\"]]]],[16,\"disabled\",[30,2]],[16,\"aria-controls\",[30,4]],[16,\"aria-expanded\",[52,[30,3],\"false\",\"true\"]],[24,4,\"button\"],[4,[38,3],[\"click\",[30,0,[\"handleClick\"]]],null],[12],[1,\"\\n \"],[18,5,null],[1,\"\\n \"],[13],[1,\"\\n \"],[13],[1,\"\\n\"]],[\"&attrs\",\"@disabled\",\"@collapsed\",\"@controls\",\"&default\"],false,[\"h2\",\"button\",\"if\",\"on\",\"yield\"]]", + "moduleName": "ember-bootstrap/components/bs-accordion/item/title.hbs", + "isStrictMode": false + }); - var fetchedInternalModel = this._findRecord(internalModel, options); + /** + Component for an accordion item title. + + See [Components.Accordion](Components.Accordion.html) for examples. + + @class AccordionItemTitle + @namespace Components + @extends Glimmer.Component + @public + */ + let AccordionItemTitle = _exports.default = (_class = class AccordionItemTitle extends _component2.default { + /** + * @property collapsed + * @type boolean + * @public + */ - return promiseRecord(fetchedInternalModel, 'DS: Store#findRecord ' + normalizedModelName + ' with id: ' + id); - }, - _findRecord: function _findRecord(internalModel, options) { - // Refetch if the reload option is passed - if (options.reload) { - return this._scheduleFetch(internalModel, options); - } + /** + * @property disabled + * @type boolean + * @private + */ - var snapshot = internalModel.createSnapshot(options); - var adapter = this.adapterFor(internalModel.modelName); + /** + * @event onClick + * @public + */ - // Refetch the record if the adapter thinks the record is stale - if (adapter.shouldReloadRecord(this, snapshot)) { - return this._scheduleFetch(internalModel, options); + handleClick(e) { + e.preventDefault(); + if (!this.args.disabled) { + this.args.onClick?.(); } + } + }, (_applyDecoratedDescriptor(_class.prototype, "handleClick", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "handleClick"), _class.prototype)), _class); + (0, _component.setComponentTemplate)(__COLOCATED_TEMPLATE__, AccordionItemTitle); +}); +;define("ember-bootstrap/components/bs-alert", ["exports", "@ember/component", "@ember/object", "@glimmer/component", "@glimmer/tracking", "@ember/runloop", "ember-bootstrap/utils/decorators/uses-transition", "ember-bootstrap/utils/decorators/arg", "@ember/template-factory"], function (_exports, _component, _object, _component2, _tracking, _runloop, _usesTransition, _arg, _templateFactory) { + "use strict"; - if (options.backgroundReload === false) { - return Promise.resolve(internalModel); - } + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + var _dec, _class, _descriptor, _descriptor2, _descriptor3, _descriptor4, _descriptor5, _descriptor6; + 0; //eaimeta@70e063a35619d71f0,"@ember/object",0,"@glimmer/component",0,"@glimmer/tracking",0,"@ember/runloop",0,"ember-bootstrap/utils/decorators/uses-transition",0,"ember-bootstrap/utils/decorators/arg",0,"@ember/template-factory",0,"@ember/component"eaimeta@70e063a35619d71f + function _initializerDefineProperty(e, i, r, l) { r && Object.defineProperty(e, i, { enumerable: r.enumerable, configurable: r.configurable, writable: r.writable, value: r.initializer ? r.initializer.call(l) : void 0 }); } + function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } + function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } + function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } + function _applyDecoratedDescriptor(i, e, r, n, l) { var a = {}; return Object.keys(n).forEach(function (i) { a[i] = n[i]; }), a.enumerable = !!a.enumerable, a.configurable = !!a.configurable, ("value" in a || a.initializer) && (a.writable = !0), a = r.slice().reverse().reduce(function (r, n) { return n(i, e, r) || r; }, a), l && void 0 !== a.initializer && (a.value = a.initializer ? a.initializer.call(l) : void 0, a.initializer = void 0), void 0 === a.initializer && (Object.defineProperty(i, e, a), a = null), a; } + function _initializerWarningHelper(r, e) { throw Error("Decorating class property failed. Please ensure that transform-class-properties is enabled and runs after the decorators transform."); } + const __COLOCATED_TEMPLATE__ = (0, _templateFactory.createTemplateFactory)( + /* + {{! @glint-nocheck }} +
+ {{#unless this.hidden}} + {{#if this.dismissible}} + + {{/if}} + + {{#if (has-block "header")}} + {{#let (element (bs-default @headerTag "h4")) as |Tag|}} + + {{yield to="header"}} + + {{/let}} + {{/if}} + + {{#if (has-block "body")}} + {{yield to="body"}} + {{else}} + {{yield}} + {{/if}} + {{/unless}} +
+ */ + { + "id": "SnJbgc4V", + "block": "[[[11,0],[16,0,[29,[[52,[51,[30,0,[\"hidden\"]]],\"alert\"],\" \",[52,[30,0,[\"fade\"]],\"fade\"],\" \",[52,[30,0,[\"dismissible\"]],\"alert-dismissible\"],\" \",[28,[37,3],[\"alert\",[30,1]],null],\" \",[52,[30,0,[\"showAlert\"]],\"show\"]]]],[17,2],[4,[38,4],[[30,0,[\"showOrHide\"]],[30,0,[\"_visible\"]]],null],[4,[38,4],[[30,0,[\"updateVisibility\"]],[30,3]],null],[12],[1,\"\\n\"],[41,[51,[30,0,[\"hidden\"]]],[[[41,[30,0,[\"dismissible\"]],[[[1,\" \"],[11,\"button\"],[24,0,\"btn-close\"],[24,\"aria-label\",\"Close\"],[24,4,\"button\"],[4,[38,6],[\"click\",[30,0,[\"dismiss\"]]],null],[12],[1,\"\\n \"],[1,\"\\n \"],[13],[1,\"\\n\"]],[]],null],[1,\"\\n\"],[41,[48,[30,6]],[[[44,[[28,[37,9],[[28,[37,10],[[30,4],\"h4\"],null]],null]],[[[1,\" \"],[8,[30,5],[[24,0,\"alert-heading\"]],null,[[\"default\"],[[[[1,\"\\n \"],[18,6,null],[1,\"\\n \"]],[]]]]],[1,\"\\n\"]],[5]]]],[]],null],[1,\"\\n\"],[41,[48,[30,7]],[[[1,\" \"],[18,7,null],[1,\"\\n\"]],[]],[[[1,\" \"],[18,8,null],[1,\"\\n\"]],[]]]],[]],null],[13]],[\"@type\",\"&attrs\",\"@visible\",\"@headerTag\",\"Tag\",\"&header\",\"&body\",\"&default\"],false,[\"div\",\"unless\",\"if\",\"bs-type-class\",\"did-update\",\"button\",\"on\",\"has-block\",\"let\",\"element\",\"bs-default\",\"yield\"]]", + "moduleName": "ember-bootstrap/components/bs-alert.hbs", + "isStrictMode": false + }); - // Trigger the background refetch if backgroundReload option is passed - if (options.backgroundReload || adapter.shouldBackgroundReloadRecord(this, snapshot)) { - this._scheduleFetch(internalModel, options); - } + /** + Implements [Bootstrap alerts](http://getbootstrap.com/components/#alerts) + + ### Usage + + By default, it is a user dismissible alert with a fade out animation, both of which can be disabled. Be sure to set the + `type` property for proper styling. + + ```hbs + + Well done! You successfully read this important alert message. + + ``` + + Optionally you can render a header for the alert using named blocks syntax: + + ```hbs + + <:header> + Well done! + + <:body> + You successfully read this important alert message. + + + ``` + + The header is rendered using a `

` element by default. You can customize + that one by setting `@headerTag` argument of ``. + + Using named block syntax as shown above may require installing + [ember-named-blocks-polyfill](https://github.com/ember-polyfills/ember-named-blocks-polyfill) + in your project depending on the Ember version used. + + *Note that only invoking the component in a template as shown above is considered part of its public API. Extending from it (subclassing) is generally not supported, and may break at any time.* + + @class Alert + @namespace Components + @extends Glimmer.Component + @public + */ + let Alert = _exports.default = (_dec = (0, _usesTransition.default)('fade'), (_class = class Alert extends _component2.default { + constructor(...args) { + super(...args); + /** + * A dismissible alert will have a close button in the upper right corner, that the user can click to dismiss + * the alert. + * + * @property dismissible + * @type boolean + * @default true + * @public + */ + _initializerDefineProperty(this, "dismissible", _descriptor, this); + /** + * If true the alert is completely hidden. Will be set when the fade animation has finished. + * + * @property hidden + * @type boolean + * @default false + * @readonly + * @private + */ + _initializerDefineProperty(this, "hidden", _descriptor2, this); + /** + * @property _visible + * @private + */ + _initializerDefineProperty(this, "_visible", _descriptor3, this); + /** + * Set to false to disable the fade out animation when hiding the alert. + * + * @property fade + * @type boolean + * @default true + * @public + */ + _initializerDefineProperty(this, "fade", _descriptor4, this); + /** + * The duration of the fade out animation + * + * @property fadeDuration + * @type number + * @default 150 + * @public + */ + _initializerDefineProperty(this, "fadeDuration", _descriptor5, this); + /** + * Property for type styling + * + * For the available types see the [Bootstrap docs](https://getbootstrap.com/docs/4.3/components/alerts/) + * + * @property type + * @type String + * @public + */ + /** + * Use CSS transitions? + * + * @property usesTransition + * @type boolean + * @readonly + * @private + */ + _initializerDefineProperty(this, "usesTransition", _descriptor6, this); + } + /** + * This property controls if the alert should be visible. If false it might still be in the DOM until the fade animation + * has completed. + * + * When the alert is dismissed by user interaction this property will not update by using two-way bindings in order + * to follow DDAU best practices. If you want to react to such changes, subscribe to the `onDismiss` action + * + * @property visible + * @type boolean + * @default true + * @public + */ + get visible() { + return this._visible ?? true; + } + get showAlert() { + return this.visible && this.args.fade !== false; + } + /** + * The action to be sent after the alert has been dismissed (including the CSS transition). + * + * @event onDismissed + * @public + */ - // Return the cached record - return Promise.resolve(internalModel); - }, - _findByInternalModel: function _findByInternalModel(internalModel) { - var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + /** + * The action is called when the close button is clicked. + * + * You can return false to prevent closing the alert automatically, and do that in your action by + * setting `visible` to false. + * + * @event onDismiss + * @public + */ - if (options.preload) { - internalModel.preloadData(options.preload); + dismiss() { + if (this.args.onDismiss?.() !== false) { + this._visible = false; } + } - var fetchedInternalModel = this._findEmptyInternalModel(internalModel, options); + /** + * Call to make the alert visible again after it has been hidden + * + * @method show + * @private + */ + show() { + this.hidden = false; + } - return promiseRecord(fetchedInternalModel, 'DS: Store#findRecord ' + internalModel.modelName + ' with id: ' + internalModel.id); - }, - _findEmptyInternalModel: function _findEmptyInternalModel(internalModel, options) { - if (internalModel.isEmpty()) { - return this._scheduleFetch(internalModel, options); + /** + * Call to hide the alert. If the `fade` property is true, this will fade out the alert before being finally + * dismissed. + * + * @method hide + * @private + */ + hide() { + if (this.hidden) { + return; } - - //TODO double check about reloading - if (internalModel.isLoading()) { - return internalModel._loadingPromise; + if (this.usesTransition) { + (0, _runloop.later)(this, function () { + if (!this.isDestroyed) { + this.hidden = true; + this.args.onDismissed?.(); + } + }, this.fadeDuration); + } else { + this.hidden = true; + this.args.onDismissed?.(); } - - return Promise.resolve(internalModel); - }, - - - /** - This method makes a series of requests to the adapter's `find` method - and returns a promise that resolves once they are all loaded. - @private - @method findByIds - @param {String} modelName - @param {Array} ids - @return {Promise} promise - */ - findByIds: function findByIds(modelName, ids) { - (0, _debug.assert)('You need to pass a model name to the store\'s findByIds method', isPresent(modelName)); - (0, _debug.assert)('Passing classes to store methods has been removed. Please pass a dasherized string instead of ' + modelName, typeof modelName === 'string'); - - var promises = new Array(ids.length); - - var normalizedModelName = (0, _normalizeModelName.default)(modelName); - - for (var i = 0; i < ids.length; i++) { - promises[i] = this.findRecord(normalizedModelName, ids[i]); + } + showOrHide() { + if (this.visible) { + this.show(); + } else { + this.hide(); } + } + updateVisibility() { + this._visible = this.args.visible; + } + }, (_descriptor = _applyDecoratedDescriptor(_class.prototype, "dismissible", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return true; + } + }), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "hidden", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return !this.visible; + } + }), _descriptor3 = _applyDecoratedDescriptor(_class.prototype, "_visible", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return this.args.visible; + } + }), _descriptor4 = _applyDecoratedDescriptor(_class.prototype, "fade", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return true; + } + }), _descriptor5 = _applyDecoratedDescriptor(_class.prototype, "fadeDuration", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return 150; + } + }), _descriptor6 = _applyDecoratedDescriptor(_class.prototype, "usesTransition", [_dec], { + configurable: true, + enumerable: true, + writable: true, + initializer: null + }), _applyDecoratedDescriptor(_class.prototype, "dismiss", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "dismiss"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "showOrHide", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "showOrHide"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "updateVisibility", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "updateVisibility"), _class.prototype)), _class)); + (0, _component.setComponentTemplate)(__COLOCATED_TEMPLATE__, Alert); +}); +;define("ember-bootstrap/components/bs-button-group", ["exports", "@ember/component", "@ember/object", "@glimmer/component", "@ember/array", "@ember/template-factory"], function (_exports, _component, _object, _component2, _array, _templateFactory) { + "use strict"; - return (0, _promiseProxies.promiseArray)(RSVP.all(promises).then(A, null, 'DS: Store#findByIds of ' + normalizedModelName + ' complete')); - }, - + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + var _class; + 0; //eaimeta@70e063a35619d71f0,"@ember/object",0,"@glimmer/component",0,"@ember/array",0,"@ember/template-factory",0,"@ember/component"eaimeta@70e063a35619d71f + function _applyDecoratedDescriptor(i, e, r, n, l) { var a = {}; return Object.keys(n).forEach(function (i) { a[i] = n[i]; }), a.enumerable = !!a.enumerable, a.configurable = !!a.configurable, ("value" in a || a.initializer) && (a.writable = !0), a = r.slice().reverse().reduce(function (r, n) { return n(i, e, r) || r; }, a), l && void 0 !== a.initializer && (a.value = a.initializer ? a.initializer.call(l) : void 0, a.initializer = void 0), void 0 === a.initializer && (Object.defineProperty(i, e, a), a = null), a; } + const __COLOCATED_TEMPLATE__ = (0, _templateFactory.createTemplateFactory)( + /* + {{! @glint-nocheck }} +
+ {{yield + (hash + button=(component (ensure-safe-component (bs-default @buttonComponent (component "bs-button-group/button"))) buttonGroupType=@type groupValue=@value onClick=this.buttonPressed) + ) + }} +
+ */ + { + "id": "Is5vefqV", + "block": "[[[11,0],[16,0,[29,[[52,[30,1],\"btn-group-vertical\",\"btn-group\"],\" \",[28,[37,2],[\"btn-group\",[30,2]],null]]]],[24,\"role\",\"group\"],[17,3],[12],[1,\"\\n \"],[18,7,[[28,[37,4],null,[[\"button\"],[[50,[28,[37,6],[[28,[37,7],[[30,4],[50,\"bs-button-group/button\",0,null,null]],null]],null],0,null,[[\"buttonGroupType\",\"groupValue\",\"onClick\"],[[30,5],[30,6],[30,0,[\"buttonPressed\"]]]]]]]]]],[1,\"\\n\"],[13]],[\"@vertical\",\"@size\",\"&attrs\",\"@buttonComponent\",\"@type\",\"@value\",\"&default\"],false,[\"div\",\"if\",\"bs-size-class\",\"yield\",\"hash\",\"component\",\"ensure-safe-component\",\"bs-default\"]]", + "moduleName": "ember-bootstrap/components/bs-button-group.hbs", + "isStrictMode": false + }); + /** + Bootstrap-style button group, that visually groups buttons, and optionally adds radio/checkbox like behaviour. + See http://getbootstrap.com/components/#btn-groups + + Use as a block level component with any number of [Components.Button](Components.Button.html) components provided as + a yielded pre-configured contextual component: + + ```handlebars + + 1 + 2 + 3 + + ``` + + ### Radio-like behaviour + + Use the `type` property set to "radio" to make the child buttons toggle like radio buttons, i.e. only one button can be active. + Set the `value` property of the buttons to something meaningful. The `value` property of the button group will then reflect + the value of the active button: + + ```handlebars + + 1 + 2 + 3 + + + You selected: {{this.buttonGroupValue}}! + ``` + + ### Checkbox-like behaviour + + Set `type` to "checkbox" to make any number of child buttons selectable. The `value` property will be an array + of all the values of the active buttons: + + ```handlebars + + 1 + 2 + 3 + + + You selected: +
    + {{#each value in this.buttonGroupValue}} +
  • {{value}}
  • + {{/each}} +
+ ``` + + *Note that only invoking the component in a template as shown above is considered part of its public API. Extending from it (subclassing) is generally not supported, and may break at any time.* + + @class ButtonGroup + @namespace Components + @extends Glimmer.Component + @public + */ + let ButtonGroup = _exports.default = (_class = class ButtonGroup extends _component2.default { /** - This method is called by `findRecord` if it discovers that a particular - type/id pair hasn't been loaded yet to kick off a request to the - adapter. - @method _fetchRecord - @private - @param {InternalModel} internalModel model - @return {Promise} promise + * @property buttonComponent + * @type {String} + * @private */ - _fetchRecord: function _fetchRecord(internalModel, options) { - var modelName = internalModel.modelName; - var adapter = this.adapterFor(modelName); - - (0, _debug.assert)('You tried to find a record but you have no adapter (for ' + modelName + ')', adapter); - (0, _debug.assert)('You tried to find a record but your adapter (for ' + modelName + ') does not implement \'findRecord\'', typeof adapter.findRecord === 'function'); - - return (0, _finders._find)(adapter, this, internalModel.type, internalModel.id, internalModel, options); - }, - _scheduleFetchMany: function _scheduleFetchMany(internalModels) { - var fetches = new Array(internalModels.length); - - for (var i = 0; i < internalModels.length; i++) { - fetches[i] = this._scheduleFetch(internalModels[i]); - } - - return Promise.all(fetches); - }, - _scheduleFetch: function _scheduleFetch(internalModel, options) { - if (internalModel._loadingPromise) { - return internalModel._loadingPromise; - } - var id = internalModel.id, - modelName = internalModel.modelName; + /** + * Set to true for a vertically stacked button group, see http://getbootstrap.com/components/#btn-groups-vertical + * + * @property vertical + * @type boolean + * @default false + * @public + */ - var resolver = RSVP.defer('Fetching ' + modelName + '\' with id: ' + id); - var pendingFetchItem = { - internalModel: internalModel, - resolver: resolver, - options: options - }; + /** + * The type of the button group specifies how child buttons behave and how the `value` property will be computed: + * + * ### null + * If `type` is not set (null), the button group will add no functionality besides Bootstrap styling + * + * ### radio + * if `type` is set to "radio", the buttons will behave like radio buttons: + * * the `value` property of the button group will reflect the `value` property of the active button + * * thus only one button may be active + * + * ### checkbox + * if `type` is set to "checkbox", the buttons will behave like checkboxes: + * * any number of buttons may be active + * * the `value` property of the button group will be an array containing the `value` properties of all active buttons + * + * @property type + * @type string + * @default null + * @public + */ - var promise = resolver.promise; + /** + * The value of the button group, computed by its child buttons. + * See the `type` property for how the value property is constructed. + * + * When you set the value, the corresponding buttons will be activated: + * * use a single value for a radio button group to activate the button with the same value + * * use an array of values for a checkbox button group to activate all the buttons with values contained in the array + * + * @property value + * @type array + * @public + */ - internalModel.loadingData(promise); - if (this._pendingFetch.size === 0) { - emberRun.schedule('afterRender', this, this.flushAllPendingFetches); - } + /** + * Property for size styling, set to 'lg', 'sm' or 'xs' + * + * Also see the [Bootstrap docs](https://getbootstrap.com/docs/4.3/components/button-group/#sizing) + * + * @property size + * @type String + * @public + */ - this._pendingFetch.get(modelName).push(pendingFetchItem); + /** + * This action is called whenever the button group's value should be changed because the user clicked a button. + * You will receive the new value of the button group (based on the `type` property), which you should use to update the + * `value` property. + * + * @event onChange + * @param {*} value + * @public + */ - return promise; - }, - flushAllPendingFetches: function flushAllPendingFetches() { - if (this.isDestroyed || this.isDestroying) { + buttonPressed(pressedValue) { + if (!this.args.onChange) { return; } - - this._pendingFetch.forEach(this._flushPendingFetchForType, this); - this._pendingFetch.clear(); - }, - _flushPendingFetchForType: function _flushPendingFetchForType(pendingFetchItems, modelName) { - var store = this; - var adapter = store.adapterFor(modelName); - var shouldCoalesce = !!adapter.findMany && adapter.coalesceFindRequests; - var totalItems = pendingFetchItems.length; - var internalModels = new Array(totalItems); - var seeking = Object.create(null); - - for (var i = 0; i < totalItems; i++) { - var pendingItem = pendingFetchItems[i]; - var internalModel = pendingItem.internalModel; - internalModels[i] = internalModel; - seeking[internalModel.id] = pendingItem; - } - - function _fetchRecord(recordResolverPair) { - var recordFetch = store._fetchRecord(recordResolverPair.internalModel, recordResolverPair.options); // TODO adapter options - - recordResolverPair.resolver.resolve(recordFetch); - } - - function handleFoundRecords(foundInternalModels, expectedInternalModels) { - // resolve found records - var found = Object.create(null); - for (var _i = 0, l = foundInternalModels.length; _i < l; _i++) { - var _internalModel = foundInternalModels[_i]; - var pair = seeking[_internalModel.id]; - found[_internalModel.id] = _internalModel; - - if (pair) { - var resolver = pair.resolver; - resolver.resolve(_internalModel); - } + let newValue; + if (this.args.type === 'radio') { + if (pressedValue === this.args.value) { + return; } - - // reject missing records - var missingInternalModels = []; - - for (var _i2 = 0, _l = expectedInternalModels.length; _i2 < _l; _i2++) { - var _internalModel2 = expectedInternalModels[_i2]; - - if (!found[_internalModel2.id]) { - missingInternalModels.push(_internalModel2); + newValue = pressedValue; + } else { + if (!(0, _array.isArray)(this.args.value)) { + newValue = [pressedValue]; + } else { + if (this.args.value.includes(pressedValue)) { + newValue = this.args.value.filter(v => v !== pressedValue); + } else { + newValue = [...this.args.value, pressedValue]; } } - if (missingInternalModels.length) { - (0, _debug.warn)('Ember Data expected to find records with the following ids in the adapter response but they were missing: ' + inspect(missingInternalModels.map(function (r) { - return r.id; - })), false, { - id: 'ds.store.missing-records-from-adapter' - }); - rejectInternalModels(missingInternalModels); - } - } - - function rejectInternalModels(internalModels, error) { - for (var _i3 = 0, l = internalModels.length; _i3 < l; _i3++) { - var _internalModel3 = internalModels[_i3]; - var pair = seeking[_internalModel3.id]; - - if (pair) { - pair.resolver.reject(error || new Error('Expected: \'' + _internalModel3 + '\' to be present in the adapter provided payload, but it was not found.')); - } - } + // For compatibility we continue to return an EmberArray instance for now + // @todo this should be changed for the next major release! + newValue = (0, _array.A)(newValue); } + this.args.onChange(newValue); + } + }, (_applyDecoratedDescriptor(_class.prototype, "buttonPressed", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "buttonPressed"), _class.prototype)), _class); + (0, _component.setComponentTemplate)(__COLOCATED_TEMPLATE__, ButtonGroup); +}); +;define("ember-bootstrap/components/bs-button-group/button", ["exports", "@ember/component", "@ember/array", "ember-bootstrap/components/bs-button", "@ember/object/internals", "@ember/template-factory"], function (_exports, _component, _array, _bsButton, _internals, _templateFactory) { + "use strict"; - if (shouldCoalesce) { - // TODO: Improve records => snapshots => records => snapshots - // - // We want to provide records to all store methods and snapshots to all - // adapter methods. To make sure we're doing that we're providing an array - // of snapshots to adapter.groupRecordsForFindMany(), which in turn will - // return grouped snapshots instead of grouped records. - // - // But since the _findMany() finder is a store method we need to get the - // records from the grouped snapshots even though the _findMany() finder - // will once again convert the records to snapshots for adapter.findMany() - var snapshots = new Array(totalItems); - for (var _i4 = 0; _i4 < totalItems; _i4++) { - snapshots[_i4] = internalModels[_i4].createSnapshot(); - } - - var groups = adapter.groupRecordsForFindMany(this, snapshots); - - var _loop = function _loop(l, _i5) { - var group = groups[_i5]; - var totalInGroup = groups[_i5].length; - var ids = new Array(totalInGroup); - var groupedInternalModels = new Array(totalInGroup); - - for (var j = 0; j < totalInGroup; j++) { - var _internalModel4 = group[j]._internalModel; + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + 0; //eaimeta@70e063a35619d71f0,"@ember/array",0,"ember-bootstrap/components/bs-button",0,"@ember/object/internals",0,"@embroider/macros",0,"@ember/template-factory",0,"@ember/component"eaimeta@70e063a35619d71f + function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } + function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } + function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } + const __COLOCATED_TEMPLATE__ = (0, _templateFactory.createTemplateFactory)( + /* + {{! @glint-nocheck }} + {{#if this.isBS5ToggleButton}} + + + {{else}} + + {{/if}} + */ + { + "id": "lXLpL3N5", + "block": "[[[41,[30,0,[\"isBS5ToggleButton\"]],[[[1,\" \"],[11,\"input\"],[16,4,[30,1]],[24,0,\"btn-check\"],[16,1,[30,0,[\"formId\"]]],[24,\"autocomplete\",\"off\"],[16,\"checked\",[30,0,[\"active\"]]],[17,2],[4,[38,2],[\"click\",[30,0,[\"handleClick\"]]],null],[4,[38,3],[[30,0,[\"resetState\"]],[30,3]],null],[12],[13],[1,\"\\n \"],[10,\"label\"],[15,0,[29,[\"btn \",[28,[37,5],[\"btn\",[30,4]],null],\" \",[28,[37,6],[\"btn\",[30,5]],[[\"default\",\"outline\"],[\"secondary\",[30,6]]]]]]],[15,\"for\",[30,0,[\"formId\"]]],[12],[1,\"\\n\"],[41,[30,0,[\"icon\"]],[[[1,\" \"],[10,\"i\"],[15,0,[30,0,[\"icon\"]]],[12],[13],[1,\"\\n\"]],[]],null],[1,\" \"],[1,[30,0,[\"text\"]]],[1,\"\\n \"],[18,7,[[28,[37,9],null,[[\"isFulfilled\",\"isPending\",\"isRejected\",\"isSettled\"],[[30,0,[\"isFulfilled\"]],[30,0,[\"isPending\"]],[30,0,[\"isRejected\"]],[30,0,[\"isSettled\"]]]]]]],[1,\"\\n \"],[13],[1,\"\\n\"]],[]],[[[1,\" \"],[11,\"button\"],[16,\"disabled\",[30,0,[\"__disabled\"]]],[24,4,\"button\"],[16,0,[29,[\"btn \",[52,[30,0,[\"active\"]],\"active\"],\" \",[52,[30,0,[\"block\"]],\"btn-block\"],\" \",[28,[37,5],[\"btn\",[30,4]],null],\" \",[28,[37,6],[\"btn\",[30,5]],[[\"default\",\"outline\"],[\"secondary\",[30,6]]]]]]],[17,2],[4,[38,2],[\"click\",[30,0,[\"handleClick\"]]],null],[4,[38,3],[[30,0,[\"resetState\"]],[30,3]],null],[12],[1,\"\\n\"],[41,[30,0,[\"icon\"]],[[[1,\" \"],[10,\"i\"],[15,0,[30,0,[\"icon\"]]],[12],[13],[1,\"\\n\"]],[]],null],[1,\" \"],[1,[30,0,[\"text\"]]],[1,\"\\n \"],[18,7,[[28,[37,9],null,[[\"isFulfilled\",\"isPending\",\"isRejected\",\"isSettled\"],[[30,0,[\"isFulfilled\"]],[30,0,[\"isPending\"]],[30,0,[\"isRejected\"]],[30,0,[\"isSettled\"]]]]]]],[1,\"\\n \"],[13],[1,\"\\n\"]],[]]]],[\"@buttonGroupType\",\"&attrs\",\"@reset\",\"@size\",\"@type\",\"@outline\",\"&default\"],false,[\"if\",\"input\",\"on\",\"did-update\",\"label\",\"bs-size-class\",\"bs-type-class\",\"i\",\"yield\",\"hash\",\"button\"]]", + "moduleName": "ember-bootstrap/components/bs-button-group/button.hbs", + "isStrictMode": false + }); - groupedInternalModels[j] = _internalModel4; - ids[j] = _internalModel4.id; - } + /** + Internal component for button-group buttons + + @class ButtonGroupButton + @namespace Components + @extends Components.Button + @private + */ + class ButtonGroupButton extends _bsButton.default { + constructor(...args) { + super(...args); + _defineProperty(this, "formId", (0, _internals.guidFor)(this)); + } + /** + * @property groupValue + * @private + */ - if (totalInGroup > 1) { - (0, _finders._findMany)(adapter, store, modelName, ids, groupedInternalModels).then(function (foundInternalModels) { - handleFoundRecords(foundInternalModels, groupedInternalModels); - }).catch(function (error) { - rejectInternalModels(groupedInternalModels, error); - }); - } else if (ids.length === 1) { - var pair = seeking[groupedInternalModels[0].id]; - _fetchRecord(pair); - } else { - (0, _debug.assert)("You cannot return an empty array from adapter's method groupRecordsForFindMany", false); - } - }; + /** + * @property buttonGroupType + * @type string + * @private + */ - for (var _i5 = 0, l = groups.length; _i5 < l; _i5++) { - _loop(l, _i5); - } + /** + * @property active + * @type boolean + * @readonly + * @private + */ + get active() { + let { + value, + groupValue + } = this.args; + if (this.args.buttonGroupType === 'radio') { + return value === groupValue; } else { - for (var _i6 = 0; _i6 < totalItems; _i6++) { - _fetchRecord(pendingFetchItems[_i6]); + if ((0, _array.isArray)(groupValue)) { + return groupValue.indexOf(value) !== -1; } } - }, - + return false; + } + get isBS5ToggleButton() { + { + return this.args.buttonGroupType === 'radio' || this.args.buttonGroupType === 'checkbox'; + } + } + } + _exports.default = ButtonGroupButton; + (0, _component.setComponentTemplate)(__COLOCATED_TEMPLATE__, ButtonGroupButton); +}); +;define("ember-bootstrap/components/bs-button", ["exports", "@ember/component", "@glimmer/tracking", "@ember/object", "@glimmer/component", "ember-bootstrap/utils/decorators/arg", "@ember/template-factory"], function (_exports, _component, _tracking, _object, _component2, _arg, _templateFactory) { + "use strict"; - /** - Get the reference for the specified record. - Example - ```javascript - let userRef = store.getReference('user', 1); - // check if the user is loaded - let isLoaded = userRef.value() !== null; - // get the record of the reference (null if not yet available) - let user = userRef.value(); - // get the identifier of the reference - if (userRef.remoteType() === 'id') { - let id = userRef.id(); + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + var _class, _descriptor, _descriptor2; + 0; //eaimeta@70e063a35619d71f0,"@glimmer/tracking",0,"@ember/object",0,"@glimmer/component",0,"ember-bootstrap/utils/decorators/arg",0,"@ember/template-factory",0,"@ember/component"eaimeta@70e063a35619d71f + function _initializerDefineProperty(e, i, r, l) { r && Object.defineProperty(e, i, { enumerable: r.enumerable, configurable: r.configurable, writable: r.writable, value: r.initializer ? r.initializer.call(l) : void 0 }); } + function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } + function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } + function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } + function _applyDecoratedDescriptor(i, e, r, n, l) { var a = {}; return Object.keys(n).forEach(function (i) { a[i] = n[i]; }), a.enumerable = !!a.enumerable, a.configurable = !!a.configurable, ("value" in a || a.initializer) && (a.writable = !0), a = r.slice().reverse().reduce(function (r, n) { return n(i, e, r) || r; }, a), l && void 0 !== a.initializer && (a.value = a.initializer ? a.initializer.call(l) : void 0, a.initializer = void 0), void 0 === a.initializer && (Object.defineProperty(i, e, a), a = null), a; } + function _initializerWarningHelper(r, e) { throw Error("Decorating class property failed. Please ensure that transform-class-properties is enabled and runs after the decorators transform."); } + const __COLOCATED_TEMPLATE__ = (0, _templateFactory.createTemplateFactory)( + /* + + */ + { + "id": "+Azfb/n8", + "block": "[[[11,\"button\"],[16,\"disabled\",[30,0,[\"__disabled\"]]],[16,4,[52,[30,1],[30,1],\"button\"]],[16,0,[29,[\"btn \",[52,[30,2],\"active\"],\" \",[27],\" \",[28,[37,2],[\"btn\",[30,3]],null],\" \",[28,[37,3],[\"btn\",[30,4]],[[\"default\",\"outline\"],[\"secondary\",[30,5]]]]]]],[17,6],[4,[38,4],[\"click\",[30,0,[\"handleClick\"]]],null],[4,[38,5],[[30,0,[\"resetState\"]],[30,7]],null],[12],[1,\"\\n \"],[41,[30,0,[\"icon\"]],[[[10,\"i\"],[15,0,[30,0,[\"icon\"]]],[12],[13],[1,\" \"]],[]],null],[1,[30,0,[\"text\"]]],[18,8,[[28,[37,8],null,[[\"isFulfilled\",\"isPending\",\"isRejected\",\"isSettled\"],[[30,0,[\"isFulfilled\"]],[30,0,[\"isPending\"]],[30,0,[\"isRejected\"]],[30,0,[\"isSettled\"]]]]]]],[1,\"\\n\"],[13]],[\"@attrTypePrivateWorkaround\",\"@active\",\"@size\",\"@type\",\"@outline\",\"&attrs\",\"@reset\",\"&default\"],false,[\"button\",\"if\",\"bs-size-class\",\"bs-type-class\",\"on\",\"did-update\",\"i\",\"yield\",\"hash\"]]", + "moduleName": "ember-bootstrap/components/bs-button.hbs", + "isStrictMode": false + }); + /** + Implements a HTML button element, with support for all [Bootstrap button CSS styles](http://getbootstrap.com/css/#buttons) + as well as advanced functionality such as button states. + + ### Basic Usage + + ```hbs + + Downloads + + ``` + + ### Actions + + Use the `onClick` property of the component to send an action to your controller. It will receive the button's value + (see the `value` property) as an argument. + + ```hbs + + Downloads + + ``` + + ### Promise support for automatic state change + + When returning a Promise for any asynchronous operation from the `onClick` closure action the button will + manage an internal state ("default" > "pending" > "fulfilled"/"rejected") automatically. + + The button is disabled by default if it's in pending state. You could override this behavior by passing + the `disabled` HTML attribute or by setting `@preventConcurrency` to false. + + ```hbs + + ``` + + ```hbs + + ``` + + The label could be changed automatically according to the state of the promise with `@defaultText`, + `@pendingText`, `@fulfilledText` and `@rejectedText` arguments: + + ```hbs + + ``` + + ```js + // controller.js + import { Controller } from '@ember/controller'; + import { action } from '@ember/object'; + + export default class MyController extends Controller { + @action + download(value) { + return new Promise(...); } - // load user (via store.find) - userRef.load().then(...) - // or trigger a reload - userRef.reload().then(...) - // provide data for reference - userRef.push({ id: 1, username: '@user' }).then(function(user) { - userRef.value() === user; - }); - ``` - @method getReference - @param {String} modelName - @param {String|Integer} id - @since 2.5.0 - @return {RecordReference} - */ - getReference: function getReference(modelName, id) { - var normalizedModelName = (0, _normalizeModelName.default)(modelName); + }); + ``` + + For further customization `isPending`, `isFulfilled`, `isRejected` and `isSettled` properties are yielded: + + ```hbs + + Download + {{#if button.isPending}} + + {{/if}} + + ``` + + You can `reset` the state represented by these properties and used for button's text by setting `reset` property to + `true`. + + *Note that only invoking the component in a template as shown above is considered part of its public API. Extending from it (subclassing) is generally not supported, and may break at any time.* + + @class Button + @namespace Components + @extends Glimmer.Component + @public + */ + let Button = _exports.default = (_class = class Button extends _component2.default { + constructor(...args) { + super(...args); + /** + * Set the 'active' class to apply active/pressed CSS styling + * + * @property active + * @type boolean + * @default false + * @public + */ + /** + * Property for block level buttons (BS3 and BS4 only!) + * + * See the [Bootstrap docs](http://getbootstrap.com/css/#buttons-sizes) + * @property block + * @type boolean + * @default false + * @public + */ + _initializerDefineProperty(this, "block", _descriptor, this); + /** + * Supply a value that will be associated with this button. This will be sent + * as a parameter of the default action triggered when clicking the button + * + * @property value + * @type any + * @public + */ + /** + * Controls if `onClick` action is fired concurrently. If `true` clicking button multiple times will not trigger + * `onClick` action if a Promise returned by previous click is not settled yet. + * + * This does not affect event bubbling. + * + * @property preventConcurrency + * @type Boolean + * @default true + * @public + */ + /** + * State of the button. The button's label (if not used as a block component) will be set to the + * `Text` property. + * This property will automatically be set when using a click action that supplies the callback with a promise. + * Possible values are: "default" > "pending" > "fulfilled" / "rejected". + * It could be resetted by `reset` property. + * + * @property state + * @type String + * @default 'default' + * @private + */ + _initializerDefineProperty(this, "_state", _descriptor2, this); + } + /** + * Default label of the button. Not need if used as a block component + * + * @property defaultText + * @type string + * @public + */ - return this._internalModelForId(normalizedModelName, id).recordReference; - }, + /** + * Label of the button used if `onClick` event has returned a Promise which is pending. + * Not considered if used as a block component. + * + * @property pendingText + * @type string + * @public + */ + /** + * Label of the button used if `onClick` event has returned a Promise which succeeded. + * Not considered if used as a block component. + * + * @property fulfilledText + * @type string + * @public + */ /** - Get a record by a given type and ID without triggering a fetch. - This method will synchronously return the record if it is available in the store, - otherwise it will return `null`. A record is available if it has been fetched earlier, or - pushed manually into the store. - _Note: This is a synchronous method and does not return a promise._ - ```js - let post = store.peekRecord('post', 1); - post.get('id'); // 1 - ``` - @since 1.13.0 - @method peekRecord - @param {String} modelName - @param {String|Integer} id - @return {DS.Model|null} record - */ - peekRecord: function peekRecord(modelName, id) { - (0, _debug.assert)('You need to pass a model name to the store\'s peekRecord method', isPresent(modelName)); - (0, _debug.assert)('Passing classes to store methods has been removed. Please pass a dasherized string instead of ' + modelName, typeof modelName === 'string'); - var normalizedModelName = (0, _normalizeModelName.default)(modelName); + * Label of the button used if `onClick` event has returned a Promise which failed. + * Not considered if used as a block component. + * + * @property rejectedText + * @type string + * @public + */ - if (this.hasRecordForId(normalizedModelName, id)) { - return this._internalModelForId(normalizedModelName, id).getRecord(); - } else { - return null; + /** + * Property to disable the button only used in internal communication + * between Ember Boostrap components. + * + * @property _disabled + * @type ?boolean + * @default null + * @private + */ + get __disabled() { + if (this.args._disabled !== undefined) { + return this.args._disabled; } - }, - - + return this.isPending && this.args.preventConcurrency !== false; + } /** - This method is called by the record's `reload` method. - This method calls the adapter's `find` method, which returns a promise. When - **that** promise resolves, `reloadRecord` will resolve the promise returned - by the record's `reload`. - @method reloadRecord - @private - @param {DS.Model} internalModel - @return {Promise} promise - */ - _reloadRecord: function _reloadRecord(internalModel) { - var id = internalModel.id, - modelName = internalModel.modelName; - - var adapter = this.adapterFor(modelName); - - (0, _debug.assert)('You cannot reload a record without an ID', id); - (0, _debug.assert)('You tried to reload a record but you have no adapter (for ' + modelName + ')', adapter); - (0, _debug.assert)('You tried to reload a record but your adapter does not implement \'findRecord\'', typeof adapter.findRecord === 'function' || typeof adapter.find === 'function'); - - return this._scheduleFetch(internalModel); - }, - + * A click event on a button will not bubble up the DOM tree if it has an `onClick` action handler. Set to true to + * enable the event to bubble + * + * @property bubble + * @type boolean + * @default false + * @public + */ /** - This method returns true if a record for a given modelName and id is already - loaded in the store. Use this function to know beforehand if a findRecord() - will result in a request or that it will be a cache hit. - Example - ```javascript - store.hasRecordForId('post', 1); // false - store.findRecord('post', 1).then(function() { - store.hasRecordForId('post', 1); // true - }); - ``` - @method hasRecordForId - @param {String} modelName - @param {(String|Integer)} id - @return {Boolean} - */ - hasRecordForId: function hasRecordForId(modelName, id) { - (0, _debug.assert)('You need to pass a model name to the store\'s hasRecordForId method', isPresent(modelName)); - (0, _debug.assert)('Passing classes to store methods has been removed. Please pass a dasherized string instead of ' + modelName, typeof modelName === 'string'); - - var normalizedModelName = (0, _normalizeModelName.default)(modelName); - - var trueId = (0, _coerceId.default)(id); - var internalModel = this._internalModelsFor(normalizedModelName).get(trueId); - - return !!internalModel && internalModel.isLoaded(); - }, - + * If button is active and this is set, the icon property will match this property + * + * @property iconActive + * @type String + * @public + */ /** - Returns id record for a given type and ID. If one isn't already loaded, - it builds a new record and leaves it in the `empty` state. - @method recordForId - @private - @param {String} modelName - @param {(String|Integer)} id - @return {DS.Model} record - */ - recordForId: function recordForId(modelName, id) { - (0, _debug.assert)('You need to pass a model name to the store\'s recordForId method', isPresent(modelName)); - (0, _debug.assert)('Passing classes to store methods has been removed. Please pass a dasherized string instead of ' + modelName, typeof modelName === 'string'); - - return this._internalModelForId(modelName, id).getRecord(); - }, - _internalModelForId: function _internalModelForId(modelName, id) { - var trueId = (0, _coerceId.default)(id); - var internalModel = this._internalModelsFor(modelName).get(trueId); - - if (!internalModel) { - internalModel = this.buildInternalModel(modelName, trueId); - } + * If button is inactive and this is set, the icon property will match this property + * + * @property iconInactive + * @type String + * @public + */ - return internalModel; - }, + /** + * Class(es) (e.g. glyphicons or font awesome) to use as a button icon + * This will render a element in front of the button's label + * + * @property icon + * @type String + * @public + */ + get icon() { + return this.args.icon || (this.args.active ? this.args.iconActive : this.args.iconInactive); + } + get state() { + return this.args.state ?? this._state; + } + set state(state) { + this._state = state; + } + /** + * Promise returned by `onClick` event is pending. + * + * @property isPending + * @type Boolean + * @private + */ + get isPending() { + return this.state === 'pending'; + } /** - @method findMany - @private - @param {Array} internalModels - @return {Promise} promise - */ - findMany: function findMany(internalModels) { - var finds = new Array(internalModels.length); + * Promise returned by `onClick` event has been succeeded. + * + * @property isFulfilled + * @type Boolean + * @private + */ + get isFulfilled() { + return this.state === 'fulfilled'; + } - for (var i = 0; i < internalModels.length; i++) { - finds[i] = this._findEmptyInternalModel(internalModels[i]); - } + /** + * Promise returned by `onClick` event has been rejected. + * + * @property isRejected + * @type Boolean + * @private + */ + get isRejected() { + return this.state === 'rejected'; + } - return Promise.all(finds); - }, + /** + * Promise returned by `onClick` event has been succeeded or rejected. + * + * @property isSettled + * @type Boolean + * @private + */ + get isSettled() { + return this.isFulfilled || this.isRejected; + } + /** + * Set this to `true` to reset the `state`. A typical use case is to bind this attribute with ember-data isDirty flag. + * + * The old value is not taken into consideration. Setting a `true` value to `true` again will also reset `state`. + * In that case it's even to notify the observer system that the property has changed by calling + * [`notifyPropertyChange()`](https://www.emberjs.com/api/ember/3.2/classes/EmberObject/methods/notifyPropertyChange?anchor=notifyPropertyChange). + * + * @property reset + * @type boolean + * @public + */ /** - If a relationship was originally populated by the adapter as a link - (as opposed to a list of IDs), this method is called when the - relationship is fetched. - The link (which is usually a URL) is passed through unchanged, so the - adapter can make whatever request it wants. - The usual use-case is for the server to register a URL as a link, and - then use that URL in the future to make a request for the relationship. - @method findHasMany - @private - @param {InternalModel} internalModel - @param {any} link - @param {(Relationship)} relationship - @return {Promise} promise - */ - findHasMany: function findHasMany(internalModel, link, relationship) { - var adapter = this.adapterFor(internalModel.modelName); + * Property for size styling, set to 'lg', 'sm' or 'xs' + * + * Also see the [Bootstrap docs](https://getbootstrap.com/docs/4.3/components/buttons/#sizes) + * + * @property size + * @type String + * @public + */ - (0, _debug.assert)('You tried to load a hasMany relationship but you have no adapter (for ' + internalModel.modelName + ')', adapter); - (0, _debug.assert)('You tried to load a hasMany relationship from a specified \'link\' in the original payload but your adapter does not implement \'findHasMany\'', typeof adapter.findHasMany === 'function'); + /** + * Property for type styling + * + * For the available types see the [Bootstrap docs](https://getbootstrap.com/docs/4.3/components/buttons/) + * + * @property type + * @type String + * @default 'secondary' + * @public + */ - return (0, _finders._findHasMany)(adapter, this, internalModel, link, relationship); - }, + /** + * Property to create outline buttons (BS4+ only) + * + * @property outline + * @type boolean + * @default false + * @public + */ + /** + * When clicking the button this action is called with the value of the button (that is the value of the "value" property). + * + * Return a promise object, and the buttons state will automatically set to "pending", "resolved" and/or "rejected". + * This could be used to automatically set the button's text depending on promise state (`defaultText`, `pendingText`, + * `fulfilledText`, `rejectedText`) and for further customization using the yielded `isPending`, `isFulfilled`, + * `isRejected` properties. + * + * The click event will not bubble up, unless you set `bubble` to true. + * + * @event onClick + * @param {*} value + * @public + */ /** - @method findBelongsTo - @private - @param {InternalModel} internalModel - @param {any} link - @param {Relationship} relationship - @return {Promise} promise - */ - findBelongsTo: function findBelongsTo(internalModel, link, relationship) { - var adapter = this.adapterFor(internalModel.modelName); + * This will reset the state property to 'default', and with that the button's label to defaultText + * + * @method resetState + * @private + */ + resetState() { + this.state = 'default'; + } + get text() { + return this.args[`${this.state}Text`] || this.args.defaultText; + } - (0, _debug.assert)('You tried to load a belongsTo relationship but you have no adapter (for ' + internalModel.modelName + ')', adapter); - (0, _debug.assert)('You tried to load a belongsTo relationship from a specified \'link\' in the original payload but your adapter does not implement \'findBelongsTo\'', typeof adapter.findBelongsTo === 'function'); + /** + * @method click + * @private + */ + async handleClick(e) { + const { + bubble, + onClick, + preventConcurrency + } = this.args; + if (typeof onClick !== 'function') { + return; + } - return (0, _finders._findBelongsTo)(adapter, this, internalModel, link, relationship); - }, + // Shouldn't we prevent propagation regardless if `@onClick` is a function? + if (!bubble) { + e.stopPropagation(); + } + if (preventConcurrency && this.isPending) { + return; + } + this.state = 'pending'; + try { + await onClick(this.args.value); + if (!this.isDestroyed) { + this.state = 'fulfilled'; + } + } catch (error) { + if (!this.isDestroyed) { + this.state = 'rejected'; + } + throw error; + } + } + }, (_descriptor = _applyDecoratedDescriptor(_class.prototype, "block", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return false; + } + }), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "_state", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return 'default'; + } + }), _applyDecoratedDescriptor(_class.prototype, "resetState", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "resetState"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "handleClick", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "handleClick"), _class.prototype)), _class); + (0, _component.setComponentTemplate)(__COLOCATED_TEMPLATE__, Button); +}); +;define("ember-bootstrap/components/bs-carousel", ["exports", "@ember/component", "ember-concurrency/-private/async-arrow-runtime", "@ember/object", "ember-bootstrap/components/bs-carousel/slide", "@glimmer/component", "@ember/runloop", "ember-concurrency", "@glimmer/tracking", "@ember/template-factory"], function (_exports, _component, _asyncArrowRuntime, _object, _slide, _component2, _runloop, _emberConcurrency, _tracking, _templateFactory) { + "use strict"; + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + var _class, _descriptor, _descriptor2, _descriptor3, _descriptor4, _descriptor5, _descriptor6, _descriptor7; + 0; //eaimeta@70e063a35619d71f0,"ember-concurrency/-private/async-arrow-runtime",0,"@ember/object",0,"ember-bootstrap/components/bs-carousel/slide",0,"@glimmer/component",0,"@ember/runloop",0,"ember-concurrency",0,"@glimmer/tracking",0,"@ember/template-factory",0,"@ember/component"eaimeta@70e063a35619d71f + function _initializerDefineProperty(e, i, r, l) { r && Object.defineProperty(e, i, { enumerable: r.enumerable, configurable: r.configurable, writable: r.writable, value: r.initializer ? r.initializer.call(l) : void 0 }); } + function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } + function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } + function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } + function _applyDecoratedDescriptor(i, e, r, n, l) { var a = {}; return Object.keys(n).forEach(function (i) { a[i] = n[i]; }), a.enumerable = !!a.enumerable, a.configurable = !!a.configurable, ("value" in a || a.initializer) && (a.writable = !0), a = r.slice().reverse().reduce(function (r, n) { return n(i, e, r) || r; }, a), l && void 0 !== a.initializer && (a.value = a.initializer ? a.initializer.call(l) : void 0, a.initializer = void 0), void 0 === a.initializer && (Object.defineProperty(i, e, a), a = null), a; } + function _initializerWarningHelper(r, e) { throw Error("Decorating class property failed. Please ensure that transform-class-properties is enabled and runs after the decorators transform."); } + const __COLOCATED_TEMPLATE__ = (0, _templateFactory.createTemplateFactory)( + /* + {{! @glint-nocheck }} + + */ + { + "id": "0/iGGu6A", + "block": "[[[11,0],[16,\"tabindex\",[30,0,[\"tabindex\"]]],[16,0,[29,[\"carousel slide \",[52,[30,0,[\"carouselFade\"]],\"carousel-fade\"]]]],[17,1],[4,[38,2],[\"keydown\",[30,0,[\"handleKeyDown\"]]],null],[4,[38,2],[\"mouseenter\",[30,0,[\"handleMouseEnter\"]]],null],[4,[38,2],[\"mouseleave\",[30,0,[\"handleMouseLeave\"]]],null],[4,[38,3],[[30,0,[\"childSlidesObserver\"]],[30,0,[\"childSlides\"]],[30,0,[\"autoPlay\"]]],null],[4,[38,3],[[30,0,[\"indexObserver\"]],[30,0,[\"index\"]]],null],[12],[1,\"\\n\"],[41,[30,0,[\"showIndicators\"]],[[[1,\" \"],[10,0],[14,0,\"carousel-indicators\"],[12],[1,\"\\n\"],[42,[28,[37,5],[[28,[37,5],[[30,0,[\"indicators\"]]],null]],null],null,[[[1,\" \"],[11,\"button\"],[24,\"data-bs-target\",\"\"],[16,0,[52,[28,[37,7],[[30,0,[\"currentIndex\"]],[30,3]],null],\"active\"]],[16,\"aria-current\",[29,[[28,[37,7],[[30,0,[\"currentIndex\"]],[30,3]],null]]]],[24,4,\"button\"],[4,[38,2],[\"click\",[28,[37,8],[[30,0,[\"toSlide\"]],[30,3]],null]],null],[12],[13],[1,\"\\n\"]],[2,3]],null],[1,\" \"],[13],[1,\"\\n\"],[1,\"\\n\"]],[]],null],[1,\"\\n \"],[10,0],[14,0,\"carousel-inner\"],[14,\"role\",\"listbox\"],[12],[1,\"\\n \"],[18,5,[[28,[37,10],null,[[\"slide\"],[[50,[28,[37,12],[[28,[37,13],[[30,4],[50,\"bs-carousel/slide\",0,null,null]],null]],null],0,null,[[\"currentSlide\",\"directionalClassName\",\"followingSlide\",\"orderClassName\",\"presentationState\",\"registerChild\",\"unregisterChild\"],[[30,0,[\"currentSlide\"]],[30,0,[\"directionalClassName\"]],[30,0,[\"followingSlide\"]],[30,0,[\"orderClassName\"]],[30,0,[\"presentationState\"]],[30,0,[\"registerChild\"]],[30,0,[\"unregisterChild\"]]]]]]]]]],[1,\"\\n \"],[13],[1,\"\\n\\n\"],[41,[30,0,[\"showControls\"]],[[[1,\" \"],[11,\"button\"],[24,0,\"carousel-control-prev\"],[24,4,\"button\"],[4,[38,2],[\"click\",[30,0,[\"toPrevSlide\"]]],null],[12],[1,\"\\n \"],[10,1],[14,\"aria-hidden\",\"true\"],[14,0,\"carousel-control-prev-icon\"],[12],[13],[1,\"\\n \"],[10,1],[14,0,\"visually-hidden\"],[12],[1,[30,0,[\"prevControlLabel\"]]],[13],[1,\"\\n \"],[13],[1,\"\\n \"],[11,\"button\"],[24,0,\"carousel-control-next\"],[24,4,\"button\"],[4,[38,2],[\"click\",[30,0,[\"toNextSlide\"]]],null],[12],[1,\"\\n \"],[10,1],[14,\"aria-hidden\",\"true\"],[14,0,\"carousel-control-next-icon\"],[12],[13],[1,\"\\n \"],[10,1],[14,0,\"visually-hidden\"],[12],[1,[30,0,[\"nextControlLabel\"]]],[13],[1,\"\\n \"],[13],[1,\"\\n\"]],[]],null],[1,\"\\n\"],[13]],[\"&attrs\",\"indicator\",\"_index\",\"@slideComponent\",\"&default\"],false,[\"div\",\"if\",\"on\",\"did-update\",\"each\",\"-track-array\",\"button\",\"bs-eq\",\"fn\",\"yield\",\"hash\",\"component\",\"ensure-safe-component\",\"bs-default\",\"span\"]]", + "moduleName": "ember-bootstrap/components/bs-carousel.hbs", + "isStrictMode": false + }); - /** - This method delegates a query to the adapter. This is the one place where - adapter-level semantics are exposed to the application. - Each time this method is called a new request is made through the adapter. - Exposing queries this way seems preferable to creating an abstract query - language for all server-side queries, and then require all adapters to - implement them. - --- - If you do something like this: - ```javascript - store.query('person', { page: 1 }); - ``` - The call made to the server, using a Rails backend, will look something like this: - ``` - Started GET "/api/v1/person?page=1" - Processing by Api::V1::PersonsController#index as HTML - Parameters: { "page"=>"1" } - ``` - --- - If you do something like this: - ```javascript - store.query('person', { ids: [1, 2, 3] }); - ``` - The call to the server, using a Rails backend, will look something like this: - ``` - Started GET "/api/v1/person?ids%5B%5D=1&ids%5B%5D=2&ids%5B%5D=3" - Processing by Api::V1::PersonsController#index as HTML - Parameters: { "ids" => ["1", "2", "3"] } - ``` - This method returns a promise, which is resolved with an - [`AdapterPopulatedRecordArray`](http://emberjs.com/api/data/classes/DS.AdapterPopulatedRecordArray.html) - once the server returns. - @since 1.13.0 - @method query - @param {String} modelName - @param {any} query an opaque query to be used by the adapter - @return {Promise} promise - */ - query: function query(modelName, _query2) { - (0, _debug.assert)('You need to pass a model name to the store\'s query method', isPresent(modelName)); - (0, _debug.assert)('You need to pass a query hash to the store\'s query method', _query2); - (0, _debug.assert)('Passing classes to store methods has been removed. Please pass a dasherized string instead of ' + modelName, typeof modelName === 'string'); + /** + Ember implementation of Bootstrap's Carousel. Supports all original features but API is partially different: + + | Description | Original | Component | + | ------ | ------ | ------ | + | Autoplays after first user event or on page load. | ride='carousel'\|false | autoPlay=false\|true | + | Disable automatic cycle. | interval=false | interval=0 | + | If first slide should follow last slide on "previous" event, the opposite will also be true for "next" event. | wrap=false\|true | wrap=false\|true | + | Jumps into specific slide index | data-slide-to=n | index=n | + | Keyboard events. | keyboard=false\|true | keyboard=false\|true | + | Left-to-right or right-to-left sliding. | N/A | ltr=false\|true | + | Pause current cycle on mouse enter. | pause='hover'\|null | pauseOnMouseEnter=false\|true | + | Show or hide controls | Tag manipulation. | showControls=false\|true | + | Show or hide indicators | Tag manipulation. | showIndicators=false\|true | + | Waiting time of slides in an automatic cycle. | interval=n | interval=n | + + Default settings are the same as the original, so you don't have to worry about changing parameters. + + ```hbs + + + First slide + + + Second slide + + + Third slide + + + ``` + + To better understand the whole documentation, you should be aware of the following operations: + + | Operation | Description | + | ------ | ------ | + | Transition | Swaps two slides. | + | Interval | Waiting time after a transition. | + | Presentation | Represents a single transition, or a single interval, or the union of both. | + | Cycle | Presents all slides until it reaches first or last slide. | + | Wrap | wrap slides, cycles without stopping at first or last slide. | + + *Note that only invoking the component in a template as shown above is considered part of its public API. Extending from it (subclassing) is generally not supported, and may break at any time.* + + @class Carousel + @namespace Components + @extends Component + @public + */ + let Carousel = _exports.default = (_class = class Carousel extends _component2.default { + constructor(...args) { + super(...args); + _defineProperty(this, "tabindex", '1'); + _initializerDefineProperty(this, "children", _descriptor, this); + /** + * Indicates the current index of the current slide. + * + * @property currentIndex + * @private + */ + _initializerDefineProperty(this, "currentIndex", _descriptor2, this); + /** + * Bootstrap style to indicate that a given slide should be moving to left/right. + * + * @property directionalClassName + * @private + * @type { 'left' | 'right' | null } + */ + _initializerDefineProperty(this, "directionalClassName", _descriptor3, this); + /** + * Indicates the next slide index to move into. + * + * @property followingIndex + * @private + * @type number + */ + _initializerDefineProperty(this, "followingIndex", _descriptor4, this); + /** + * If user is hovering its cursor on component. + * This property is only manipulated when 'pauseOnMouseEnter' is true. + * + * @property isMouseHovering + * @private + * @type boolean + */ + _initializerDefineProperty(this, "isMouseHovering", _descriptor5, this); + /** + * The class name to append to the next control link element. + * + * @property nextControlClassName + * @type string + * @private + */ + /** + * Bootstrap style to indicate the next/previous slide. + * + * @property orderClassName + * @private + * @type string + */ + _initializerDefineProperty(this, "orderClassName", _descriptor6, this); + /** + * The current state of the current presentation, can be either "didTransition" + * or "willTransit". + * + * @private + * @property presentationState + * @type { 'didTransition' | 'willTransit' | null } + */ + _initializerDefineProperty(this, "presentationState", _descriptor7, this); + /** + * Action called after the slide has changed. + * + * @event onSlideChanged + * @param toIndex + * @public + */ + /** + * Do a presentation and calls itself to perform a cycle. + * + * @method cycle + * @this Carousel + * @private + */ + _defineProperty(this, "cycle", (0, _asyncArrowRuntime.buildTask)(() => ({ + context: this, + generator: function* () { + yield this.transitioner.perform(); + yield (0, _emberConcurrency.timeout)(this.interval); + this.toAppropriateSlide(); + } + }), { + restartable: true + }, "cycle", null)); + /** + * @method transitioner + * @this Carousel + * @private + */ + _defineProperty(this, "transitioner", (0, _asyncArrowRuntime.buildTask)(() => ({ + context: this, + generator: function* () { + this.presentationState = 'willTransit'; + yield (0, _emberConcurrency.timeout)(this.transitionDuration); + this.presentationState = 'didTransition'; + // Must change current index after execution of 'presentationStateObserver' method + // from child components. + yield new Promise(resolve => { + (0, _runloop.schedule)('afterRender', this, () => { + this.currentIndex = this.followingIndex; + resolve(); + }); + }); + } + }), { + drop: true + }, "transitioner", null)); + /** + * Waits an interval time to start a cycle. + * + * @method waitIntervalToInitCycle + * @this Carousel + * @private + */ + _defineProperty(this, "waitIntervalToInitCycle", (0, _asyncArrowRuntime.buildTask)(() => ({ + context: this, + generator: function* () { + if (this.shouldRunAutomatically === false) { + return; + } + yield (0, _emberConcurrency.timeout)(this.interval); + this.toAppropriateSlide(); + } + }), { + restartable: true + }, "waitIntervalToInitCycle", null)); + } + /** + * @property slideComponent + * @type {String} + * @private + */ - var normalizedModelName = (0, _normalizeModelName.default)(modelName); - return this._query(normalizedModelName, _query2); - }, - _query: function _query(modelName, query, array) { - (0, _debug.assert)('You need to pass a model name to the store\'s query method', isPresent(modelName)); - (0, _debug.assert)('You need to pass a query hash to the store\'s query method', query); - (0, _debug.assert)('Passing classes to store methods has been removed. Please pass a dasherized string instead of ' + modelName, typeof modelName === 'string'); + /** + * If a slide can turn to left, including corners. + * + * @private + * @property canTurnToLeft + */ + get canTurnToLeft() { + return this.wrap || this.currentIndex > 0; + } - array = array || this.recordArrayManager.createAdapterPopulatedRecordArray(modelName, query); + /** + * If a slide can turn to right, including corners. + * + * @private + * @property canTurnToRight + */ + get canTurnToRight() { + return this.wrap || this.currentIndex < this.childSlides.length - 1; + } + /** + * All `CarouselSlide` child components. + * + * @private + * @property childSlides + * @readonly + * @type array + */ + get childSlides() { + return this.children.filter(view => view instanceof _slide.default); + } - var adapter = this.adapterFor(modelName); + /** + * This observer is the entry point for real time insertion and removing of slides. + * + * @private + * @property childSlidesObserver + */ + childSlidesObserver() { + let childSlides = this.childSlides; + if (childSlides.length === 0) { + return; + } + // Sets new current index + let currentIndex = this.currentIndex; + if (currentIndex >= childSlides.length) { + currentIndex = childSlides.length - 1; + this.currentIndex = currentIndex; + } + // Automatic sliding + if (this.autoPlay) { + this.waitIntervalToInitCycle.perform(); + } + // Initial slide state + this.presentationState = null; + } + /** + * The current slide object that is going to be used by the nested slides components. + * + * @property currentSlide + * @private + * + */ + get currentSlide() { + return this.childSlides[this.currentIndex]; + } + /** + * The following slide object that is going to be used by the nested slides components. + * + * @property followingIndex + * @private + */ + get followingSlide() { + return this.childSlides[this.followingIndex]; + } + /** + * @private + * @property hasInterval + * @type boolean + */ + get hasInterval() { + return this.interval > 0; + } - (0, _debug.assert)('You tried to load a query but you have no adapter (for ' + modelName + ')', adapter); - (0, _debug.assert)('You tried to load a query but your adapter does not implement \'query\'', typeof adapter.query === 'function'); + /** + * This observer is the entry point for programmatically slide changing. + * + * @property indexObserver + * @private + */ + indexObserver() { + this.toSlide(this.index); + } - var pA = (0, _promiseProxies.promiseArray)((0, _finders._query)(adapter, this, modelName, query, array)); + /** + * @property indicators + * @private + */ + get indicators() { + return [...Array(this.childSlides.length)]; + } + /** + * The class name to append to the previous control link element. + * + * @property prevControlClassName + * @type string + * @private + */ - return pA; - }, + /** + * @private + * @property shouldNotDoPresentation + * @type boolean + */ + get shouldNotDoPresentation() { + return this.childSlides.length <= 1; + } + /** + * @private + * @property shouldRunAutomatically + * @type boolean + */ + get shouldRunAutomatically() { + return this.hasInterval; + } /** - This method makes a request for one record, where the `id` is not known - beforehand (if the `id` is known, use [`findRecord`](#method_findRecord) - instead). - This method can be used when it is certain that the server will return a - single object for the primary data. - Let's assume our API provides an endpoint for the currently logged in user - via: - ``` - // GET /api/current_user - { - user: { - id: 1234, - username: 'admin' - } - } - ``` - Since the specific `id` of the `user` is not known beforehand, we can use - `queryRecord` to get the user: - ```javascript - store.queryRecord('user', {}).then(function(user) { - let username = user.get('username'); - console.log(`Currently logged in as ${username}`); - }); - ``` - The request is made through the adapters' `queryRecord`: - ```app/adapters/user.js - import DS from 'ember-data'; - export default DS.Adapter.extend({ - queryRecord(modelName, query) { - return Ember.$.getJSON('/api/current_user'); - } - }); - ``` - Note: the primary use case for `store.queryRecord` is when a single record - is queried and the `id` is not known beforehand. In all other cases - `store.query` and using the first item of the array is likely the preferred - way: - ``` - // GET /users?username=unique - { - data: [{ - id: 1234, - type: 'user', - attributes: { - username: "unique" - } - }] - } - ``` - ```javascript - store.query('user', { username: 'unique' }).then(function(users) { - return users.get('firstObject'); - }).then(function(user) { - let id = user.get('id'); - }); - ``` - This method returns a promise, which resolves with the found record. - If the adapter returns no data for the primary data of the payload, then - `queryRecord` resolves with `null`: - ``` - // GET /users?username=unique - { - data: null - } - ``` - ```javascript - store.queryRecord('user', { username: 'unique' }).then(function(user) { - console.log(user); // null - }); - ``` - @since 1.13.0 - @method queryRecord - @param {String} modelName - @param {any} query an opaque query to be used by the adapter - @return {Promise} promise which resolves with the found record or `null` - */ - queryRecord: function queryRecord(modelName, query) { - (0, _debug.assert)('You need to pass a model name to the store\'s queryRecord method', isPresent(modelName)); - (0, _debug.assert)('You need to pass a query hash to the store\'s queryRecord method', query); - (0, _debug.assert)('Passing classes to store methods has been removed. Please pass a dasherized string instead of ' + modelName, typeof modelName === 'string'); + * Starts automatic sliding on page load. + * This parameter has no effect if interval is less than or equal to zero. + * + * @default false + * @property autoPlay + * @public + * @type boolean + */ + get autoPlay() { + return this.args.autoPlay ?? false; + } - var normalizedModelName = (0, _normalizeModelName.default)(modelName); + /** + * If false will hard stop on corners, i.e., first slide won't make a transition to the + * last slide and vice versa. + * + * @default true + * @property wrap + * @public + * @type boolean + */ + get wrap() { + return this.args.wrap ?? true; + } - var adapter = this.adapterFor(normalizedModelName); + /** + * Index of starting slide. + * + * @default 0 + * @property index + * @public + * @type number + */ + get index() { + return this.args.index ?? 0; + } - (0, _debug.assert)('You tried to make a query but you have no adapter (for ' + normalizedModelName + ')', adapter); - (0, _debug.assert)('You tried to make a query but your adapter does not implement \'queryRecord\'', typeof adapter.queryRecord === 'function'); + /** + * Waiting time before automatically show another slide. + * Automatic sliding is canceled if interval is less than or equal to zero. + * + * @default 5000 + * @property interval + * @public + * @type number + */ + get interval() { + return this.args.interval ?? 5000; + } - return (0, _promiseProxies.promiseObject)((0, _finders._queryRecord)(adapter, this, modelName, query).then(function (internalModel) { - // the promise returned by store.queryRecord is expected to resolve with - // an instance of DS.Model - if (internalModel) { - return internalModel.getRecord(); - } + /** + * Should bind keyboard events into sliding. + * + * @default true + * @property keyboard + * @public + * @type boolean + */ + get keyboard() { + return this.args.keyboard ?? true; + } - return null; - })); - }, + /** + * If automatic sliding should be left-to-right or right-to-left. + * This parameter has no effect if interval is less than or equal to zero. + * + * @default true + * @property ltr + * @public + * @type boolean + */ + get ltr() { + return this.args.ltr ?? true; + } + /** + * The next control icon to be displayed. + * + * @default null + * @property nextControlIcon + * @type string + * @public + */ /** - `findAll` asks the adapter's `findAll` method to find the records for the - given type, and returns a promise which will resolve with all records of - this type present in the store, even if the adapter only returns a subset - of them. - ```app/routes/authors.js - import Ember from 'ember'; - export default Ember.Route.extend({ - model(params) { - return this.store.findAll('author'); - } - }); - ``` - _When_ the returned promise resolves depends on the reload behavior, - configured via the passed `options` hash and the result of the adapter's - `shouldReloadAll` method. - ### Reloading - If `{ reload: true }` is passed or `adapter.shouldReloadAll` evaluates to - `true`, then the returned promise resolves once the adapter returns data, - regardless if there are already records in the store: - ```js - store.push({ - data: { - id: 'first', - type: 'author' - } - }); - // adapter#findAll resolves with - // [ - // { - // id: 'second', - // type: 'author' - // } - // ] - store.findAll('author', { reload: true }).then(function(authors) { - authors.getEach('id'); // ['first', 'second'] - }); - ``` - If no reload is indicated via the abovementioned ways, then the promise - immediately resolves with all the records currently loaded in the store. - ### Background Reloading - Optionally, if `adapter.shouldBackgroundReloadAll` evaluates to `true`, - then a background reload is started. Once this resolves, the array with - which the promise resolves, is updated automatically so it contains all the - records in the store: - ```js - // app/adapters/application.js - export default DS.Adapter.extend({ - shouldReloadAll(store, snapshotsArray) { - return false; - }, - shouldBackgroundReloadAll(store, snapshotsArray) { - return true; - } - }); - // ... - store.push({ - data: { - id: 'first', - type: 'author' - } - }); - let allAuthors; - store.findAll('author').then(function(authors) { - authors.getEach('id'); // ['first'] - allAuthors = authors; - }); - // later, once adapter#findAll resolved with - // [ - // { - // id: 'second', - // type: 'author' - // } - // ] - allAuthors.getEach('id'); // ['first', 'second'] - ``` - If you would like to force or prevent background reloading, you can set a - boolean value for `backgroundReload` in the options object for - `findAll`. - ```app/routes/post/edit.js - import Ember from 'ember'; - export default Ember.Route.extend({ - model() { - return this.store.findAll('post', { backgroundReload: false }); - } - }); - ``` - If you pass an object on the `adapterOptions` property of the options - argument it will be passed to you adapter via the `snapshotRecordArray` - ```app/routes/posts.js - import Ember from 'ember'; - export default Ember.Route.extend({ - model(params) { - return this.store.findAll('post', { - adapterOptions: { subscribe: false } - }); - } - }); - ``` - ```app/adapters/post.js - import MyCustomAdapter from './custom-adapter'; - export default MyCustomAdapter.extend({ - findAll(store, type, sinceToken, snapshotRecordArray) { - if (snapshotRecordArray.adapterOptions.subscribe) { - // ... - } - // ... - } - }); - ``` - See [peekAll](#method_peekAll) to get an array of current records in the - store, without waiting until a reload is finished. - ### Retrieving Related Model Records - If you use an adapter such as Ember's default - [`JSONAPIAdapter`](http://emberjs.com/api/data/classes/DS.JSONAPIAdapter.html) - that supports the [JSON API specification](http://jsonapi.org/) and if your server - endpoint supports the use of an - ['include' query parameter](http://jsonapi.org/format/#fetching-includes), - you can use `findAll()` to automatically retrieve additional records related to - those requested by supplying an `include` parameter in the `options` object. - For example, given a `post` model that has a `hasMany` relationship with a `comment` - model, when we retrieve all of the post records we can have the server also return - all of the posts' comments in the same request: - ```app/routes/posts.js - import Ember from 'ember'; - export default Ember.Route.extend({ - model() { - return this.store.findAll('post', { include: 'comments' }); - } - }); - ``` - Multiple relationships can be requested using an `include` parameter consisting of a - comma-separated list (without white-space) while nested relationships can be specified - using a dot-separated sequence of relationship names. So to request both the posts' - comments and the authors of those comments the request would look like this: - ```app/routes/posts.js - import Ember from 'ember'; - export default Ember.Route.extend({ - model() { - return this.store.findAll('post', { include: 'comments,comments.author' }); - } - }); - ``` - See [query](#method_query) to only get a subset of records from the server. - @since 1.13.0 - @method findAll - @param {String} modelName - @param {Object} options - @return {Promise} promise - */ - findAll: function findAll(modelName, options) { - (0, _debug.assert)('You need to pass a model name to the store\'s findAll method', isPresent(modelName)); - (0, _debug.assert)('Passing classes to store methods has been removed. Please pass a dasherized string instead of ' + modelName, typeof modelName === 'string'); + * Label for screen readers, defaults to 'Next'. + * + * @default 'Next' + * @property nextControlLabel + * @type string + * @public + */ + get nextControlLabel() { + return this.args.nextControlLabel ?? 'Next'; + } - var normalizedModelName = (0, _normalizeModelName.default)(modelName); - var fetch = this._fetchAll(normalizedModelName, this.peekAll(normalizedModelName), options); + /** + * Pauses automatic sliding if mouse cursor is hovering the component. + * This parameter has no effect if interval is less than or equal to zero. + * + * @default true + * @property pauseOnMouseEnter + * @public + * @type boolean + */ + get pauseOnMouseEnter() { + return this.args.pauseOnMouseEnter ?? true; + } - return fetch; - }, + /** + * The previous control icon to be displayed. + * + * @default null + * @property prevControlIcon + * @type string + * @public + */ + /** + * Label for screen readers, defaults to 'Previous'. + * + * @default 'Previous' + * @property prevControlLabel + * @type string + * @public + */ + get prevControlLabel() { + return this.args.prevControlLabel ?? 'Previous'; + } /** - @method _fetchAll - @private - @param {DS.Model} modelName - @param {DS.RecordArray} array - @return {Promise} promise - */ - _fetchAll: function _fetchAll(modelName, array) { - var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + * Show or hide controls. + * + * @default true + * @property showControls + * @public + * @type boolean + */ + get showControls() { + return this.args.showControls ?? true; + } - var adapter = this.adapterFor(modelName); - var sinceToken = this._internalModelsFor(modelName).metadata.since; + /** + * Show or hide indicators. + * + * @default true + * @property showIndicators + * @public + * @type boolean + */ + get showIndicators() { + return this.args.showIndicators ?? true; + } - (0, _debug.assert)('You tried to load all records but you have no adapter (for ' + modelName + ')', adapter); - (0, _debug.assert)('You tried to load all records but your adapter does not implement \'findAll\'', typeof adapter.findAll === 'function'); + /** + * The duration of the slide transition. + * You should also change this parameter in Bootstrap CSS file. + * + * @default 600 + * @property transitionDuration + * @public + * @type number + */ + get transitionDuration() { + return this.args.transitionDuration ?? 600; + } - if (options.reload) { - set(array, 'isUpdating', true); - return (0, _promiseProxies.promiseArray)((0, _finders._findAll)(adapter, this, modelName, sinceToken, options)); + /** + * The type slide transition to perform. + * Options are 'fade' or 'slide'. Note: BS4 only + * + * @default 'slide' + * @property transition + * @public + * @type string + */ + get transition() { + return this.args.transition ?? 'slide'; + } + get carouselFade() { + return this.transition === 'fade'; + } + toSlide(toIndex) { + if (this.currentIndex === toIndex || this.shouldNotDoPresentation) { + return; } - - var snapshotArray = array._createSnapshot(options); - - if (adapter.shouldReloadAll(this, snapshotArray)) { - set(array, 'isUpdating', true); - return (0, _promiseProxies.promiseArray)((0, _finders._findAll)(adapter, this, modelName, sinceToken, options)); + this.assignClassNameControls(toIndex); + this.setFollowingIndex(toIndex); + if (this.shouldRunAutomatically === false || this.isMouseHovering) { + this.transitioner.perform(); + } else { + this.cycle.perform(); } - - if (options.backgroundReload === false) { - return (0, _promiseProxies.promiseArray)(Promise.resolve(array)); + this.args.onSlideChanged?.(toIndex); + } + toNextSlide() { + if (this.canTurnToRight) { + this.toSlide(this.currentIndex + 1); } - - if (options.backgroundReload || adapter.shouldBackgroundReloadAll(this, snapshotArray)) { - set(array, 'isUpdating', true); - (0, _finders._findAll)(adapter, this, modelName, sinceToken, options); + } + toPrevSlide() { + if (this.canTurnToLeft) { + this.toSlide(this.currentIndex - 1); } - - return (0, _promiseProxies.promiseArray)(Promise.resolve(array)); - }, - + } /** - @method didUpdateAll - @param {String} modelName - @private - */ - didUpdateAll: function didUpdateAll(modelName) { - var liveRecordArray = this.recordArrayManager.liveRecordArrayFor(modelName); - - set(liveRecordArray, 'isUpdating', false); - }, - + * Indicates what class names should be applicable to the current transition slides. + * + * @method assignClassNameControls + * @private + */ + assignClassNameControls(toIndex) { + if (toIndex < this.currentIndex) { + this.directionalClassName = 'right'; + this.orderClassName = 'prev'; + } else { + this.directionalClassName = 'left'; + this.orderClassName = 'next'; + } + } + handleMouseEnter() { + if (this.pauseOnMouseEnter) { + this.isMouseHovering = true; + this.cycle.cancelAll(); + this.waitIntervalToInitCycle.cancelAll(); + } + } + handleMouseLeave() { + if (this.pauseOnMouseEnter && (this.transitioner.last !== null || this.waitIntervalToInitCycle.last !== null)) { + this.isMouseHovering = false; + this.waitIntervalToInitCycle.perform(); + } + } + handleKeyDown(e) { + let code = e.keyCode || e.which; + if (this.keyboard === false || /input|textarea/i.test(e.target.tagName)) { + return; + } + switch (code) { + case 37: + this.toPrevSlide(); + break; + case 39: + this.toNextSlide(); + break; + default: + break; + } + } /** - This method returns a filtered array that contains all of the - known records for a given type in the store. - Note that because it's just a filter, the result will contain any - locally created records of the type, however, it will not make a - request to the backend to retrieve additional records. If you - would like to request all the records from the backend please use - [store.findAll](#method_findAll). - Also note that multiple calls to `peekAll` for a given type will always - return the same `RecordArray`. - Example - ```javascript - let localPosts = store.peekAll('post'); - ``` - @since 1.13.0 - @method peekAll - @param {String} modelName - @return {DS.RecordArray} - */ - peekAll: function peekAll(modelName) { - (0, _debug.assert)('You need to pass a model name to the store\'s peekAll method', isPresent(modelName)); - (0, _debug.assert)('Passing classes to store methods has been removed. Please pass a dasherized string instead of ' + modelName, typeof modelName === 'string'); - var normalizedModelName = (0, _normalizeModelName.default)(modelName); - var liveRecordArray = this.recordArrayManager.liveRecordArrayFor(normalizedModelName); - - this.recordArrayManager.syncLiveRecordArray(liveRecordArray, normalizedModelName); - - return liveRecordArray; - }, - + * Sets the following slide index within the lower and upper bounds. + * + * @method setFollowingIndex + * @private + */ + setFollowingIndex(toIndex) { + let slidesLengthMinusOne = this.childSlides.length - 1; + if (toIndex > slidesLengthMinusOne) { + this.followingIndex = 0; + } else if (toIndex < 0) { + this.followingIndex = slidesLengthMinusOne; + } else { + this.followingIndex = toIndex; + } + } /** - This method unloads all records in the store. - It schedules unloading to happen during the next run loop. - Optionally you can pass a type which unload all records for a given type. - ```javascript - store.unloadAll(); - store.unloadAll('post'); - ``` - @method unloadAll - @param {String} modelName - */ - unloadAll: function unloadAll(modelName) { - (0, _debug.assert)('Passing classes to store methods has been removed. Please pass a dasherized string instead of ' + modelName, !modelName || typeof modelName === 'string'); - - if (arguments.length === 0) { - this._identityMap.clear(); + * Coordinates the correct slide movement direction. + * + * @method toAppropriateSlide + * @private + */ + toAppropriateSlide() { + if (this.ltr) { + this.toNextSlide(); } else { - var normalizedModelName = (0, _normalizeModelName.default)(modelName); - this._internalModelsFor(normalizedModelName).clear(); + this.toPrevSlide(); } - }, + } + registerChild(element) { + (0, _runloop.schedule)('actions', this, () => { + this.children = [...this.children, element]; + }); + } + unregisterChild(element) { + (0, _runloop.schedule)('actions', this, () => { + this.children = this.children.filter(value => value !== element); + }); + } + }, (_descriptor = _applyDecoratedDescriptor(_class.prototype, "children", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return []; + } + }), _applyDecoratedDescriptor(_class.prototype, "childSlidesObserver", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "childSlidesObserver"), _class.prototype), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "currentIndex", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return this.index; + } + }), _descriptor3 = _applyDecoratedDescriptor(_class.prototype, "directionalClassName", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return null; + } + }), _descriptor4 = _applyDecoratedDescriptor(_class.prototype, "followingIndex", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return null; + } + }), _applyDecoratedDescriptor(_class.prototype, "indexObserver", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "indexObserver"), _class.prototype), _descriptor5 = _applyDecoratedDescriptor(_class.prototype, "isMouseHovering", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return false; + } + }), _descriptor6 = _applyDecoratedDescriptor(_class.prototype, "orderClassName", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return null; + } + }), _descriptor7 = _applyDecoratedDescriptor(_class.prototype, "presentationState", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return null; + } + }), _applyDecoratedDescriptor(_class.prototype, "toSlide", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "toSlide"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "toNextSlide", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "toNextSlide"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "toPrevSlide", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "toPrevSlide"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "handleMouseEnter", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "handleMouseEnter"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "handleMouseLeave", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "handleMouseLeave"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "handleKeyDown", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "handleKeyDown"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "registerChild", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "registerChild"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "unregisterChild", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "unregisterChild"), _class.prototype)), _class); + (0, _component.setComponentTemplate)(__COLOCATED_TEMPLATE__, Carousel); +}); +;define("ember-bootstrap/components/bs-carousel/slide", ["exports", "@ember/component", "@glimmer/component", "@ember/runloop", "ember-ref-bucket", "@glimmer/tracking", "@ember/object", "@ember/destroyable", "@ember/template-factory"], function (_exports, _component, _component2, _runloop, _emberRefBucket, _tracking, _object, _destroyable, _templateFactory) { + "use strict"; + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + var _dec, _class, _descriptor, _descriptor2, _descriptor3, _descriptor4, _descriptor5, _descriptor6; + 0; //eaimeta@70e063a35619d71f0,"@glimmer/component",0,"@ember/runloop",0,"ember-ref-bucket",0,"@glimmer/tracking",0,"@ember/object",0,"@ember/destroyable",0,"@ember/template-factory",0,"@ember/component"eaimeta@70e063a35619d71f + function _initializerDefineProperty(e, i, r, l) { r && Object.defineProperty(e, i, { enumerable: r.enumerable, configurable: r.configurable, writable: r.writable, value: r.initializer ? r.initializer.call(l) : void 0 }); } + function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } + function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } + function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } + function _applyDecoratedDescriptor(i, e, r, n, l) { var a = {}; return Object.keys(n).forEach(function (i) { a[i] = n[i]; }), a.enumerable = !!a.enumerable, a.configurable = !!a.configurable, ("value" in a || a.initializer) && (a.writable = !0), a = r.slice().reverse().reduce(function (r, n) { return n(i, e, r) || r; }, a), l && void 0 !== a.initializer && (a.value = a.initializer ? a.initializer.call(l) : void 0, a.initializer = void 0), void 0 === a.initializer && (Object.defineProperty(i, e, a), a = null), a; } + function _initializerWarningHelper(r, e) { throw Error("Decorating class property failed. Please ensure that transform-class-properties is enabled and runs after the decorators transform."); } + const __COLOCATED_TEMPLATE__ = (0, _templateFactory.createTemplateFactory)( + /* + {{! @glint-nocheck }} + + */ + { + "id": "sCitZ/Ay", + "block": "[[[11,0],[16,0,[29,[\"carousel-item \",[52,[30,0,[\"active\"]],\"active\"],\" \",[52,[30,0,[\"left\"]],\"carousel-item-start\"],\" \",[52,[30,0,[\"next\"]],\"carousel-item-next\"],\" \",[52,[30,0,[\"prev\"]],\"carousel-item-prev\"],\" \",[52,[30,0,[\"right\"]],\"carousel-item-end\"]]]],[17,1],[4,[38,2],[\"mainNode\"],[[\"debugName\",\"bucket\"],[\"create-ref\",[30,0]]]],[4,[38,3],[[30,0,[\"presentationStateObserver\"]],[30,2],[30,3]],null],[12],[1,\"\\n \"],[18,4,null],[1,\"\\n\"],[13]],[\"&attrs\",\"@presentationState\",\"@currentSlide\",\"&default\"],false,[\"div\",\"if\",\"create-ref\",\"did-update\",\"yield\"]]", + "moduleName": "ember-bootstrap/components/bs-carousel/slide.hbs", + "isStrictMode": false + }); + /** + A visible user-defined slide. + + See [Components.Carousel](Components.Carousel.html) for examples. + + @class CarouselSlide + @namespace Components + @extends Component + @public + */ + let CarouselSlide = _exports.default = (_dec = (0, _emberRefBucket.ref)('mainNode'), (_class = class CarouselSlide extends _component2.default { /** - Takes a type and filter function, and returns a live RecordArray that - remains up to date as new records are loaded into the store or created - locally. - The filter function takes a materialized record, and returns true - if the record should be included in the filter and false if it should - not. - Example - ```javascript - store.filter('post', function(post) { - return post.get('unread'); - }); - ``` - The filter function is called once on all records for the type when - it is created, and then once on each newly loaded or created record. - If any of a record's properties change, or if it changes state, the - filter function will be invoked again to determine whether it should - still be in the array. - Optionally you can pass a query, which is the equivalent of calling - [query](#method_query) with that same query, to fetch additional records - from the server. The results returned by the server could then appear - in the filter if they match the filter function. - The query itself is not used to filter records, it's only sent to your - server for you to be able to do server-side filtering. The filter - function will be applied on the returned results regardless. - Example - ```javascript - store.filter('post', { unread: true }, function(post) { - return post.get('unread'); - }).then(function(unreadPosts) { - unreadPosts.get('length'); // 5 - let unreadPost = unreadPosts.objectAt(0); - unreadPost.set('unread', false); - unreadPosts.get('length'); // 4 + * @private + * @property isCurrentSlide + * @type boolean + */ + get isCurrentSlide() { + return this.args.currentSlide === this; + } + + /** + * @private + * @property isFollowingSlide + * @type boolean + */ + get isFollowingSlide() { + return this.args.followingSlide === this; + } + + /** + * Slide is moving to the left. + * + * @property left + * @type boolean + * @private + */ + + constructor(owner, args) { + super(owner, args); + /** + * @property _element + * @type null | HTMLElement + * @private + */ + _initializerDefineProperty(this, "_element", _descriptor, this); + /** + * Defines slide visibility. + * + * @property active + * @type boolean + * @private + */ + _initializerDefineProperty(this, "active", _descriptor2, this); + _initializerDefineProperty(this, "left", _descriptor3, this); + /** + * Next to appear in a left sliding. + * + * @property next + * @type boolean + * @private + */ + _initializerDefineProperty(this, "next", _descriptor4, this); + /** + * Next to appear in a right sliding. + * + * @property prev + * @type boolean + * @private + */ + _initializerDefineProperty(this, "prev", _descriptor5, this); + /** + * Slide is moving to the right. + * + * @property right + * @type boolean + * @private + */ + _initializerDefineProperty(this, "right", _descriptor6, this); + args.registerChild?.(this); + (0, _destroyable.registerDestructor)(this, () => { + this.args.unregisterChild?.(this); }); - ``` - @method filter - @private - @param {String} modelName - @param {Object} query optional query - @param {Function} filter - @return {DS.PromiseArray} - @deprecated - */ - filter: function filter(modelName, query, _filter) { - (0, _debug.assert)('You need to pass a model name to the store\'s filter method', isPresent(modelName)); - (0, _debug.assert)('Passing classes to store methods has been removed. Please pass a dasherized string instead of ' + modelName, typeof modelName === 'string'); - - if (!ENV.ENABLE_DS_FILTER) { - (0, _debug.assert)('The filter API has been moved to a plugin. To enable store.filter using an environment flag, or to use an alternative, you can visit the ember-data-filter addon page. https://github.com/ember-data/ember-data-filter', false); - } - - var promise = void 0; - var length = arguments.length; - var array = void 0; - var hasQuery = length === 3; - - var normalizedModelName = (0, _normalizeModelName.default)(modelName); + } - // allow an optional server query - if (hasQuery) { - promise = this.query(normalizedModelName, query); - } else if (arguments.length === 2) { - _filter = query; + /** + * Coordinates the execution of a presentation. + * + * @method presentationStateObserver + * @private + */ + presentationStateObserver() { + if (!this.active) { + this.active = this.isCurrentSlide && this.args.presentationState === null; + } + let presentationState = this.args.presentationState; + if (this.isCurrentSlide) { + switch (presentationState) { + case 'didTransition': + this.currentSlideDidTransition(); + break; + case 'willTransit': + this.currentSlideWillTransit(); + break; + } } - - if (hasQuery) { - array = this.recordArrayManager.createFilteredRecordArray(normalizedModelName, _filter, query); - } else { - array = this.recordArrayManager.createFilteredRecordArray(normalizedModelName, _filter); + if (this.isFollowingSlide) { + switch (presentationState) { + case 'didTransition': + this.followingSlideDidTransition(); + break; + case 'willTransit': + this.followingSlideWillTransit(); + break; + } } + } - promise = promise || Promise.resolve(array); - - return (0, _promiseProxies.promiseArray)(promise.then(function () { - return array; - }, null, 'DS: Store#filter of ' + normalizedModelName)); - }, - + /** + * @method currentSlideDidTransition + * @private + */ + currentSlideDidTransition() { + this[this.args.directionalClassName] = false; + this.active = false; + } /** - This method has been deprecated and is an alias for store.hasRecordForId, which should - be used instead. - @deprecated - @method recordIsLoaded - @param {String} modelName - @param {string} id - @return {boolean} - */ - recordIsLoaded: function recordIsLoaded(modelName, id) { - (0, _debug.deprecate)('Use of recordIsLoaded is deprecated, use hasRecordForId instead.', false, { - id: 'ds.store.recordIsLoaded', - until: '3.0' + * @method currentSlideWillTransit + * @private + */ + currentSlideWillTransit() { + this.active = true; + (0, _runloop.next)(this, function () { + this[this.args.directionalClassName] = true; }); - return this.hasRecordForId(modelName, id); - }, - + } - // .............. - // . PERSISTING . - // .............. + /** + * @method followingSlideDidTransition + * @private + */ + followingSlideDidTransition() { + this.active = true; + this[this.args.directionalClassName] = false; + this[this.args.orderClassName] = false; + } /** - This method is called by `record.save`, and gets passed a - resolver for the promise that `record.save` returns. - It schedules saving to happen at the end of the run loop. - @method scheduleSave - @private - @param {InternalModel} internalModel - @param {Resolver} resolver - @param {Object} options - */ - scheduleSave: function scheduleSave(internalModel, resolver, options) { - var snapshot = internalModel.createSnapshot(options); - internalModel.flushChangedAttributes(); - internalModel.adapterWillCommit(); - this._pendingSave.push({ - snapshot: snapshot, - resolver: resolver + * @method followingSlideWillTransit + * @private + */ + followingSlideWillTransit() { + this[this.args.orderClassName] = true; + (0, _runloop.next)(this, () => { + this.reflow(); + this[this.args.directionalClassName] = true; }); - emberRun.once(this, this.flushPendingSave); - }, - + } /** - This method is called at the end of the run loop, and - flushes any records passed into `scheduleSave` - @method flushPendingSave - @private - */ - flushPendingSave: function flushPendingSave() { - var pending = this._pendingSave.slice(); - this._pendingSave = []; - - for (var i = 0, j = pending.length; i < j; i++) { - var pendingItem = pending[i]; - var snapshot = pendingItem.snapshot; - var resolver = pendingItem.resolver; - var internalModel = snapshot._internalModel; - var adapter = this.adapterFor(internalModel.modelName); - var operation = void 0; - - if (internalModel.currentState.stateName === 'root.deleted.saved') { - return resolver.resolve(); - } else if (internalModel.isNew()) { - operation = 'createRecord'; - } else if (internalModel.isDeleted()) { - operation = 'deleteRecord'; - } else { - operation = 'updateRecord'; - } - - resolver.resolve(_commit(adapter, this, operation, snapshot)); - } - }, - + * Makes things more stable, especially when fast changing. + */ + reflow() { + this._element.offsetHeight; + } + }, (_descriptor = _applyDecoratedDescriptor(_class.prototype, "_element", [_dec], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return null; + } + }), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "active", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return this.isCurrentSlide && this.args.presentationState === null; + } + }), _descriptor3 = _applyDecoratedDescriptor(_class.prototype, "left", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return false; + } + }), _descriptor4 = _applyDecoratedDescriptor(_class.prototype, "next", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return false; + } + }), _descriptor5 = _applyDecoratedDescriptor(_class.prototype, "prev", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return false; + } + }), _descriptor6 = _applyDecoratedDescriptor(_class.prototype, "right", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return false; + } + }), _applyDecoratedDescriptor(_class.prototype, "presentationStateObserver", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "presentationStateObserver"), _class.prototype)), _class)); + (0, _component.setComponentTemplate)(__COLOCATED_TEMPLATE__, CarouselSlide); +}); +;define("ember-bootstrap/components/bs-collapse", ["exports", "@ember/component", "@ember/object", "@glimmer/component", "@ember/utils", "@ember/runloop", "ember-bootstrap/utils/transition-end", "ember-ref-bucket", "ember-bootstrap/utils/decorators/arg", "@glimmer/tracking", "@ember/debug", "@ember/template-factory"], function (_exports, _component, _object, _component2, _utils, _runloop, _transitionEnd, _emberRefBucket, _arg, _tracking, _debug, _templateFactory) { + "use strict"; + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + var _dec, _class, _descriptor, _descriptor2, _descriptor3, _descriptor4, _descriptor5, _descriptor6, _descriptor7, _descriptor8; + 0; //eaimeta@70e063a35619d71f0,"@ember/object",0,"@glimmer/component",0,"@ember/utils",0,"@ember/runloop",0,"ember-bootstrap/utils/transition-end",0,"ember-ref-bucket",0,"ember-bootstrap/utils/decorators/arg",0,"@glimmer/tracking",0,"@ember/debug",0,"@ember/template-factory",0,"@ember/component"eaimeta@70e063a35619d71f + function _initializerDefineProperty(e, i, r, l) { r && Object.defineProperty(e, i, { enumerable: r.enumerable, configurable: r.configurable, writable: r.writable, value: r.initializer ? r.initializer.call(l) : void 0 }); } + function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } + function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } + function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } + function _applyDecoratedDescriptor(i, e, r, n, l) { var a = {}; return Object.keys(n).forEach(function (i) { a[i] = n[i]; }), a.enumerable = !!a.enumerable, a.configurable = !!a.configurable, ("value" in a || a.initializer) && (a.writable = !0), a = r.slice().reverse().reduce(function (r, n) { return n(i, e, r) || r; }, a), l && void 0 !== a.initializer && (a.value = a.initializer ? a.initializer.call(l) : void 0, a.initializer = void 0), void 0 === a.initializer && (Object.defineProperty(i, e, a), a = null), a; } + function _initializerWarningHelper(r, e) { throw Error("Decorating class property failed. Please ensure that transform-class-properties is enabled and runs after the decorators transform."); } + const __COLOCATED_TEMPLATE__ = (0, _templateFactory.createTemplateFactory)( + /* +
+ {{yield}} +
+ + */ + { + "id": "Bd/rMHtK", + "block": "[[[11,0],[16,0,[29,[[52,[30,0,[\"collapse\"]],\"collapse\"],\" \",[52,[30,0,[\"transitioning\"]],\"collapsing\"],\" \",[52,[30,0,[\"showContent\"]],\"show\"]]]],[17,1],[4,[38,2],[\"mainNode\"],[[\"debugName\",\"bucket\"],[\"create-ref\",[30,0]]]],[4,[38,3],[[30,0,[\"cssStyle\"]]],null],[4,[38,4],[[30,0,[\"_onCollapsedChange\"]],[30,0,[\"collapsed\"]]],null],[4,[38,4],[[30,0,[\"_updateCollapsedSize\"]],[30,0,[\"collapsedSize\"]]],null],[4,[38,4],[[30,0,[\"_updateExpandedSize\"]],[30,0,[\"expandedSize\"]]],null],[12],[1,\"\\n \"],[18,2,null],[1,\"\\n\"],[13],[1,\"\\n\"]],[\"&attrs\",\"&default\"],false,[\"div\",\"if\",\"create-ref\",\"style\",\"did-update\",\"yield\"]]", + "moduleName": "ember-bootstrap/components/bs-collapse.hbs", + "isStrictMode": false + }); + /** + An Ember component that mimics the behaviour of [Bootstrap's collapse.js plugin](http://getbootstrap.com/javascript/#collapse) + + ### Usage + + ```hbs + +
+

Collapse

+

This is collapsible content

+
+
+ ``` + + *Note that only invoking the component in a template as shown above is considered part of its public API. Extending from it (subclassing) is generally not supported, and may break at any time.* + + @class Collapse + @namespace Components + @extends Glimmer.Component + @public + */ + let Collapse = _exports.default = (_dec = (0, _emberRefBucket.ref)('mainNode'), (_class = class Collapse extends _component2.default { + constructor(...args) { + super(...args); + /** + * @property _element + * @type null | HTMLElement + * @private + */ + _initializerDefineProperty(this, "_element", _descriptor, this); + /** + * Collapsed/expanded state + * + * @property collapsed + * @type boolean + * @default true + * @public + */ + _initializerDefineProperty(this, "collapsed", _descriptor2, this); + /** + * True if this item is expanded + * + * @property active + * @private + */ + _defineProperty(this, "active", !this.collapsed); + /** + * true if the component is currently transitioning + * + * @property transitioning + * @type boolean + * @private + */ + _initializerDefineProperty(this, "transitioning", _descriptor3, this); + /** + * The size of the element when collapsed. Defaults to 0. + * + * @property collapsedSize + * @type number + * @default 0 + * @public + */ + _initializerDefineProperty(this, "collapsedSize", _descriptor4, this); + /** + * The size of the element when expanded. When null the value is calculated automatically to fit the containing elements. + * + * @property expandedSize + * @type number + * @default null + * @public + */ + _initializerDefineProperty(this, "expandedSize", _descriptor5, this); + /** + * Usually the size (height) of the element is only set while transitioning, and reseted afterwards. Set to true to always set a size. + * + * @property resetSizeWhenNotCollapsing + * @type boolean + * @default true + * @private + */ + _defineProperty(this, "resetSizeWhenNotCollapsing", true); + /** + * The direction (height/width) of the collapse animation. + * When setting this to 'width' you should also define custom CSS transitions for the width property, as the Bootstrap + * CSS does only support collapsible elements for the height direction. + * + * @property collapseDimension + * @type string + * @default 'height' + * @public + */ + _initializerDefineProperty(this, "collapseDimension", _descriptor6, this); + /** + * The duration of the fade transition + * + * @property transitionDuration + * @type number + * @default 350 + * @public + */ + _initializerDefineProperty(this, "transitionDuration", _descriptor7, this); + _initializerDefineProperty(this, "collapseSize", _descriptor8, this); + } + get collapse() { + return !this.transitioning; + } + get showContent() { + return this.collapse && this.active; + } /** - This method is called once the promise returned by an - adapter's `createRecord`, `updateRecord` or `deleteRecord` - is resolved. - If the data provides a server-generated ID, it will - update the record and the store's indexes. - @method didSaveRecord - @private - @param {InternalModel} internalModel the in-flight internal model - @param {Object} data optional data (see above) - */ - didSaveRecord: function didSaveRecord(internalModel, dataArg) { - var data = void 0; - if (dataArg) { - data = dataArg.data; - } - if (data) { - // normalize relationship IDs into records - this.updateId(internalModel, data); - this._setupRelationshipsForModel(internalModel, data); - } else { - (0, _debug.assert)('Your ' + internalModel.modelName + ' record was saved to the server, but the response does not have an id and no id has been set client side. Records must have ids. Please update the server response to provide an id in the response or generate the id on the client side either before saving the record or while normalizing the response.', internalModel.id); + * Calculates a hash for style attribute. + */ + get cssStyle() { + if ((0, _utils.isNone)(this.collapseSize)) { + return {}; } - - //We first make sure the primary data has been updated - //TODO try to move notification to the user to the end of the runloop - internalModel.adapterDidCommit(data); - }, - - - /** - This method is called once the promise returned by an - adapter's `createRecord`, `updateRecord` or `deleteRecord` - is rejected with a `DS.InvalidError`. - @method recordWasInvalid - @private - @param {InternalModel} internalModel - @param {Object} errors - */ - recordWasInvalid: function recordWasInvalid(internalModel, errors) { - internalModel.adapterDidInvalidate(errors); - }, - - + return { + [this.collapseDimension]: `${this.collapseSize}px` + }; + } /** - This method is called once the promise returned by an - adapter's `createRecord`, `updateRecord` or `deleteRecord` - is rejected (with anything other than a `DS.InvalidError`). - @method recordWasError - @private - @param {InternalModel} internalModel - @param {Error} error - */ - recordWasError: function recordWasError(internalModel, error) { - internalModel.adapterDidError(error); - }, - + * The action to be sent when the element is about to be hidden. + * + * @event onHide + * @public + */ /** - When an adapter's `createRecord`, `updateRecord` or `deleteRecord` - resolves with data, this method extracts the ID from the supplied - data. - @method updateId - @private - @param {InternalModel} internalModel - @param {Object} data - */ - updateId: function updateId(internalModel, data) { - var oldId = internalModel.id; - var modelName = internalModel.modelName; - var id = (0, _coerceId.default)(data.id); - - // ID absolutely can't be missing if the oldID is empty (missing Id in response for a new record) - (0, _debug.assert)('\'' + modelName + '\' was saved to the server, but the response does not have an id and your record does not either.', !(id === null && oldId === null)); - - // ID absolutely can't be different than oldID if oldID is not null - (0, _debug.assert)('\'' + modelName + ':' + oldId + '\' was saved to the server, but the response returned the new id \'' + id + '\'. The store cannot assign a new id to a record that already has an id.', !(oldId !== null && id !== oldId)); - - // ID can be null if oldID is not null (altered ID in response for a record) - // however, this is more than likely a developer error. - if (oldId !== null && id === null) { - (0, _debug.warn)('Your ' + modelName + ' record was saved to the server, but the response does not have an id.', !(oldId !== null && id === null)); - return; - } - - this._internalModelsFor(internalModel.modelName).set(id, internalModel); - - internalModel.setId(id); - }, - + * The action to be sent after the element has been completely hidden (including the CSS transition). + * + * @event onHidden + * @public + */ /** - Returns a map of IDs to client IDs for a given modelName. - @method _internalModelsFor - @private - @param {String} modelName - @return {Object} recordMap - */ - _internalModelsFor: function _internalModelsFor(modelName) { - return this._identityMap.retrieve(modelName); - }, - - - // ................ - // . LOADING DATA . - // ................ + * The action to be sent when the element is about to be shown. + * + * @event onShow + * @public + */ /** - This internal method is used by `push`. - @method _load - @private - @param {Object} data - */ - _load: function _load(data) { - var internalModel = this._internalModelForId(data.type, data.id); - - internalModel.setupData(data); - - this.recordArrayManager.recordDidChange(internalModel); - - return internalModel; - }, - - - /* - In case someone defined a relationship to a mixin, for example: - ``` - let Comment = DS.Model.extend({ - owner: belongsTo('commentable'. { polymorphic: true }) - }); - let Commentable = Ember.Mixin.create({ - comments: hasMany('comment') - }); - ``` - we want to look up a Commentable class which has all the necessary - relationship metadata. Thus, we look up the mixin and create a mock - DS.Model, so we can access the relationship CPs of the mixin (`comments`) - in this case - @private - */ - _modelForMixin: function _modelForMixin(normalizedModelName) { - // container.registry = 2.1 - // container._registry = 1.11 - 2.0 - // container = < 1.11 - var owner = (0, _utils.getOwner)(this); - var mixin = void 0; - - if (owner.factoryFor) { - var MaybeMixin = owner.factoryFor('mixin:' + normalizedModelName); - mixin = MaybeMixin && MaybeMixin.class; - } else { - mixin = owner._lookupFactory('mixin:' + normalizedModelName); - } - - if (mixin) { - var ModelForMixin = _model.default.extend(mixin); - ModelForMixin.reopenClass({ - __isMixin: true, - __mixin: mixin - }); - - //Cache the class as a model - owner.register('model:' + normalizedModelName, ModelForMixin); - } - - return this.modelFactoryFor(normalizedModelName); - }, - + * The action to be sent after the element has been completely shown (including the CSS transition). + * + * @event onShown + * @public + */ /** - Returns the model class for the particular `modelName`. - The class of a model might be useful if you want to get a list of all the - relationship names of the model, see - [`relationshipNames`](http://emberjs.com/api/data/classes/DS.Model.html#property_relationshipNames) - for example. - @method modelFor - @param {String} modelName - @return {DS.Model} - */ - modelFor: function modelFor(modelName) { - (0, _debug.assert)('You need to pass a model name to the store\'s modelFor method', isPresent(modelName)); - (0, _debug.assert)('Passing classes to store methods has been removed. Please pass a dasherized string instead of ' + modelName, typeof modelName === 'string'); - - var normalizedModelName = (0, _normalizeModelName.default)(modelName); - - return this._modelFor(normalizedModelName); - }, - - - /* - @private + * Triggers the show transition + * + * @method show + * @protected */ - _modelFor: function _modelFor(modelName) { - var maybeFactory = this._modelFactoryFor(modelName); - // for factorFor factory/class split - return maybeFactory.class ? maybeFactory.class : maybeFactory; - }, - _modelFactoryFor: function _modelFactoryFor(modelName) { - var factory = this._modelFactoryCache[modelName]; - - if (!factory) { - factory = this.modelFactoryFor(modelName); - - if (!factory) { - //Support looking up mixins as base types for polymorphic relationships - factory = this._modelForMixin(modelName); + show() { + (true && !(this._element) && (0, _debug.assert)('Reference to collapse div element exists.', this._element)); + this.args.onShow?.(); + this.transitioning = true; + this.active = true; + this.collapseSize = this.collapsedSize; + (0, _transitionEnd.default)(this._element, this.transitionDuration).then(() => { + if (this.isDestroyed) { + return; } - if (!factory) { - throw new EmberError('No model was found for \'' + modelName + '\''); + this.transitioning = false; + if (this.resetSizeWhenNotCollapsing) { + this.collapseSize = null; } + this.args.onShown?.(); + }); + (0, _runloop.next)(this, function () { + if (!this.isDestroyed) { + this.collapseSize = this.getExpandedSize('show'); + } + }); + } - // interopt with the future - var klass = (0, _utils.getOwner)(this).factoryFor ? factory.class : factory; - - (0, _debug.assert)('\'' + inspect(klass) + '\' does not appear to be an ember-data model', klass.isModel); - - // TODO: deprecate this - klass.modelName = klass.modelName || modelName; - - this._modelFactoryCache[modelName] = factory; - } - - return factory; - }, - - - /* - @private + /** + * Get the size of the element when expanded + * + * @method getExpandedSize + * @param action + * @return {Number} + * @private */ - modelFactoryFor: function modelFactoryFor(modelName) { - (0, _debug.assert)('You need to pass a model name to the store\'s modelFactoryFor method', isPresent(modelName)); - (0, _debug.assert)('Passing classes to store methods has been removed. Please pass a dasherized string instead of ' + modelName, typeof modelName === 'string'); - - var normalizedModelName = (0, _normalizeModelName.default)(modelName); - var owner = (0, _utils.getOwner)(this); - - if (owner.factoryFor) { - return owner.factoryFor('model:' + normalizedModelName); - } else { - return owner._lookupFactory('model:' + normalizedModelName); + getExpandedSize(action) { + (true && !(this._element) && (0, _debug.assert)('Reference to collapse div element exists.', this._element)); + const expandedSize = this.expandedSize; + if (expandedSize != null) { + return expandedSize; } - }, - + const collapseElement = this._element; + const prefix = action === 'show' ? 'scroll' : 'offset'; + const measureProperty = `${prefix}${this.collapseDimension.substring(0, 1).toUpperCase()}${this.collapseDimension.substring(1)}`; + return collapseElement[measureProperty]; + } /** - Push some data for a given type into the store. - This method expects normalized [JSON API](http://jsonapi.org/) document. This means you have to follow [JSON API specification](http://jsonapi.org/format/) with few minor adjustments: - - record's `type` should always be in singular, dasherized form - - members (properties) should be camelCased - [Your primary data should be wrapped inside `data` property](http://jsonapi.org/format/#document-top-level): - ```js - store.push({ - data: { - // primary data for single record of type `Person` - id: '1', - type: 'person', - attributes: { - firstName: 'Daniel', - lastName: 'Kmak' - } + * Triggers the hide transition + * + * @method hide + * @protected + */ + hide() { + (true && !(this._element) && (0, _debug.assert)('Reference to collapse div element exists.', this._element)); + this.args.onHide?.(); + this.transitioning = true; + this.active = false; + this.collapseSize = this.getExpandedSize('hide'); + (0, _transitionEnd.default)(this._element, this.transitionDuration).then(() => { + if (this.isDestroyed) { + return; } + this.transitioning = false; + if (this.resetSizeWhenNotCollapsing) { + this.collapseSize = null; + } + this.args.onHidden?.(); }); - ``` - [Demo.](http://ember-twiddle.com/fb99f18cd3b4d3e2a4c7) - `data` property can also hold an array (of records): - ```js - store.push({ - data: [ - // an array of records - { - id: '1', - type: 'person', - attributes: { - firstName: 'Daniel', - lastName: 'Kmak' - } - }, - { - id: '2', - type: 'person', - attributes: { - firstName: 'Tom', - lastName: 'Dale' - } - } - ] - }); - ``` - [Demo.](http://ember-twiddle.com/69cdbeaa3702159dc355) - There are some typical properties for `JSONAPI` payload: - * `id` - mandatory, unique record's key - * `type` - mandatory string which matches `model`'s dasherized name in singular form - * `attributes` - object which holds data for record attributes - `DS.attr`'s declared in model - * `relationships` - object which must contain any of the following properties under each relationships' respective key (example path is `relationships.achievements.data`): - - [`links`](http://jsonapi.org/format/#document-links) - - [`data`](http://jsonapi.org/format/#document-resource-object-linkage) - place for primary data - - [`meta`](http://jsonapi.org/format/#document-meta) - object which contains meta-information about relationship - For this model: - ```app/models/person.js - import DS from 'ember-data'; - export default DS.Model.extend({ - firstName: DS.attr('string'), - lastName: DS.attr('string'), - children: DS.hasMany('person') - }); - ``` - To represent the children as IDs: - ```js - { - data: { - id: '1', - type: 'person', - attributes: { - firstName: 'Tom', - lastName: 'Dale' - }, - relationships: { - children: { - data: [ - { - id: '2', - type: 'person' - }, - { - id: '3', - type: 'person' - }, - { - id: '4', - type: 'person' - } - ] - } - } + (0, _runloop.next)(this, function () { + if (!this.isDestroyed) { + this.collapseSize = this.collapsedSize; } + }); + } + _onCollapsedChange() { + const collapsed = this.collapsed; + const active = this.active; + if (collapsed !== active) { + return; } - ``` - [Demo.](http://ember-twiddle.com/343e1735e034091f5bde) - To represent the children relationship as a URL: - ```js - { - data: { - id: '1', - type: 'person', - attributes: { - firstName: 'Tom', - lastName: 'Dale' - }, - relationships: { - children: { - links: { - related: '/people/1/children' - } - } - } - } + if (collapsed === false) { + this.show(); + } else { + this.hide(); } - ``` - If you're streaming data or implementing an adapter, make sure - that you have converted the incoming data into this form. The - store's [normalize](#method_normalize) method is a convenience - helper for converting a json payload into the form Ember Data - expects. - ```js - store.push(store.normalize('person', data)); - ``` - This method can be used both to push in brand new - records, as well as to update existing records. - @method push - @param {Object} data - @return {DS.Model|Array} the record(s) that was created or - updated. - */ - push: function push(data) { - var pushed = this._push(data); - - if (Array.isArray(pushed)) { - var records = pushed.map(function (internalModel) { - return internalModel.getRecord(); - }); - - return records; + } + _updateCollapsedSize() { + if (!this.resetSizeWhenNotCollapsing && this.collapsed && !this.transitioning) { + this.collapseSize = this.collapsedSize; } + } + _updateExpandedSize() { + if (!this.resetSizeWhenNotCollapsing && !this.collapsed && !this.transitioning) { + this.collapseSize = this.expandedSize; + } + } + }, (_descriptor = _applyDecoratedDescriptor(_class.prototype, "_element", [_dec], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return null; + } + }), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "collapsed", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return true; + } + }), _descriptor3 = _applyDecoratedDescriptor(_class.prototype, "transitioning", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return false; + } + }), _descriptor4 = _applyDecoratedDescriptor(_class.prototype, "collapsedSize", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return 0; + } + }), _descriptor5 = _applyDecoratedDescriptor(_class.prototype, "expandedSize", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return null; + } + }), _descriptor6 = _applyDecoratedDescriptor(_class.prototype, "collapseDimension", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return 'height'; + } + }), _descriptor7 = _applyDecoratedDescriptor(_class.prototype, "transitionDuration", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return 350; + } + }), _descriptor8 = _applyDecoratedDescriptor(_class.prototype, "collapseSize", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return null; + } + }), _applyDecoratedDescriptor(_class.prototype, "_onCollapsedChange", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "_onCollapsedChange"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "_updateCollapsedSize", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "_updateCollapsedSize"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "_updateExpandedSize", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "_updateExpandedSize"), _class.prototype)), _class)); + (0, _component.setComponentTemplate)(__COLOCATED_TEMPLATE__, Collapse); +}); +;define("ember-bootstrap/components/bs-contextual-help", ["exports", "@glimmer/component", "@ember/array", "@ember/object", "@ember/runloop", "ember-bootstrap/utils/transition-end", "ember-bootstrap/utils/dom", "ember-bootstrap/utils/decorators/uses-transition", "@ember/debug", "ember", "ember-bootstrap/utils/decorators/arg", "@glimmer/tracking", "ember-ref-bucket"], function (_exports, _component, _array, _object, _runloop, _transitionEnd, _dom, _usesTransition, _debug, _ember, _arg, _tracking, _emberRefBucket) { + "use strict"; - if (pushed === null) { - return null; + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + var _dec, _dec2, _class, _descriptor, _descriptor2, _descriptor3, _descriptor4, _descriptor5, _descriptor6, _descriptor7, _descriptor8, _descriptor9, _descriptor10, _descriptor11, _descriptor12, _descriptor13, _descriptor14, _descriptor15, _descriptor16; + 0; //eaimeta@70e063a35619d71f0,"@glimmer/component",0,"@ember/array",0,"@ember/object",0,"@ember/runloop",0,"ember-bootstrap/utils/transition-end",0,"ember-bootstrap/utils/dom",0,"ember-bootstrap/utils/decorators/uses-transition",0,"@ember/debug",0,"ember",0,"ember-bootstrap/utils/decorators/arg",0,"@glimmer/tracking",0,"ember-ref-bucket"eaimeta@70e063a35619d71f + function _initializerDefineProperty(e, i, r, l) { r && Object.defineProperty(e, i, { enumerable: r.enumerable, configurable: r.configurable, writable: r.writable, value: r.initializer ? r.initializer.call(l) : void 0 }); } + function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } + function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } + function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } + function _applyDecoratedDescriptor(i, e, r, n, l) { var a = {}; return Object.keys(n).forEach(function (i) { a[i] = n[i]; }), a.enumerable = !!a.enumerable, a.configurable = !!a.configurable, ("value" in a || a.initializer) && (a.writable = !0), a = r.slice().reverse().reduce(function (r, n) { return n(i, e, r) || r; }, a), l && void 0 !== a.initializer && (a.value = a.initializer ? a.initializer.call(l) : void 0, a.initializer = void 0), void 0 === a.initializer && (Object.defineProperty(i, e, a), a = null), a; } + function _initializerWarningHelper(r, e) { throw Error("Decorating class property failed. Please ensure that transform-class-properties is enabled and runs after the decorators transform."); } + const HOVERSTATE_NONE = 'none'; + const HOVERSTATE_IN = 'in'; + const HOVERSTATE_OUT = 'out'; + function noop() {} + + /** + @class ContextualHelp + @namespace Components + @extends Glimmer.Component + @private + */ + let ContextualHelp = _exports.default = (_dec = (0, _usesTransition.default)('fade'), _dec2 = (0, _emberRefBucket.ref)('overlayElement'), (_class = class ContextualHelp extends _component.default { + constructor(...args) { + super(...args); + /** + * @property title + * @type string + * @public + */ + /** + * How to position the tooltip/popover - top | bottom | left | right + * + * @property title + * @type string + * @default 'top' + * @public + */ + _initializerDefineProperty(this, "placement", _descriptor, this); + /** + * By default it will dynamically reorient the tooltip/popover based on the available space in the viewport. For + * example, if `placement` is "left", the tooltip/popover will display to the left when possible, otherwise it will + * display right. Set to `false` to force placement according to the `placement` property + * + * @property autoPlacement + * @type boolean + * @default true + * @public + */ + _initializerDefineProperty(this, "autoPlacement", _descriptor2, this); + /** + * You can programmatically show the tooltip/popover by setting this to `true` + * + * @property visible + * @type boolean + * @default false + * @public + */ + _initializerDefineProperty(this, "visible", _descriptor3, this); + /** + * @property inDom + * @type boolean + * @private + */ + _initializerDefineProperty(this, "_inDom", _descriptor4, this); + /** + * Set to false to disable fade animations. + * + * @property fade + * @type boolean + * @default true + * @public + */ + _initializerDefineProperty(this, "fade", _descriptor5, this); + /** + * Used to apply Bootstrap's visibility class + * + * @property showHelp + * @type boolean + * @default false + * @private + */ + _initializerDefineProperty(this, "showHelp", _descriptor6, this); + /** + * Delay showing and hiding the tooltip/popover (ms). Individual delays for showing and hiding can be specified by using the + * `delayShow` and `delayHide` properties. + * + * @property delay + * @type number + * @default 0 + * @public + */ + _initializerDefineProperty(this, "delay", _descriptor7, this); + /** + * Delay showing the tooltip/popover. This property overrides the general delay set with the `delay` property. + * + * @property delayShow + * @type number + * @default 0 + * @public + */ + _initializerDefineProperty(this, "delayShow", _descriptor8, this); + /** + * Delay hiding the tooltip/popover. This property overrides the general delay set with the `delay` property. + * + * @property delayHide + * @type number + * @default 0 + * @public + */ + _initializerDefineProperty(this, "delayHide", _descriptor9, this); + /** + * The duration of the fade transition + * + * @property transitionDuration + * @type number + * @default 150 + * @public + */ + _initializerDefineProperty(this, "transitionDuration", _descriptor10, this); + /** + * Keeps the tooltip/popover within the bounds of this element when `autoPlacement` is true. Can be any valid CSS selector. + * + * @property viewportSelector + * @type string + * @default 'body' + * @see viewportPadding + * @see autoPlacement + * @public + */ + _initializerDefineProperty(this, "viewportSelector", _descriptor11, this); + /** + * Take a padding into account for keeping the tooltip/popover within the bounds of the element given by `viewportSelector`. + * + * @property viewportPadding + * @type number + * @default 0 + * @see viewportSelector + * @see autoPlacement + * @public + */ + _initializerDefineProperty(this, "viewportPadding", _descriptor12, this); + _defineProperty(this, "_parentFinder", self.document ? self.document.createTextNode('') : ''); + /** + * The DOM element that triggers the tooltip/popover. By default it is the parent element of this component. + * You can set this to any CSS selector to have any other element trigger the tooltip/popover. + * + * @property triggerElement + * @type string | null + * @public + */ + _initializerDefineProperty(this, "triggerElement", _descriptor13, this); + /** + * The event(s) that should trigger the tooltip/popover - click | hover | focus. + * You can set this to a single event or multiple events, given as an array or a string separated by spaces. + * + * @property triggerEvents + * @type array|string + * @default 'hover focus' + * @public + */ + _initializerDefineProperty(this, "triggerEvents", _descriptor14, this); + /** + * Current hover state, 'in', 'out' or null + * + * @property hoverState + * @type number + * @private + */ + _defineProperty(this, "hoverState", HOVERSTATE_NONE); + /** + * Current state for events + */ + _defineProperty(this, "hover", false); + _defineProperty(this, "focus", false); + _defineProperty(this, "click", false); + /** + * Ember.run timer + * + * @property timer + * @private + */ + _defineProperty(this, "timer", null); + /** + * Use CSS transitions? + * + * @property usesTransition + * @type boolean + * @readonly + * @private + */ + _initializerDefineProperty(this, "usesTransition", _descriptor15, this); + /** + * The DOM element of the overlay element. + * + * @property overlayElement + * @type object + * @readonly + * @private + */ + _initializerDefineProperty(this, "overlayElement", _descriptor16, this); + } + get inDom() { + return this._inDom ?? !!(this.visible && this.triggerTargetElement); + } + set inDom(value) { + if (this._inDom === value) { + return; } + this._inDom = value; + } + /** + * The DOM element of the arrow element. + * + * @property arrowElement + * @type object + * @readonly + * @private + */ - var record = pushed.getRecord(); - - return record; - }, - - - /* - Push some data in the form of a json-api document into the store, - without creating materialized records. - @method _push - @private - @param {Object} jsonApiDoc - @return {DS.InternalModel|Array} pushed InternalModel(s) - */ - _push: function _push(jsonApiDoc) { - var _this = this; - - var internalModelOrModels = this._backburner.join(function () { - var included = jsonApiDoc.included; - var i = void 0, - length = void 0; - - if (included) { - for (i = 0, length = included.length; i < length; i++) { - _this._pushInternalModel(included[i]); - } - } - - if (Array.isArray(jsonApiDoc.data)) { - length = jsonApiDoc.data.length; - var internalModels = new Array(length); - - for (i = 0; i < length; i++) { - internalModels[i] = _this._pushInternalModel(jsonApiDoc.data[i]); - } - return internalModels; - } + /** + * The wormhole destinationElement + * + * @property destinationElement + * @type object + * @readonly + * @private + */ + get destinationElement() { + return (0, _dom.getDestinationElement)(this); + } - if (jsonApiDoc.data === null) { - return null; + /** + * The DOM element of the viewport element. + * + * @property viewportElement + * @type object + * @readonly + * @private + */ + get viewportElement() { + return document.querySelector(this.viewportSelector); + } + /** + * @method getTriggerTargetElement + * @private + */ + getTriggerTargetElement() { + let triggerElement = this.triggerElement; + let el; + if (!triggerElement) { + el = this._parent; + } else { + el = document.querySelector(triggerElement); + } + (true && !(el) && (0, _debug.assert)('Could not find trigger element for tooltip/popover component', el)); + return el; + } + get _triggerEvents() { + let events = this.triggerEvents; + if (!(0, _array.isArray)(events)) { + events = events.split(' '); + } + return events.map(event => { + switch (event) { + case 'hover': + return ['mouseenter', 'mouseleave']; + case 'focus': + return ['focusin', 'focusout']; + default: + return event; } - - (0, _debug.assert)('Expected an object in the \'data\' property in a call to \'push\' for ' + jsonApiDoc.type + ', but was ' + typeOf(jsonApiDoc.data), typeOf(jsonApiDoc.data) === 'object'); - - return _this._pushInternalModel(jsonApiDoc.data); }); + } - return internalModelOrModels; - }, - _hasModelFor: function _hasModelFor(modelName) { - var owner = (0, _utils.getOwner)(this); - modelName = (0, _normalizeModelName.default)(modelName); - - if (owner.factoryFor) { - return !!owner.factoryFor('model:' + modelName); - } else { - return !!owner._lookupFactory('model:' + modelName); - } - }, - _pushInternalModel: function _pushInternalModel(data) { - var _this2 = this; - - var modelName = data.type; - (0, _debug.assert)('You must include an \'id\' for ' + modelName + ' in an object passed to \'push\'', data.id !== null && data.id !== undefined && data.id !== ''); - (0, _debug.assert)('You tried to push data with a type \'' + modelName + '\' but no model could be found with that name.', this._hasModelFor(modelName)); - - (0, _debug.runInDebug)(function () { - // If ENV.DS_WARN_ON_UNKNOWN_KEYS is set to true and the payload - // contains unknown attributes or relationships, log a warning. - - if (ENV.DS_WARN_ON_UNKNOWN_KEYS) { - var modelClass = _this2._modelFor(modelName); + /** + * If true component will render in place, rather than be wormholed. + * + * @property renderInPlace + * @type boolean + * @default false + * @public + */ - // Check unknown attributes - var unknownAttributes = Object.keys(data.attributes || {}).filter(function (key) { - return !get(modelClass, 'fields').has(key); - }); - var unknownAttributesMessage = 'The payload for \'' + modelName + '\' contains these unknown attributes: ' + unknownAttributes + '. Make sure they\'ve been defined in your model.'; - (0, _debug.warn)(unknownAttributesMessage, unknownAttributes.length === 0, { id: 'ds.store.unknown-keys-in-payload' }); + /** + * @property _renderInPlace + * @type boolean + * @private + */ + get _renderInPlace() { + return this.args.renderInPlace || !this.destinationElement; + } + get shouldShowHelp() { + return this.hover || this.focus || this.click; + } + /** + * This action is called immediately when the tooltip/popover is about to be shown. + * + * @event onShow + * @public + */ - // Check unknown relationships - var unknownRelationships = Object.keys(data.relationships || {}).filter(function (key) { - return !get(modelClass, 'fields').has(key); - }); - var unknownRelationshipsMessage = 'The payload for \'' + modelName + '\' contains these unknown relationships: ' + unknownRelationships + '. Make sure they\'ve been defined in your model.'; - (0, _debug.warn)(unknownRelationshipsMessage, unknownRelationships.length === 0, { id: 'ds.store.unknown-keys-in-payload' }); - } - }); + /** + * This action will be called when the tooltip/popover has been made visible to the user (will wait for CSS transitions to complete). + * + * @event onShown + * @public + */ - // Actually load the record into the store. - var internalModel = this._load(data); + /** + * This action is called immediately when the tooltip/popover is about to be hidden. + * + * @event onHide + * @public + */ - this._setupRelationshipsForModel(internalModel, data); + /** + * This action is called when the tooltip/popover has finished being hidden from the user (will wait for CSS transitions to complete). + * + * @event onHidden + * @public + */ - return internalModel; - }, - _setupRelationshipsForModel: function _setupRelationshipsForModel(internalModel, data) { - if (this._pushedInternalModels.push(internalModel, data) !== 2) { + /** + * Called when a show event has been received + * + * @method enter + * @param e + * @private + */ + enter(e) { + if (e) { + let eventType = e.type === 'focusin' ? 'focus' : 'hover'; + this[eventType] = true; + } + if (this.showHelp || this.hoverState === HOVERSTATE_IN) { + this.hoverState = HOVERSTATE_IN; return; } - - this._backburner.schedule('normalizeRelationships', this, this._setupRelationships); - }, - _setupRelationships: function _setupRelationships() { - var pushed = this._pushedInternalModels; - - for (var i = 0, l = pushed.length; i < l; i += 2) { - // This will convert relationships specified as IDs into DS.Model instances - // (possibly unloaded) and also create the data structures used to track - // relationships. - var internalModel = pushed[i]; - var data = pushed[i + 1]; - setupRelationships(this, internalModel, data); + (0, _runloop.cancel)(this.timer); + this.hoverState = HOVERSTATE_IN; + if (!this.delayShow) { + return this.show(); } - - pushed.length = 0; - }, - + this.timer = (0, _runloop.later)(this, function () { + if (this.hoverState === HOVERSTATE_IN) { + this.show(); + } + }, this.delayShow); + } /** - Push some raw data into the store. - This method can be used both to push in brand new - records, as well as to update existing records. You - can push in more than one type of object at once. - All objects should be in the format expected by the - serializer. - ```app/serializers/application.js - import DS from 'ember-data'; - export default DS.ActiveModelSerializer; - ``` - ```js - let pushData = { - posts: [ - { id: 1, post_title: "Great post", comment_ids: [2] } - ], - comments: [ - { id: 2, comment_body: "Insightful comment" } - ] + * Called when a hide event has been received + * + * @method leave + * @param e + * @private + */ + leave(e) { + if (e) { + let eventType = e.type === 'focusout' ? 'focus' : 'hover'; + this[eventType] = false; } - store.pushPayload(pushData); - ``` - By default, the data will be deserialized using a default - serializer (the application serializer if it exists). - Alternatively, `pushPayload` will accept a model type which - will determine which serializer will process the payload. - ```app/serializers/application.js - import DS from 'ember-data'; - export default DS.ActiveModelSerializer; - ``` - ```app/serializers/post.js - import DS from 'ember-data'; - export default DS.JSONSerializer; - ``` - ```js - store.pushPayload('comment', pushData); // Will use the application serializer - store.pushPayload('post', pushData); // Will use the post serializer - ``` - @method pushPayload - @param {String} modelName Optionally, a model type used to determine which serializer will be used - @param {Object} inputPayload - */ - pushPayload: function pushPayload(modelName, inputPayload) { - var serializer = void 0; - var payload = void 0; - if (!inputPayload) { - payload = modelName; - serializer = defaultSerializer(this); - (0, _debug.assert)('You cannot use \'store#pushPayload\' without a modelName unless your default serializer defines \'pushPayload\'', typeof serializer.pushPayload === 'function'); - } else { - payload = inputPayload; - (0, _debug.assert)('Passing classes to store methods has been removed. Please pass a dasherized string instead of ' + modelName, typeof modelName === 'string'); - var normalizedModelName = (0, _normalizeModelName.default)(modelName); - serializer = this.serializerFor(normalizedModelName); + if (this.shouldShowHelp) { + return; } - if ((0, _features.default)('ds-pushpayload-return')) { - return serializer.pushPayload(this, payload); - } else { - serializer.pushPayload(this, payload); + (0, _runloop.cancel)(this.timer); + this.hoverState = HOVERSTATE_OUT; + if (!this.delayHide) { + return this.hide(); } - }, - + this.timer = (0, _runloop.later)(() => { + if (this.hoverState === HOVERSTATE_OUT) { + this.hide(); + } + }, this.delayHide); + } /** - `normalize` converts a json payload into the normalized form that - [push](#method_push) expects. - Example - ```js - socket.on('message', function(message) { - let modelName = message.model; - let data = message.data; - store.push(store.normalize(modelName, data)); - }); - ``` - @method normalize - @param {String} modelName The name of the model type for this payload - @param {Object} payload - @return {Object} The normalized payload - */ - normalize: function normalize(modelName, payload) { - (0, _debug.assert)('You need to pass a model name to the store\'s normalize method', isPresent(modelName)); - (0, _debug.assert)('Passing classes to store methods has been removed. Please pass a dasherized string instead of ' + inspect(modelName), typeof modelName === 'string'); - var normalizedModelName = (0, _normalizeModelName.default)(modelName); - var serializer = this.serializerFor(normalizedModelName); - var model = this._modelFor(normalizedModelName); - return serializer.normalize(model, payload); - }, - + * Called for a click event + * + * @method toggle + * @private + */ + toggle() { + this.click = !this.click; + if (this.shouldShowHelp) { + this.enter(); + } else { + this.leave(); + } + } /** - Build a brand new record for a given type, ID, and - initial data. - @method buildRecord - @private - @param {String} modelName - @param {String} id - @param {Object} data - @return {InternalModel} internal model - */ - buildInternalModel: function buildInternalModel(modelName, id, data) { - - (0, _debug.assert)('You can no longer pass a modelClass as the first argument to store.buildInternalModel. Pass modelName instead.', typeof modelName === 'string'); - - var recordMap = this._internalModelsFor(modelName); - - (0, _debug.assert)('The id ' + id + ' has already been used with another record for modelClass \'' + modelName + '\'.', !id || !recordMap.get(id)); - - // lookupFactory should really return an object that creates - // instances with the injections applied - var internalModel = new _internalModel5.default(modelName, id, this, data); - - recordMap.add(internalModel, id); - - return internalModel; - }, - - - //Called by the state machine to notify the store that the record is ready to be interacted with - recordWasLoaded: function recordWasLoaded(record) { - this.recordArrayManager.recordWasLoaded(record); - }, + * Show the tooltip/popover + * + * @method show + * @private + */ + show() { + if (this.isDestroyed || this.isDestroying) { + return; + } + if (false === this.args.onShow?.(this)) { + return; + } + this.inDom = true; + (0, _runloop.schedule)('afterRender', this, this._show); + } + _show(skipTransition = false) { + if (this.isDestroyed || this.isDestroying) { + return; + } + this.showHelp = true; + // If this is a touch-enabled device we add extra + // empty mouseover listeners to the body's immediate children; + // only needed because of broken event delegation on iOS + // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html - // ............... - // . DESTRUCTION . - // ............... + // See https://github.com/twbs/bootstrap/pull/22481 + if ('ontouchstart' in document.documentElement) { + let { + children + } = document.body; + for (let i = 0; i < children.length; i++) { + children[i].addEventListener('mouseover', noop); + } + } + let tooltipShowComplete = () => { + if (this.isDestroyed) { + return; + } + let prevHoverState = this.hoverState; + this.args.onShown?.(this); + this.hoverState = HOVERSTATE_NONE; + if (prevHoverState === HOVERSTATE_OUT) { + this.leave(); + } + }; + if (skipTransition === false && this.usesTransition) { + (0, _transitionEnd.default)(this.overlayElement, this.transitionDuration).then(tooltipShowComplete); + } else { + tooltipShowComplete(); + } + } /** - When a record is destroyed, this un-indexes it and - removes it from any record arrays so it can be GCed. - @method _removeFromIdMap - @private - @param {InternalModel} internalModel - */ - _removeFromIdMap: function _removeFromIdMap(internalModel) { - var recordMap = this._internalModelsFor(internalModel.modelName); - var id = internalModel.id; - - recordMap.remove(internalModel, id); - }, - - - // ...................... - // . PER-TYPE ADAPTERS - // ...................... + * Position the tooltip/popover's arrow + * + * @method replaceArrow + * @param delta + * @param dimension + * @param isVertical + * @private + */ + replaceArrow(delta, dimension, isVertical) { + let el = this.arrowElement; + el.style[isVertical ? 'left' : 'top'] = `${50 * (1 - delta / dimension)}%`; + el.style[isVertical ? 'top' : 'left'] = null; + } /** - Returns an instance of the adapter for a given type. For - example, `adapterFor('person')` will return an instance of - `App.PersonAdapter`. - If no `App.PersonAdapter` is found, this method will look - for an `App.ApplicationAdapter` (the default adapter for - your entire application). - If no `App.ApplicationAdapter` is found, it will return - the value of the `defaultAdapter`. - @method adapterFor - @public - @param {String} modelName - @return DS.Adapter - */ - adapterFor: function adapterFor(modelName) { - (0, _debug.assert)('You need to pass a model name to the store\'s adapterFor method', isPresent(modelName)); - (0, _debug.assert)('Passing classes to store.adapterFor has been removed. Please pass a dasherized string instead of ' + modelName, typeof modelName === 'string'); - var normalizedModelName = (0, _normalizeModelName.default)(modelName); - - return this._instanceCache.get('adapter', normalizedModelName); - }, - + * Hide the tooltip/popover + * + * @method hide + * @private + */ + hide() { + if (this.isDestroyed) { + return; + } + if (false === this.args.onHide?.(this)) { + return; + } + let tooltipHideComplete = () => { + if (this.isDestroyed) { + return; + } + if (this.hoverState !== HOVERSTATE_IN) { + this.inDom = false; + } + this.args.onHidden?.(this); + }; + this.showHelp = false; - // .............................. - // . RECORD CHANGE NOTIFICATION . - // .............................. + // if this is a touch-enabled device we remove the extra + // empty mouseover listeners we added for iOS support + if ('ontouchstart' in document.documentElement) { + let { + children + } = document.body; + for (let i = 0; i < children.length; i++) { + children[i].removeEventListener('mouseover', noop); + } + } + if (this.usesTransition) { + (0, _transitionEnd.default)(this.overlayElement, this.transitionDuration).then(tooltipHideComplete); + } else { + tooltipHideComplete(); + } + this.hoverState = HOVERSTATE_NONE; + } /** - Returns an instance of the serializer for a given type. For - example, `serializerFor('person')` will return an instance of - `App.PersonSerializer`. - If no `App.PersonSerializer` is found, this method will look - for an `App.ApplicationSerializer` (the default serializer for - your entire application). - if no `App.ApplicationSerializer` is found, it will attempt - to get the `defaultSerializer` from the `PersonAdapter` - (`adapterFor('person')`). - If a serializer cannot be found on the adapter, it will fall back - to an instance of `DS.JSONSerializer`. - @method serializerFor - @public - @param {String} modelName the record to serialize - @return {DS.Serializer} - */ - serializerFor: function serializerFor(modelName) { - (0, _debug.assert)('You need to pass a model name to the store\'s serializerFor method', isPresent(modelName)); - (0, _debug.assert)('Passing classes to store.serializerFor has been removed. Please pass a dasherized string instead of ' + modelName, typeof modelName === 'string'); - var normalizedModelName = (0, _normalizeModelName.default)(modelName); - - return this._instanceCache.get('serializer', normalizedModelName); - }, - lookupAdapter: function lookupAdapter(name) { - (0, _debug.deprecate)('Use of lookupAdapter is deprecated, use adapterFor instead.', false, { - id: 'ds.store.lookupAdapter', - until: '3.0' - }); - return this.adapterFor(name); - }, - lookupSerializer: function lookupSerializer(name) { - (0, _debug.deprecate)('Use of lookupSerializer is deprecated, use serializerFor instead.', false, { - id: 'ds.store.lookupSerializer', - until: '3.0' + * @method addListeners + * @private + */ + addListeners() { + let target = this.triggerTargetElement; + this._triggerEvents.forEach(event => { + if ((0, _array.isArray)(event)) { + let [inEvent, outEvent] = event; + target.addEventListener(inEvent, this._handleEnter); + target.addEventListener(outEvent, this._handleLeave); + } else { + target.addEventListener(event, this._handleToggle); + } }); - return this.serializerFor(name); - }, - willDestroy: function willDestroy() { - this._super.apply(this, arguments); - this._pushedInternalModels = null; - this.recordArrayManager.destroy(); - this._instanceCache.destroy(); + } - this.unloadAll(); - }, - _updateRelationshipState: function _updateRelationshipState(relationship) { - var _this3 = this; + /** + * @method removeListeners + * @private + */ + removeListeners() { + try { + let target = this.triggerTargetElement; + this._triggerEvents.forEach(event => { + if ((0, _array.isArray)(event)) { + let [inEvent, outEvent] = event; + target.removeEventListener(inEvent, this._handleEnter); + target.removeEventListener(outEvent, this._handleLeave); + } else { + target.removeEventListener(event, this._handleToggle); + } + }); + } catch (e) {} // eslint-disable-line no-empty + } - if (this._updatedRelationships.push(relationship) !== 1) { + /** + * @method handleTriggerEvent + * @private + */ + handleTriggerEvent(handler, e) { + let overlayElement = this.overlayElement; + if (overlayElement && overlayElement.contains(e.target)) { return; } - - this._backburner.join(function () { - _this3._backburner.schedule('syncRelationships', _this3, _this3._flushUpdatedRelationships); - }); - }, - _flushUpdatedRelationships: function _flushUpdatedRelationships() { - var updated = this._updatedRelationships; - - for (var i = 0, l = updated.length; i < l; i++) { - updated[i].flushCanonical(); - } - - updated.length = 0; - }, - _updateInternalModel: function _updateInternalModel(internalModel) { - if (this._updatedInternalModels.push(internalModel) !== 1) { + return handler.call(this, e); + } + _handleEnter(e) { + this.handleTriggerEvent(this.enter, e); + } + _handleLeave(e) { + this.handleTriggerEvent(this.leave, e); + } + _handleToggle(e) { + this.handleTriggerEvent(this.toggle, e); + } + close() { + // Make sure our click state is off, otherwise the next click would + // close the already-closed tooltip/popover. We don't need to worry + // about this for hover/focus because those aren't "stateful" toggle + // events like click. + this.click = false; + this.hide(); + } + setup() { + if (typeof FastBoot !== 'undefined') { + // ember-render-helpers calls this also in FastBoot, so guard against this return; } - - emberRun.schedule('actions', this, this._flushUpdatedInternalModels); - }, - _flushUpdatedInternalModels: function _flushUpdatedInternalModels() { - var updated = this._updatedInternalModels; - - for (var i = 0, l = updated.length; i < l; i++) { - updated[i]._triggerDeferredTriggers(); + let parent = this._parentFinder.parentNode; + // In the rare case of using FastBoot w/ rehydration, the parent finder TextNode rendered by FastBoot will be reused, + // so our own instance on the component is not rendered, only exists here as detached from DOM and thus has no parent. + // In this case we try to use Ember's private API as a fallback. + // Related: https://github.com/emberjs/rfcs/issues/168 + if (!parent) { + try { + parent = _ember.default.ViewUtils.getViewBounds(this).parentElement; + } catch (e) { + // we catch the possibly broken private API call, the component can still work if the trigger element is defined + // using a CSS selector. + } } + this._parent = parent; - updated.length = 0; - }, - _pushResourceIdentifier: function _pushResourceIdentifier(relationship, resourceIdentifier) { - if (isNone(resourceIdentifier)) { - return; + // Look for target element after rendering has finished, in case the target DOM element is rendered *after* us + // see https://github.com/kaliber5/ember-bootstrap/issues/1329 + (0, _runloop.schedule)('afterRender', () => { + this.triggerTargetElement = this.getTriggerTargetElement(); + this.addListeners(); + if (this.visible) { + (0, _runloop.next)(this, this.show); + } + }); + } + showOrHide() { + if (this.args.visible) { + (0, _runloop.next)(this, this.show); + } else { + (0, _runloop.next)(this, this.hide); } + } + willDestroy() { + super.willDestroy(...arguments); + this.removeListeners(); + } + }, (_descriptor = _applyDecoratedDescriptor(_class.prototype, "placement", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return 'top'; + } + }), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "autoPlacement", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return true; + } + }), _descriptor3 = _applyDecoratedDescriptor(_class.prototype, "visible", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return false; + } + }), _descriptor4 = _applyDecoratedDescriptor(_class.prototype, "_inDom", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: null + }), _descriptor5 = _applyDecoratedDescriptor(_class.prototype, "fade", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return true; + } + }), _descriptor6 = _applyDecoratedDescriptor(_class.prototype, "showHelp", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return this.visible; + } + }), _descriptor7 = _applyDecoratedDescriptor(_class.prototype, "delay", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return 0; + } + }), _descriptor8 = _applyDecoratedDescriptor(_class.prototype, "delayShow", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return this.args.delay ?? 0; + } + }), _descriptor9 = _applyDecoratedDescriptor(_class.prototype, "delayHide", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return this.args.delay ?? 0; + } + }), _descriptor10 = _applyDecoratedDescriptor(_class.prototype, "transitionDuration", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return 150; + } + }), _descriptor11 = _applyDecoratedDescriptor(_class.prototype, "viewportSelector", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return 'body'; + } + }), _descriptor12 = _applyDecoratedDescriptor(_class.prototype, "viewportPadding", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return 0; + } + }), _descriptor13 = _applyDecoratedDescriptor(_class.prototype, "triggerElement", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return null; + } + }), _descriptor14 = _applyDecoratedDescriptor(_class.prototype, "triggerEvents", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return 'hover focus'; + } + }), _descriptor15 = _applyDecoratedDescriptor(_class.prototype, "usesTransition", [_dec], { + configurable: true, + enumerable: true, + writable: true, + initializer: null + }), _descriptor16 = _applyDecoratedDescriptor(_class.prototype, "overlayElement", [_dec2], { + configurable: true, + enumerable: true, + writable: true, + initializer: null + }), _applyDecoratedDescriptor(_class.prototype, "_handleEnter", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "_handleEnter"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "_handleLeave", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "_handleLeave"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "_handleToggle", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "_handleToggle"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "close", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "close"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "setup", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "setup"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "showOrHide", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "showOrHide"), _class.prototype)), _class)); +}); +;define("ember-bootstrap/components/bs-contextual-help/element", ["exports", "@ember/object", "@glimmer/component", "ember-bootstrap/utils/decorators/arg", "@glimmer/tracking", "ember-ref-bucket"], function (_exports, _object, _component, _arg, _tracking, _emberRefBucket) { + "use strict"; - (0, _debug.assert)('A ' + relationship.record.modelName + ' record was pushed into the store with the value of ' + relationship.key + ' being ' + inspect(resourceIdentifier) + ', but ' + relationship.key + ' is a belongsTo relationship so the value must not be an array. You should probably check your data payload or serializer.', !Array.isArray(resourceIdentifier)); + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + var _dec, _class, _descriptor, _descriptor2, _descriptor3, _descriptor4, _descriptor5; + 0; //eaimeta@70e063a35619d71f0,"@ember/object",0,"@glimmer/component",0,"ember-bootstrap/utils/decorators/arg",0,"@glimmer/tracking",0,"@embroider/macros",0,"ember-ref-bucket"eaimeta@70e063a35619d71f + function _initializerDefineProperty(e, i, r, l) { r && Object.defineProperty(e, i, { enumerable: r.enumerable, configurable: r.configurable, writable: r.writable, value: r.initializer ? r.initializer.call(l) : void 0 }); } + function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } + function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } + function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } + function _applyDecoratedDescriptor(i, e, r, n, l) { var a = {}; return Object.keys(n).forEach(function (i) { a[i] = n[i]; }), a.enumerable = !!a.enumerable, a.configurable = !!a.configurable, ("value" in a || a.initializer) && (a.writable = !0), a = r.slice().reverse().reduce(function (r, n) { return n(i, e, r) || r; }, a), l && void 0 !== a.initializer && (a.value = a.initializer ? a.initializer.call(l) : void 0, a.initializer = void 0), void 0 === a.initializer && (Object.defineProperty(i, e, a), a = null), a; } + function _initializerWarningHelper(r, e) { throw Error("Decorating class property failed. Please ensure that transform-class-properties is enabled and runs after the decorators transform."); } + /** + Internal (abstract) component for contextual help markup. Should not be used directly. + + @class ContextualHelpElement + @namespace Components + @extends Glimmer.Component + @private + */ + let ContextualHelpElement = _exports.default = (_dec = (0, _emberRefBucket.trackedRef)('popperElement'), (_class = class ContextualHelpElement extends _component.default { + constructor(...args) { + super(...args); + /** + * @property placement + * @type string + * @default 'top' + * @public + */ + _initializerDefineProperty(this, "placement", _descriptor, this); + _initializerDefineProperty(this, "actualPlacement", _descriptor2, this); + /** + * @property fade + * @type boolean + * @default true + * @public + */ + _initializerDefineProperty(this, "fade", _descriptor3, this); + /** + * @property showHelp + * @type boolean + * @default false + * @public + */ + _initializerDefineProperty(this, "showHelp", _descriptor4, this); + /** + * If true component will render in place, rather than be wormholed. + * + * @property renderInPlace + * @type boolean + * @default true + * @public + */ + /** + * Which element to align to + * + * @property popperTarget + * @type {string|HTMLElement} + * @public + */ + /** + * @property autoPlacement + * @type boolean + * @default true + * @public + */ + /** + * The DOM element of the viewport element. + * + * @property viewportElement + * @type object + * @public + */ + /** + * Take a padding into account for keeping the tooltip/popover within the bounds of the element given by `viewportElement`. + * + * @property viewportPadding + * @type number + * @default 0 + * @public + */ + /** + * @property arrowClass + * @private + */ + _defineProperty(this, "arrowClass", 'arrow'); + _defineProperty(this, "placementClassPrefix", ''); + _defineProperty(this, "offset", [0, 0]); + _initializerDefineProperty(this, "popperElement", _descriptor5, this); + } + /** + * popper.js modifier config + * + * @property popperModifiers + * @type {object} + * @private + */ + get popperOptions() { + let options = { + placement: this.placement, + onFirstUpdate: this.updatePlacement + }; - //TODO:Better asserts - return this._internalModelForId(resourceIdentifier.type, resourceIdentifier.id); - }, - _pushResourceIdentifiers: function _pushResourceIdentifiers(relationship, resourceIdentifiers) { - if (isNone(resourceIdentifiers)) { + // We need popperElement, so we wait for this getter to recompute once it's available + if (!this.popperElement) { + return options; + } + options.modifiers = [{ + name: 'arrow', + options: { + element: this.popperElement.querySelector(`.${this.arrowClass}`), + padding: 4 + } + }, { + name: 'offset', + options: { + offset: this.offset + } + }, { + name: 'preventOverflow', + enabled: this.args.autoPlacement, + options: { + boundary: this.args.viewportElement, + padding: this.args.viewportPadding + } + }, { + name: 'flip', + enabled: this.args.autoPlacement + }, { + name: 'onChange', + enabled: true, + phase: 'afterWrite', + fn: this.updatePlacement + }]; + return options; + } + get actualPlacementClass() { + let ending = this.actualPlacement; + { + if (ending === 'right') { + ending = 'end'; + } + if (ending === 'left') { + ending = 'start'; + } + } + return this.placementClassPrefix + ending; + } + updatePlacement(state) { + // normalize argument + state = state.state ?? state; + if (this.actualPlacement === state.placement) { return; } + this.actualPlacement = state.placement; + } + }, (_descriptor = _applyDecoratedDescriptor(_class.prototype, "placement", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return 'top'; + } + }), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "actualPlacement", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return this.args.placement; + } + }), _descriptor3 = _applyDecoratedDescriptor(_class.prototype, "fade", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return true; + } + }), _descriptor4 = _applyDecoratedDescriptor(_class.prototype, "showHelp", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return false; + } + }), _descriptor5 = _applyDecoratedDescriptor(_class.prototype, "popperElement", [_dec], { + configurable: true, + enumerable: true, + writable: true, + initializer: null + }), _applyDecoratedDescriptor(_class.prototype, "updatePlacement", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "updatePlacement"), _class.prototype)), _class)); +}); +;define("ember-bootstrap/components/bs-dropdown", ["exports", "@ember/component", "@ember/object", "@glimmer/component", "@ember/debug", "@glimmer/tracking", "@ember/runloop", "@ember/template-factory"], function (_exports, _component, _object, _component2, _debug, _tracking, _runloop, _templateFactory) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + var _class, _descriptor, _descriptor2, _descriptor3; + 0; //eaimeta@70e063a35619d71f0,"@ember/object",0,"@glimmer/component",0,"@ember/debug",0,"@embroider/macros",0,"@glimmer/tracking",0,"@ember/runloop",0,"@ember/template-factory",0,"@ember/component"eaimeta@70e063a35619d71f + function _initializerDefineProperty(e, i, r, l) { r && Object.defineProperty(e, i, { enumerable: r.enumerable, configurable: r.configurable, writable: r.writable, value: r.initializer ? r.initializer.call(l) : void 0 }); } + function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } + function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } + function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } + function _applyDecoratedDescriptor(i, e, r, n, l) { var a = {}; return Object.keys(n).forEach(function (i) { a[i] = n[i]; }), a.enumerable = !!a.enumerable, a.configurable = !!a.configurable, ("value" in a || a.initializer) && (a.writable = !0), a = r.slice().reverse().reduce(function (r, n) { return n(i, e, r) || r; }, a), l && void 0 !== a.initializer && (a.value = a.initializer ? a.initializer.call(l) : void 0, a.initializer = void 0), void 0 === a.initializer && (Object.defineProperty(i, e, a), a = null), a; } + function _initializerWarningHelper(r, e) { throw Error("Decorating class property failed. Please ensure that transform-class-properties is enabled and runs after the decorators transform."); } + const __COLOCATED_TEMPLATE__ = (0, _templateFactory.createTemplateFactory)( + /* + {{! @glint-nocheck }} + {{#let (element this.htmlTag) as |Tag|}} + + {{yield + (hash + button=(component (ensure-safe-component (bs-default @buttonComponent (component "bs-dropdown/button"))) + isOpen=this.isOpen + onClick=this.toggleDropdown + onKeyDown=this.handleKeyEvent + registerChildElement=this.registerChildElement + unregisterChildElement=this.unregisterChildElement + ) + toggle=(component (ensure-safe-component (bs-default @toggleComponent (component "bs-dropdown/toggle"))) + isOpen=this.isOpen + inNav=@inNav + onClick=this.toggleDropdown + onKeyDown=this.handleKeyEvent + registerChildElement=this.registerChildElement + unregisterChildElement=this.unregisterChildElement + ) + menu=(component (ensure-safe-component (bs-default @menuComponent (component "bs-dropdown/menu"))) + isOpen=this.isOpen + inNav=@inNav + direction=this.direction + toggleElement=this.toggleElement + registerChildElement=this.registerChildElement + unregisterChildElement=this.unregisterChildElement + ) + toggleDropdown=this.toggleDropdown + openDropdown=this.openDropdown + closeDropdown=this.closeDropdown + isOpen=this.isOpen + ) + }} + {{#if this.isOpen}} + {{on-document "keydown" this.handleKeyEvent}} + {{on-document "click" this.closeHandler capture=true}} + {{on-document "keyup" this.closeHandler}} + {{/if}} + + + {{/let}} + */ + { + "id": "cC1Fwavo", + "block": "[[[44,[[28,[37,1],[[30,0,[\"htmlTag\"]]],null]],[[[1,\" \"],[8,[30,1],[[16,0,[29,[[30,0,[\"containerClass\"]],\"\\n \",[52,[30,0,[\"inNav\"]],\"nav-item\"],\"\\n \",[52,[30,0,[\"isOpen\"]],\"show\"]]]],[17,2],[4,[38,3],[[30,0,[\"updateIsOpen\"]],[30,3]],null]],null,[[\"default\"],[[[[1,\"\\n \"],[18,8,[[28,[37,5],null,[[\"button\",\"toggle\",\"menu\",\"toggleDropdown\",\"openDropdown\",\"closeDropdown\",\"isOpen\"],[[50,[28,[37,7],[[28,[37,8],[[30,4],[50,\"bs-dropdown/button\",0,null,null]],null]],null],0,null,[[\"isOpen\",\"onClick\",\"onKeyDown\",\"registerChildElement\",\"unregisterChildElement\"],[[30,0,[\"isOpen\"]],[30,0,[\"toggleDropdown\"]],[30,0,[\"handleKeyEvent\"]],[30,0,[\"registerChildElement\"]],[30,0,[\"unregisterChildElement\"]]]]],[50,[28,[37,7],[[28,[37,8],[[30,5],[50,\"bs-dropdown/toggle\",0,null,null]],null]],null],0,null,[[\"isOpen\",\"inNav\",\"onClick\",\"onKeyDown\",\"registerChildElement\",\"unregisterChildElement\"],[[30,0,[\"isOpen\"]],[30,6],[30,0,[\"toggleDropdown\"]],[30,0,[\"handleKeyEvent\"]],[30,0,[\"registerChildElement\"]],[30,0,[\"unregisterChildElement\"]]]]],[50,[28,[37,7],[[28,[37,8],[[30,7],[50,\"bs-dropdown/menu\",0,null,null]],null]],null],0,null,[[\"isOpen\",\"inNav\",\"direction\",\"toggleElement\",\"registerChildElement\",\"unregisterChildElement\"],[[30,0,[\"isOpen\"]],[30,6],[30,0,[\"direction\"]],[30,0,[\"toggleElement\"]],[30,0,[\"registerChildElement\"]],[30,0,[\"unregisterChildElement\"]]]]],[30,0,[\"toggleDropdown\"]],[30,0,[\"openDropdown\"]],[30,0,[\"closeDropdown\"]],[30,0,[\"isOpen\"]]]]]]],[1,\"\\n\"],[41,[30,0,[\"isOpen\"]],[[[1,\" \"],[1,[28,[35,9],[\"keydown\",[30,0,[\"handleKeyEvent\"]]],null]],[1,\"\\n \"],[1,[28,[35,9],[\"click\",[30,0,[\"closeHandler\"]]],[[\"capture\"],[true]]]],[1,\"\\n \"],[1,[28,[35,9],[\"keyup\",[30,0,[\"closeHandler\"]]],null]],[1,\"\\n\"]],[]],null],[1,\"\\n \"]],[]]]]],[1,\"\\n\"]],[1]]]],[\"Tag\",\"&attrs\",\"@open\",\"@buttonComponent\",\"@toggleComponent\",\"@inNav\",\"@menuComponent\",\"&default\"],false,[\"let\",\"element\",\"if\",\"did-update\",\"yield\",\"hash\",\"component\",\"ensure-safe-component\",\"bs-default\",\"on-document\"]]", + "moduleName": "ember-bootstrap/components/bs-dropdown.hbs", + "isStrictMode": false + }); + const ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key + const SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key + const TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key + const ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key + const ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key - (0, _debug.assert)('A ' + relationship.record.modelName + ' record was pushed into the store with the value of ' + relationship.key + ' being \'' + inspect(resourceIdentifiers) + '\', but ' + relationship.key + ' is a hasMany relationship so the value must be an array. You should probably check your data payload or serializer.', Array.isArray(resourceIdentifiers)); + const SUPPORTED_KEYCODES = [ESCAPE_KEYCODE, ARROW_DOWN_KEYCODE, ARROW_UP_KEYCODE]; - var _internalModels = new Array(resourceIdentifiers.length); - for (var i = 0; i < resourceIdentifiers.length; i++) { - _internalModels[i] = this._pushResourceIdentifier(relationship, resourceIdentifiers[i]); - } - return _internalModels; + /** + Bootstrap style [dropdown menus](http://getbootstrap.com/components/#dropdowns), consisting + of a toggle element, and the dropdown menu itself. + + ### Usage + + Use this component together with the yielded contextual components: + * [Components.DropdownToggle](Components.DropdownToggle.html) + * [Components.DropdownButton](Components.DropdownButton.html) + * [Components.DropdownMenu](Components.DropdownMenu.html) + * [Components.DropdownMenuItem](Components.DropdownMenuItem.html) + * [Components.DropdownMenuDivider](Components.DropdownMenuDivider.html) + * [Components.DropdownMenuLinkTo](Components.DropdownMenuLinkTo.html) + + Furthermore references to the following actions are yielded: + + * `toggleDropdown` + * `openDropdown` + * `closeDropdown` + + ```hbs + + Dropdown + + + Something + + + Something different + + + + ``` + + If you need to use dropdowns in a [nav](Components.Nav.html), use the `bs-nav.dropdown` + contextual component rather than a standalone dropdown to ensure the correct styling + regardless of your Bootstrap version. + + > Note: the use of angle brackets `` as shown above is only supported for Ember >= 3.10, as it relies on its + > Ember's native implementation of the [`LinkComponent`](https://api.emberjs.com/ember/3.12/classes/Ember.Templates.helpers/methods/link-to?anchor=link-to). + > For older Ember versions please use the legacy syntax with positional arguments: + > `{{#ddm.link-to "bar" this.model}}Bar{{/ddm.link-to}}` + + ### Button dropdowns + + To use a button as the dropdown toggle element (see http://getbootstrap.com/components/#btn-dropdowns), use the + `Components.DropdownButton` component as the toggle: + + ```hbs + + Dropdown + + + Something + + + Something different + + + + ``` + + It has all the functionality of a `Components.Button` with additional dropdown support. + + ### Split button dropdowns + + To have a regular button with a dropdown button as in http://getbootstrap.com/components/#btn-dropdowns-split, use a + `Components.Button` component and a `Components.DropdownButton`: + + ```hbs + + Dropdown + Dropdown + + + Something + + + Something different + + + + ``` + + ### Dropup style + + Set the `direction` property to "up" to switch to a "dropup" style: + + ```hbs + + ... + + ``` + + ### Open, close or toggle the dropdown programmatically + + If you wanted to control when the dropdown opens and closes programmatically, the `bs-dropdown` component yields the + `openDropdown`, `closeDropdown` and `toggleDropdown` actions which you can then pass to your own handlers. For example: + + ```hbs + + Dropdown + Dropdown + + {{#each this.items as |item|}} + + + {{item.text}} + + + {{/each}} + + + ``` + + Then in your controller or component, optionally close the dropdown: + + ```js + ... + actions: { + handleDropdownClicked(item, closeDropdown) { + if(item.isTheRightOne) { + this.chosenItems.pushObject(item); + closeDropdown(); + } else { + this.set('item', this.getRandomItems()); + } + }, + } + ``` + + + ### Bootstrap 3/4 Notes + + If you need to use dropdowns in a [nav](Components.Nav.html), use the `bs-nav.dropdown` + contextual component rather than a standalone dropdown to ensure the correct styling + regardless of your Bootstrap version. + + If you use the [dropdown divider](Components.DropdownMenuDivider), you don't have to worry + about differences in the markup between versions. + + Be sure to use the [dropdown menu link-to](Component.DropdownMenuLinkTo), for in-application + links as dropdown menu items. This is essential for proper styling regardless of Bootstrap + version and will also provide automatic `active` highlighting on dropdown menu items. If you + wish to have a dropdown menu item refer to an external link, be sure to apply the `dropdown-item` + class to the `` tag for Bootstrap 4 compatibility. + + The dropdown menu will be positioned using the `popper.js` library, just as the original Bootstrap + version does. This also allows you to set `renderInPlace=false` on the menu component to render it in a wormhole, + which you might want to do if you experience clipping issues by an outer `overflow: hidden` element. + + *Note that only invoking the component in a template as shown above is considered part of its public API. Extending from it (subclassing) is generally not supported, and may break at any time.* + + @class Dropdown + @namespace Components + @extends Component + @public + s*/ + let Dropdown = _exports.default = (_class = class Dropdown extends _component2.default { + constructor(...args) { + super(...args); + /** + * This property reflects the state of the dropdown, whether it is open or closed. + * + * @property isOpen + * @default false + * @type boolean + * @private + */ + _initializerDefineProperty(this, "isOpen", _descriptor, this); + /** + * @property toggleElement + * @private + */ + _initializerDefineProperty(this, "toggleElement", _descriptor2, this); + /** + * The DOM element of the `.dropdown-menu` element + * @type object + * @readonly + * @private + */ + _initializerDefineProperty(this, "menuElement", _descriptor3, this); + } + /** + * The tag name used for the dropdown element. + * + * @property htmlTag + * @default 'div' + * @type {string} + * @public + */ + get htmlTag() { + return this.args.htmlTag ?? 'div'; + } + /** + * By default, clicking on an open dropdown menu will close it. Set this property to false for the menu to stay open. + * + * @property closeOnMenuClick + * @default true + * @type boolean + * @public + */ + get closeOnMenuClick() { + return this.args.closeOnMenuClick ?? true; } - }); - - // Delegation to the adapter and promise management - - - function defaultSerializer(store) { - return store.serializerFor('application'); - } - - function _commit(adapter, store, operation, snapshot) { - var internalModel = snapshot._internalModel; - var modelName = snapshot.modelName; - var modelClass = store._modelFor(modelName); - (0, _debug.assert)('You tried to update a record but you have no adapter (for ' + modelName + ')', adapter); - (0, _debug.assert)('You tried to update a record but your adapter (for ' + modelName + ') does not implement \'' + operation + '\'', typeof adapter[operation] === 'function'); - var promise = adapter[operation](store, modelClass, snapshot); - var serializer = (0, _serializers.serializerForAdapter)(store, adapter, modelName); - var label = 'DS: Extract and notify about ' + operation + ' completion of ' + internalModel; - (0, _debug.assert)('Your adapter\'s \'' + operation + '\' method must return a value, but it returned \'undefined\'', promise !== undefined); + /** + * By default, the dropdown menu will expand downwards. Other options include, 'up', 'left' and 'right' + * + * @property direction + * @type string + * @default 'down' + * @public + */ + get direction() { + return this.args.direction ?? 'down'; + } - promise = Promise.resolve(promise, label); - promise = (0, _common._guard)(promise, (0, _common._bind)(_common._objectIsAlive, store)); - promise = (0, _common._guard)(promise, (0, _common._bind)(_common._objectIsAlive, internalModel)); + /** + * Indicates the dropdown is being used as a navigation item dropdown. + * + * @property inNav + * @type boolean + * @default false + * @private + */ - return promise.then(function (adapterPayload) { - /* - Note to future spelunkers hoping to optimize. - We rely on this `run` to create a run loop if needed - that `store._push` and `store.didSaveRecord` will both share. - We use `join` because it is often the case that we - have an outer run loop available still from the first - call to `store._push`; - */ - store._backburner.join(function () { - var payload = void 0, - data = void 0; - if (adapterPayload) { - payload = (0, _serializerResponse.normalizeResponseHelper)(serializer, store, modelClass, adapterPayload, snapshot.id, operation); - if (payload.included) { - store._push({ data: null, included: payload.included }); - } - data = payload.data; + /** + * A computed property to generate the suiting class for the dropdown container, either + * + * - "dropdown" + * - "dropup" + * - "dropstart" (BS5) or "dropleft" (BS4) + * - "dropend" (BS5) or "dropright" (BS4) + * + * @property containerClass + * @type string + * @readonly + * @private + */ + get containerClass() { + { + if (this.direction === 'left') { + return 'dropstart'; + } else if (this.direction === 'right') { + return 'dropend'; } - store.didSaveRecord(internalModel, { data: data }); - }); - - return internalModel; - }, function (error) { - if (error instanceof _errors.InvalidError) { - var errors = serializer.extractErrors(store, modelClass, error, snapshot.id); - - store.recordWasInvalid(internalModel, errors); - } else { - store.recordWasError(internalModel, error); - } - - throw error; - }, label); - } - - function setupRelationships(store, internalModel, data) { - if (!data.relationships) { - return; - } - - internalModel.type.eachRelationship(function (key, descriptor) { - if (!data.relationships[key]) { - return; } - - var relationship = internalModel._relationships.get(key); - relationship.push(data.relationships[key]); - }); - } - - exports.Store = Store; - exports.default = Store; -}); -define('ember-data/-private/system/store/common', ['exports', 'ember'], function (exports, _ember) { - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - exports._bind = _bind; - exports._guard = _guard; - exports._objectIsAlive = _objectIsAlive; - var get = _ember.default.get; - function _bind(fn) { - for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; + return `drop${this.direction}`; } + /** + * Action is called when dropdown is about to be shown + * + * @event onShow + * @param {*} value + * @public + */ - return function () { - return fn.apply(undefined, args); - }; - } + /** + * Action is called when dropdown is about to be hidden + * Returning `false` will block closing the dropdown + * + * @event onHide + * @param {*} value + * @public + */ - function _guard(promise, test) { - var guarded = promise['finally'](function () { - if (!test()) { - guarded._subscribers.length = 0; + toggleDropdown() { + if (this.isOpen) { + this.closeDropdown(); + } else { + this.openDropdown(); } - }); - - return guarded; - } - - function _objectIsAlive(object) { - return !(get(object, "isDestroyed") || get(object, "isDestroying")); - } -}); -define('ember-data/-private/system/store/container-instance-cache', ['exports', 'ember'], function (exports, _ember) { - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - function _classCallCheck(instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); } - } - - var set = _ember.default.set; - - var ContainerInstanceCache = function () { - function ContainerInstanceCache(owner, store) { - _classCallCheck(this, ContainerInstanceCache); - - this.isDestroying = false; - this.isDestroyed = false; - this._owner = owner; - this._store = store; - this._namespaces = { - adapter: Object.create(null), - serializer: Object.create(null) - }; + openDropdown() { + this.isOpen = true; + this.args.onShow?.(); } + closeDropdown() { + if (this.args.onHide?.() === false) return; - ContainerInstanceCache.prototype.get = function get(namespace, preferredKey) { - var cache = this._namespaces[namespace]; + // When closing the dropdown immediately, any click event from dropdown items will be discarded. + // By deferring the close action to the next render cycle, we ensure that no events get lost. + (0, _runloop.next)(this, () => { + this.isOpen = false; + }); + } - if (cache[preferredKey]) { - return cache[preferredKey]; + /** + * Handler for click events to close the dropdown + * + * @method closeOnClickHandler + * @param e + * @protected + */ + closeHandler(e) { + let { + target + } = e; + let { + toggleElement, + menuElement + } = this; + if (!this.isDestroyed && (e.type === 'keyup' && e.which === TAB_KEYCODE && menuElement && !menuElement.contains(target) || e.type === 'click' && toggleElement && !toggleElement.contains(target) && (menuElement && !menuElement.contains(target) || this.closeOnMenuClick))) { + this.closeDropdown(); + } + } + handleKeyEvent(event) { + // If not input/textarea: + // - And not a key in REGEXP_KEYDOWN => not a dropdown command + // If input/textarea: + // - If space key => not a dropdown command + // - If key is other than escape + // - If key is not up or down => not a dropdown command + // - If trigger inside the menu => not a dropdown command + if (['input', 'textarea'].includes(event.target.tagName.toLowerCase()) ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE && (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE || this.menuElement.contains(event.target)) : !SUPPORTED_KEYCODES.includes(event.which)) { + return; } - - var preferredLookupKey = namespace + ':' + preferredKey; - - var instance = this._instanceFor(preferredLookupKey) || this._findInstance(namespace, this._fallbacksFor(namespace, preferredKey)); - if (instance) { - cache[preferredKey] = instance; - set(instance, 'store', this._store); + event.preventDefault(); + event.stopPropagation(); + if (!this.isOpen) { + this.openDropdown(); + return; + } else if (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE) { + this.closeDropdown(); + this.toggleElement.focus(); + return; } - - return cache[preferredKey]; - }; - - ContainerInstanceCache.prototype._fallbacksFor = function _fallbacksFor(namespace, preferredKey) { - if (namespace === 'adapter') { - return ['application', this._store.get('adapter'), '-json-api']; + let items = [].slice.call(this.menuElement.querySelectorAll('.dropdown-item:not(.disabled):not(:disabled)')); + if (items.length === 0) { + return; } - - // serializer - return ['application', this.get('adapter', preferredKey).get('defaultSerializer'), '-default']; - }; - - ContainerInstanceCache.prototype._findInstance = function _findInstance(namespace, fallbacks) { - var cache = this._namespaces[namespace]; - - for (var i = 0, length = fallbacks.length; i < length; i++) { - var fallback = fallbacks[i]; - - if (cache[fallback]) { - return cache[fallback]; - } - - var lookupKey = namespace + ':' + fallback; - var instance = this._instanceFor(lookupKey); - - if (instance) { - cache[fallback] = instance; - return instance; - } + let index = items.indexOf(event.target); + if (event.which === ARROW_UP_KEYCODE && index > 0) { + // Up + index--; } - }; - - ContainerInstanceCache.prototype._instanceFor = function _instanceFor(key) { - return this._owner.lookup(key); - }; - - ContainerInstanceCache.prototype.destroyCache = function destroyCache(cache) { - var cacheEntries = Object.keys(cache); - - for (var i = 0, length = cacheEntries.length; i < length; i++) { - var cacheKey = cacheEntries[i]; - var cacheEntry = cache[cacheKey]; - if (cacheEntry) { - cacheEntry.destroy(); - } + if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) { + // Down + index++; } - }; - - ContainerInstanceCache.prototype.destroy = function destroy() { - this.isDestroying = true; - this.destroyCache(this._namespaces.adapter); - this.destroyCache(this._namespaces.serializer); - this.isDestroyed = true; - }; - - ContainerInstanceCache.prototype.toString = function toString() { - return 'ContainerInstanceCache'; - }; - - return ContainerInstanceCache; - }(); - - exports.default = ContainerInstanceCache; -}); -define("ember-data/-private/system/store/finders", ["exports", "ember", "ember-data/-private/debug", "ember-data/-private/system/store/common", "ember-data/-private/system/store/serializer-response", "ember-data/-private/system/store/serializers"], function (exports, _ember, _debug, _common, _serializerResponse, _serializers) { - "use strict"; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - exports._find = _find; - exports._findMany = _findMany; - exports._findHasMany = _findHasMany; - exports._findBelongsTo = _findBelongsTo; - exports._findAll = _findAll; - exports._query = _query; - exports._queryRecord = _queryRecord; - var Promise = _ember.default.RSVP.Promise; - - - function payloadIsNotBlank(adapterPayload) { - if (Array.isArray(adapterPayload)) { - return true; - } else { - return Object.keys(adapterPayload || {}).length; - } - } - - function _find(adapter, store, modelClass, id, internalModel, options) { - var snapshot = internalModel.createSnapshot(options); - var modelName = internalModel.modelName; - - var promise = adapter.findRecord(store, modelClass, id, snapshot); - var serializer = (0, _serializers.serializerForAdapter)(store, adapter, modelName); - var label = "DS: Handle Adapter#findRecord of '" + modelName + "' with id: '" + id + "'"; - - promise = Promise.resolve(promise, label); - promise = (0, _common._guard)(promise, (0, _common._bind)(_common._objectIsAlive, store)); - - return promise.then(function (adapterPayload) { - (0, _debug.assert)("You made a 'findRecord' request for a '" + modelName + "' with id '" + id + "', but the adapter's response did not have any data", payloadIsNotBlank(adapterPayload)); - var payload = (0, _serializerResponse.normalizeResponseHelper)(serializer, store, modelClass, adapterPayload, id, 'findRecord'); - (0, _debug.assert)("Ember Data expected the primary data returned from a 'findRecord' response to be an object but instead it found an array.", !Array.isArray(payload.data)); - - (0, _debug.warn)("You requested a record of type '" + modelName + "' with id '" + id + "' but the adapter returned a payload with primary data having an id of '" + payload.data.id + "'. Use 'store.findRecord()' when the requested id is the same as the one returned by the adapter. In other cases use 'store.queryRecord()' instead http://emberjs.com/api/data/classes/DS.Store.html#method_queryRecord", payload.data.id === id, { - id: 'ds.store.findRecord.id-mismatch' - }); - - return store._push(payload); - }, function (error) { - internalModel.notFound(); - if (internalModel.isEmpty()) { - internalModel.unloadRecord(); + if (index < 0) { + index = 0; } - - throw error; - }, "DS: Extract payload of '" + modelName + "'"); - } - - function _findMany(adapter, store, modelName, ids, internalModels) { - var snapshots = _ember.default.A(internalModels).invoke('createSnapshot'); - var modelClass = store.modelFor(modelName); // `adapter.findMany` gets the modelClass still - var promise = adapter.findMany(store, modelClass, ids, snapshots); - var serializer = (0, _serializers.serializerForAdapter)(store, adapter, modelName); - var label = "DS: Handle Adapter#findMany of '" + modelName + "'"; - - if (promise === undefined) { - throw new Error('adapter.findMany returned undefined, this was very likely a mistake'); + items[index].focus(); + } + registerChildElement(element, [type]) { + (true && !(type === 'toggle' || type === 'menu') && (0, _debug.assert)(`Unknown child element type "${type}"`, type === 'toggle' || type === 'menu')); + (true && !(element instanceof HTMLElement) && (0, _debug.assert)(`Registered ${type} element must be an HTMLElement`, element instanceof HTMLElement)); + this[`${type}Element`] = element; + } + unregisterChildElement(element, [type]) { + (true && !(type === 'toggle' || type === 'menu') && (0, _debug.assert)(`Unknown child element type "${type}"`, type === 'toggle' || type === 'menu')); + this[`${type}Element`] = null; + } + updateIsOpen(open) { + this.isOpen = open; } - promise = Promise.resolve(promise, label); - promise = (0, _common._guard)(promise, (0, _common._bind)(_common._objectIsAlive, store)); - - return promise.then(function (adapterPayload) { - (0, _debug.assert)("You made a 'findMany' request for '" + modelName + "' records with ids '[" + ids + "]', but the adapter's response did not have any data", payloadIsNotBlank(adapterPayload)); - var payload = (0, _serializerResponse.normalizeResponseHelper)(serializer, store, modelClass, adapterPayload, null, 'findMany'); - return store._push(payload); - }, null, "DS: Extract payload of " + modelName); - } - - function _findHasMany(adapter, store, internalModel, link, relationship) { - var snapshot = internalModel.createSnapshot(); - var modelClass = store.modelFor(relationship.type); - var promise = adapter.findHasMany(store, snapshot, link, relationship); - var serializer = (0, _serializers.serializerForAdapter)(store, adapter, relationship.type); - var label = "DS: Handle Adapter#findHasMany of '" + internalModel.modelName + "' : '" + relationship.type + "'"; - - promise = Promise.resolve(promise, label); - promise = (0, _common._guard)(promise, (0, _common._bind)(_common._objectIsAlive, store)); - promise = (0, _common._guard)(promise, (0, _common._bind)(_common._objectIsAlive, internalModel)); - - return promise.then(function (adapterPayload) { - (0, _debug.assert)("You made a 'findHasMany' request for a " + internalModel.modelName + "'s '" + relationship.key + "' relationship, using link '" + link + "' , but the adapter's response did not have any data", payloadIsNotBlank(adapterPayload)); - var payload = (0, _serializerResponse.normalizeResponseHelper)(serializer, store, modelClass, adapterPayload, null, 'findHasMany'); - var internalModelArray = store._push(payload); - - internalModelArray.meta = payload.meta; - return internalModelArray; - }, null, "DS: Extract payload of '" + internalModel.modelName + "' : hasMany '" + relationship.type + "'"); - } - - function _findBelongsTo(adapter, store, internalModel, link, relationship) { - var snapshot = internalModel.createSnapshot(); - var modelClass = store.modelFor(relationship.type); - var promise = adapter.findBelongsTo(store, snapshot, link, relationship); - var serializer = (0, _serializers.serializerForAdapter)(store, adapter, relationship.type); - var label = "DS: Handle Adapter#findBelongsTo of " + internalModel.modelName + " : " + relationship.type; - - promise = Promise.resolve(promise, label); - promise = (0, _common._guard)(promise, (0, _common._bind)(_common._objectIsAlive, store)); - promise = (0, _common._guard)(promise, (0, _common._bind)(_common._objectIsAlive, internalModel)); - - return promise.then(function (adapterPayload) { - var payload = (0, _serializerResponse.normalizeResponseHelper)(serializer, store, modelClass, adapterPayload, null, 'findBelongsTo'); - - if (!payload.data) { - return null; - } - - return store._push(payload); - }, null, "DS: Extract payload of " + internalModel.modelName + " : " + relationship.type); - } - - function _findAll(adapter, store, modelName, sinceToken, options) { - var modelClass = store.modelFor(modelName); // adapter.findAll depends on the class - var recordArray = store.peekAll(modelName); - var snapshotArray = recordArray._createSnapshot(options); - var promise = adapter.findAll(store, modelClass, sinceToken, snapshotArray); - var serializer = (0, _serializers.serializerForAdapter)(store, adapter, modelName); - var label = "DS: Handle Adapter#findAll of " + modelClass; - - promise = Promise.resolve(promise, label); - promise = (0, _common._guard)(promise, (0, _common._bind)(_common._objectIsAlive, store)); - - return promise.then(function (adapterPayload) { - (0, _debug.assert)("You made a 'findAll' request for '" + modelName + "' records, but the adapter's response did not have any data", payloadIsNotBlank(adapterPayload)); - var payload = (0, _serializerResponse.normalizeResponseHelper)(serializer, store, modelClass, adapterPayload, null, 'findAll'); - - store._push(payload); - store.didUpdateAll(modelName); - - return store.peekAll(modelName); - }, null, 'DS: Extract payload of findAll ${modelName}'); - } - - function _query(adapter, store, modelName, query, recordArray) { - var modelClass = store.modelFor(modelName); // adapter.query needs the class - var promise = adapter.query(store, modelClass, query, recordArray); - - var serializer = (0, _serializers.serializerForAdapter)(store, adapter, modelName); - - var label = "DS: Handle Adapter#query of " + modelClass; - - promise = Promise.resolve(promise, label); - promise = (0, _common._guard)(promise, (0, _common._bind)(_common._objectIsAlive, store)); - - return promise.then(function (adapterPayload) { - var payload = (0, _serializerResponse.normalizeResponseHelper)(serializer, store, modelClass, adapterPayload, null, 'query'); - - var internalModels = store._push(payload); - - (0, _debug.assert)('The response to store.query is expected to be an array but it was a single record. Please wrap your response in an array or use `store.queryRecord` to query for a single record.', Array.isArray(internalModels)); - recordArray._setInternalModels(internalModels, payload); - - return recordArray; - }, null, "DS: Extract payload of query " + modelName); - } - - function _queryRecord(adapter, store, modelName, query) { - var modelClass = store.modelFor(modelName); // adapter.queryRecord needs the class - var promise = adapter.queryRecord(store, modelClass, query); - var serializer = (0, _serializers.serializerForAdapter)(store, adapter, modelName); - var label = "DS: Handle Adapter#queryRecord of " + modelName; - - promise = Promise.resolve(promise, label); - promise = (0, _common._guard)(promise, (0, _common._bind)(_common._objectIsAlive, store)); - - return promise.then(function (adapterPayload) { - var payload = (0, _serializerResponse.normalizeResponseHelper)(serializer, store, modelClass, adapterPayload, null, 'queryRecord'); + /** + * @property buttonComponent + * @type {String} + * @private + */ - (0, _debug.assert)("Expected the primary data returned by the serializer for a 'queryRecord' response to be a single object or null but instead it was an array.", !Array.isArray(payload.data), { - id: 'ds.store.queryRecord-array-response' - }); + /** + * @property toggleComponent + * @type {String} + * @private + */ - return store._push(payload); - }, null, "DS: Extract payload of queryRecord " + modelName); - } + /** + * @property menuComponent + * @type {String} + * @private + */ + }, (_descriptor = _applyDecoratedDescriptor(_class.prototype, "isOpen", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return this.args.isOpen ?? false; + } + }), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "toggleElement", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return null; + } + }), _descriptor3 = _applyDecoratedDescriptor(_class.prototype, "menuElement", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return null; + } + }), _applyDecoratedDescriptor(_class.prototype, "toggleDropdown", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "toggleDropdown"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "openDropdown", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "openDropdown"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "closeDropdown", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "closeDropdown"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "closeHandler", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "closeHandler"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "handleKeyEvent", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "handleKeyEvent"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "registerChildElement", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "registerChildElement"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "unregisterChildElement", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "unregisterChildElement"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "updateIsOpen", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "updateIsOpen"), _class.prototype)), _class); + (0, _component.setComponentTemplate)(__COLOCATED_TEMPLATE__, Dropdown); }); -define('ember-data/-private/system/store/serializer-response', ['exports', 'ember', 'ember-data/-private/debug'], function (exports, _ember, _debug) { - 'use strict'; +;define("ember-bootstrap/components/bs-dropdown/button", ["exports", "@ember/component", "@ember/component/template-only", "@ember/template-factory"], function (_exports, _component, _templateOnly, _templateFactory) { + "use strict"; - Object.defineProperty(exports, "__esModule", { + Object.defineProperty(_exports, "__esModule", { value: true }); - exports.validateDocumentStructure = validateDocumentStructure; - exports.normalizeResponseHelper = normalizeResponseHelper; - - var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { - return typeof obj; - } : function (obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; - }; - + _exports.default = void 0; + 0; //eaimeta@70e063a35619d71f0,"@ember/component/template-only",0,"@ember/template-factory",0,"@ember/component"eaimeta@70e063a35619d71f + const __COLOCATED_TEMPLATE__ = (0, _templateFactory.createTemplateFactory)( /* - This is a helper method that validates a JSON API top-level document - - The format of a document is described here: - http://jsonapi.org/format/#document-top-level + {{! @glint-nocheck }} + + {{yield}} + - @method validateDocumentStructure - @param {Object} doc JSON API document - @return {array} An array of errors found in the document structure - */ - function validateDocumentStructure(doc) { - var errors = []; - if (!doc || (typeof doc === 'undefined' ? 'undefined' : _typeof(doc)) !== 'object') { - errors.push('Top level of a JSON API document must be an object'); - } else { - if (!('data' in doc) && !('errors' in doc) && !('meta' in doc)) { - errors.push('One or more of the following keys must be present: "data", "errors", "meta".'); - } else { - if ('data' in doc && 'errors' in doc) { - errors.push('Top level keys "errors" and "data" cannot both be present in a JSON API document'); - } - } - if ('data' in doc) { - if (!(doc.data === null || Array.isArray(doc.data) || _typeof(doc.data) === 'object')) { - errors.push('data must be null, an object, or an array'); - } - } - if ('meta' in doc) { - if (_typeof(doc.meta) !== 'object') { - errors.push('meta must be an object'); - } - } - if ('errors' in doc) { - if (!Array.isArray(doc.errors)) { - errors.push('errors must be an array'); - } - } - if ('links' in doc) { - if (_typeof(doc.links) !== 'object') { - errors.push('links must be an object'); - } - } - if ('jsonapi' in doc) { - if (_typeof(doc.jsonapi) !== 'object') { - errors.push('jsonapi must be an object'); - } - } - if ('included' in doc) { - if (_typeof(doc.included) !== 'object') { - errors.push('included must be an array'); - } - } - } - - return errors; - } - - /* - This is a helper method that always returns a JSON-API Document. - - @method normalizeResponseHelper - @param {DS.Serializer} serializer - @param {DS.Store} store - @param {subclass of DS.Model} modelClass - @param {Object} payload - @param {String|Number} id - @param {String} requestType - @return {Object} JSON-API Document */ - function normalizeResponseHelper(serializer, store, modelClass, payload, id, requestType) { - var normalizedResponse = serializer.normalizeResponse(store, modelClass, payload, id, requestType); - var validationErrors = []; - (0, _debug.runInDebug)(function () { - validationErrors = validateDocumentStructure(normalizedResponse); - }); - (0, _debug.assert)('normalizeResponse must return a valid JSON API document:\n\t* ' + validationErrors.join('\n\t* '), _ember.default.isEmpty(validationErrors)); + { + "id": "0+x27Dtj", + "block": "[[[8,[39,0],[[16,\"aria-expanded\",[52,[30,1],\"true\",\"false\"]],[24,0,\"dropdown-toggle\"],[17,2],[4,[38,2],[\"keydown\",[30,4]],null],[4,[38,3],[[30,5],\"toggle\"],null],[4,[38,4],[[30,6],\"toggle\"],null]],[[\"@block\",\"@onClick\"],[[30,0,[\"args\",\"block\"]],[30,3]]],[[\"default\"],[[[[1,\"\\n \"],[18,7,null],[1,\"\\n\"]],[]]]]],[1,\"\\n\"]],[\"@isOpen\",\"&attrs\",\"@onClick\",\"@onKeyDown\",\"@registerChildElement\",\"@unregisterChildElement\",\"&default\"],false,[\"bs-button\",\"if\",\"on\",\"did-insert\",\"will-destroy\",\"yield\"]]", + "moduleName": "ember-bootstrap/components/bs-dropdown/button.hbs", + "isStrictMode": false + }); - return normalizedResponse; - } + /** + Button component with that can act as a dropdown toggler. + + See [Components.Dropdown](Components.Dropdown.html) for examples. + + @class DropdownButton + @namespace Components + @extends Components.Button + @public + */ + var _default = _exports.default = (0, _component.setComponentTemplate)(__COLOCATED_TEMPLATE__, (0, _templateOnly.default)()); }); -define("ember-data/-private/system/store/serializers", ["exports"], function (exports) { +;define("ember-bootstrap/components/bs-dropdown/menu", ["exports", "@ember/component", "@ember/object", "@glimmer/component", "@ember/runloop", "ember-bootstrap/utils/dom", "ember-ref-bucket", "@glimmer/tracking", "@ember/template-factory"], function (_exports, _component, _object, _component2, _runloop, _dom, _emberRefBucket, _tracking, _templateFactory) { "use strict"; - Object.defineProperty(exports, "__esModule", { + Object.defineProperty(_exports, "__esModule", { value: true }); - exports.serializerForAdapter = serializerForAdapter; - function serializerForAdapter(store, adapter, modelName) { - var serializer = adapter.serializer; + _exports.default = void 0; + var _dec, _class, _descriptor, _descriptor2; + 0; //eaimeta@70e063a35619d71f0,"@ember/object",0,"@glimmer/component",0,"@ember/runloop",0,"ember-bootstrap/utils/dom",0,"ember-ref-bucket",0,"@glimmer/tracking",0,"@embroider/macros",0,"@ember/template-factory",0,"@ember/component"eaimeta@70e063a35619d71f + function _initializerDefineProperty(e, i, r, l) { r && Object.defineProperty(e, i, { enumerable: r.enumerable, configurable: r.configurable, writable: r.writable, value: r.initializer ? r.initializer.call(l) : void 0 }); } + function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } + function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } + function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } + function _applyDecoratedDescriptor(i, e, r, n, l) { var a = {}; return Object.keys(n).forEach(function (i) { a[i] = n[i]; }), a.enumerable = !!a.enumerable, a.configurable = !!a.configurable, ("value" in a || a.initializer) && (a.writable = !0), a = r.slice().reverse().reduce(function (r, n) { return n(i, e, r) || r; }, a), l && void 0 !== a.initializer && (a.value = a.initializer ? a.initializer.call(l) : void 0, a.initializer = void 0), void 0 === a.initializer && (Object.defineProperty(i, e, a), a = null), a; } + function _initializerWarningHelper(r, e) { throw Error("Decorating class property failed. Please ensure that transform-class-properties is enabled and runs after the decorators transform."); } + const __COLOCATED_TEMPLATE__ = (0, _templateFactory.createTemplateFactory)( + /* + {{! @glint-nocheck }} + {{#if @isOpen}} + {{#if this._renderInPlace}} + + {{else}} + {{#in-element this.destinationElement insertBefore=null}} + + {{/in-element}} + {{/if}} + {{/if}} + + */ + { + "id": "+TlKP9iL", + "block": "[[[41,[30,1],[[[41,[30,0,[\"_renderInPlace\"]],[[[1,\" \"],[11,0],[24,\"data-bs-popper\",\"\"],[16,0,[29,[\"dropdown-menu \",[30,0,[\"alignClass\"]],\" \",[52,[30,0,[\"isOpen\"]],\"show\"]]]],[24,\"tabindex\",\"-1\"],[17,2],[4,[38,2],[[30,3],[30,0,[\"popperOptions\"]]],null],[4,[38,3],[[30,4],\"menu\"],null],[4,[38,4],[[30,5],\"menu\"],null],[4,[38,5],[[30,0,[\"updateIsOpen\"]],[30,6]],null],[4,[38,6],[\"menuElement\"],[[\"debugName\",\"bucket\"],[\"create-ref\",[30,0]]]],[12],[1,\"\\n \"],[18,10,[[28,[37,8],null,[[\"item\",\"link-to\",\"linkTo\",\"divider\"],[[28,[37,9],[[28,[37,10],[[30,7],[50,\"bs-dropdown/menu/item\",0,null,null]],null]],null],[28,[37,9],[[28,[37,10],[[30,8],[50,\"bs-link-to\",0,null,[[\"attrClassInternal\"],[\"dropdown-item\"]]]],null]],null],[28,[37,9],[[28,[37,10],[[30,8],[50,\"bs-link-to\",0,null,[[\"attrClassInternal\"],[\"dropdown-item\"]]]],null]],null],[28,[37,9],[[28,[37,10],[[30,9],[50,\"bs-dropdown/menu/divider\",0,null,null]],null]],null]]]]]],[1,\"\\n \"],[13],[1,\"\\n\"]],[]],[[[40,[[[1,\" \"],[11,0],[24,\"data-bs-popper\",\"\"],[16,0,[29,[\"dropdown-menu \",[30,0,[\"alignClass\"]],\" \",[52,[30,0,[\"isOpen\"]],\"show\"]]]],[24,\"tabindex\",\"-1\"],[17,2],[4,[38,2],[[30,3],[30,0,[\"popperOptions\"]]],null],[4,[38,3],[[30,4],\"menu\"],null],[4,[38,4],[[30,5],\"menu\"],null],[4,[38,5],[[30,0,[\"updateIsOpen\"]],[30,6]],null],[4,[38,6],[\"menuElement\"],[[\"debugName\",\"bucket\"],[\"create-ref\",[30,0]]]],[12],[1,\"\\n \"],[18,10,[[28,[37,8],null,[[\"item\",\"link-to\",\"linkTo\",\"divider\"],[[28,[37,9],[[28,[37,10],[[30,7],[50,\"bs-dropdown/menu/item\",0,null,null]],null]],null],[28,[37,9],[[28,[37,10],[[30,8],[50,\"bs-link-to\",0,null,[[\"attrClassInternal\"],[\"dropdown-item\"]]]],null]],null],[28,[37,9],[[28,[37,10],[[30,8],[50,\"bs-link-to\",0,null,[[\"attrClassInternal\"],[\"dropdown-item\"]]]],null]],null],[28,[37,9],[[28,[37,10],[[30,9],[50,\"bs-dropdown/menu/divider\",0,null,null]],null]],null]]]]]],[1,\"\\n \"],[13],[1,\"\\n\"]],[]],\"%cursor:0%\",[28,[37,13],[[30,0,[\"destinationElement\"]]],null],null]],[]]]],[]],null]],[\"@isOpen\",\"&attrs\",\"@toggleElement\",\"@registerChildElement\",\"@unregisterChildElement\",\"@open\",\"@itemComponent\",\"@linkToComponent\",\"@dividerComponent\",\"&default\"],false,[\"if\",\"div\",\"popper-tooltip\",\"did-insert\",\"will-destroy\",\"did-update\",\"create-ref\",\"yield\",\"hash\",\"ensure-safe-component\",\"bs-default\",\"component\",\"in-element\",\"-in-el-null\"]]", + "moduleName": "ember-bootstrap/components/bs-dropdown/menu.hbs", + "isStrictMode": false + }); - if (serializer === undefined) { - serializer = store.serializerFor(modelName); + /** + Component for the dropdown menu. + + See [Components.Dropdown](Components.Dropdown.html) for examples. + + @class DropdownMenu + @namespace Components + @extends Component + @public + */ + let DropdownMenu = _exports.default = (_dec = (0, _emberRefBucket.ref)('menuElement'), (_class = class DropdownMenu extends _component2.default { + constructor(...args) { + super(...args); + /** + * @property _element + * @type null | HTMLElement + * @private + */ + _initializerDefineProperty(this, "menuElement", _descriptor, this); + _initializerDefineProperty(this, "isOpen", _descriptor2, this); + _defineProperty(this, "flip", true); } - - if (serializer === null || serializer === undefined) { - serializer = { - extract: function extract(store, type, payload) { - return payload; - } - }; + /** + * Alignment of the menu, either "left" or "right" + * + * @property align + * @type string + * @default left + * @public + */ + get align() { + return this.args.align ?? 'left'; } - return serializer; - } -}); -define("ember-data/-private/transforms", ["exports", "ember-data/transform", "ember-data/-private/transforms/number", "ember-data/-private/transforms/date", "ember-data/-private/transforms/string", "ember-data/-private/transforms/boolean"], function (exports, _transform, _number, _date, _string, _boolean) { - "use strict"; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - exports.BooleanTransform = exports.StringTransform = exports.DateTransform = exports.NumberTransform = exports.Transform = undefined; - exports.Transform = _transform.default; - exports.NumberTransform = _number.default; - exports.DateTransform = _date.default; - exports.StringTransform = _string.default; - exports.BooleanTransform = _boolean.default; -}); -define("ember-data/-private/transforms/boolean", ["exports", "ember", "ember-data/transform"], function (exports, _ember, _transform) { - "use strict"; + /** + * @property direction + * @default 'down' + * @type string + * @private + */ + get direction() { + return this.args.direction ?? 'down'; + } - Object.defineProperty(exports, "__esModule", { - value: true - }); + /** + * By default, the menu is rendered in the same place as the dropdown. If you experience clipping + * issues, you can set this to false to render the menu in a wormhole at the top of the DOM. + * + * @property renderInPlace + * @type boolean + * @default true + * @public + */ + get renderInPlace() { + return this.args.renderInPlace ?? true; + } - var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { - return typeof obj; - } : function (obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; - }; + /** + * @property inNav + * @type {boolean} + * @private + */ + get inNav() { + return this.args.inNav ?? false; + } - var isNone = _ember.default.isNone; - exports.default = _transform.default.extend({ - deserialize: function deserialize(serialized, options) { - var type = typeof serialized === "undefined" ? "undefined" : _typeof(serialized); + /** + * @property _renderInPlace + * @type boolean + * @private + */ + get _renderInPlace() { + return this.renderInPlace || !this.destinationElement; + } - if (isNone(serialized) && options.allowNull === true) { - return null; + /** + * The wormhole destinationElement + * + * @property destinationElement + * @type object + * @readonly + * @private + */ + get destinationElement() { + return (0, _dom.getDestinationElement)(this); + } + get alignClass() { + if (this.align === 'right') { + const alignClass = 'end'; + return `dropdown-menu-${alignClass}`; } - - if (type === "boolean") { - return serialized; - } else if (type === "string") { - return serialized.match(/^true$|^t$|^1$/i) !== null; - } else if (type === "number") { - return serialized === 1; - } else { - return false; + return undefined; + } + updateIsOpen(value) { + // delay removing the menu from DOM to allow (delegated Ember) event to fire for the menu's children + // Fixes https://github.com/kaliber5/ember-bootstrap/issues/660 + (0, _runloop.next)(() => { + if (this.isDestroying || this.isDestroyed) { + return; + } + this.isOpen = value; + }); + } + get popperPlacement() { + let placement = 'bottom-start'; + let { + direction, + align + } = this; + if (direction === 'up') { + placement = 'top-start'; + if (align === 'right') { + placement = 'top-end'; + } + } else if (direction === 'left') { + placement = 'left-start'; + } else if (direction === 'right') { + placement = 'right-start'; + } else if (align === 'right') { + placement = 'bottom-end'; + } + return placement; + } + setFocus() { + // when the dropdown menu is rendered in place, focus can stay on the toggle element + if (this._renderInPlace) { + return; } - }, - serialize: function serialize(deserialized, options) { - if (isNone(deserialized) && options.allowNull === true) { - return null; + if (this.menuElement) { + this.menuElement.focus(); } - - return Boolean(deserialized); } - }); -}); -define("ember-data/-private/transforms/date", ["exports", "ember-data/-private/ext/date", "ember-data/transform"], function (exports, _date, _transform) { - "use strict"; - - Object.defineProperty(exports, "__esModule", { - value: true - }); + get popperOptions() { + return { + placement: this.popperPlacement, + onFirstUpdate: () => this.setFocus(), + modifiers: [{ + name: 'flip', + enabled: this.flip + }, { + name: 'applyStyles', + enabled: !this.inNav + }] + }; + } - var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { - return typeof obj; - } : function (obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; - }; + /** + * @property itemComponent + * @type {String} + * @private + */ - exports.default = _transform.default.extend({ - deserialize: function deserialize(serialized) { - var type = typeof serialized === "undefined" ? "undefined" : _typeof(serialized); + /** + * @property linkToComponent + * @type {String} + * @private + */ - if (type === "string") { - return new Date((0, _date.parseDate)(serialized)); - } else if (type === "number") { - return new Date(serialized); - } else if (serialized === null || serialized === undefined) { - // if the value is null return null - // if the value is not present in the data return undefined - return serialized; - } else { - return null; - } - }, - serialize: function serialize(date) { - if (date instanceof Date && !isNaN(date)) { - return date.toISOString(); - } else { - return null; - } + /** + * @property dividerComponent + * @type {String} + * @private + */ + }, (_descriptor = _applyDecoratedDescriptor(_class.prototype, "menuElement", [_dec], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return null; } - }); + }), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "isOpen", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return this.args.isOpen; + } + }), _applyDecoratedDescriptor(_class.prototype, "updateIsOpen", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "updateIsOpen"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "setFocus", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "setFocus"), _class.prototype)), _class)); + (0, _component.setComponentTemplate)(__COLOCATED_TEMPLATE__, DropdownMenu); }); -define("ember-data/-private/transforms/number", ["exports", "ember", "ember-data/transform"], function (exports, _ember, _transform) { +;define("ember-bootstrap/components/bs-dropdown/menu/divider", ["exports", "@ember/component", "@ember/component/template-only", "@ember/template-factory"], function (_exports, _component, _templateOnly, _templateFactory) { "use strict"; - Object.defineProperty(exports, "__esModule", { + Object.defineProperty(_exports, "__esModule", { value: true }); - - - var empty = _ember.default.isEmpty; - - function isNumber(value) { - return value === value && value !== Infinity && value !== -Infinity; - } + _exports.default = void 0; + 0; //eaimeta@70e063a35619d71f0,"@ember/component/template-only",0,"@ember/template-factory",0,"@ember/component"eaimeta@70e063a35619d71f + const __COLOCATED_TEMPLATE__ = (0, _templateFactory.createTemplateFactory)( + /* + {{! @glint-nocheck }} + + */ + { + "id": "SlmRX0G0", + "block": "[[[11,0],[24,0,\"dropdown-divider\"],[17,1],[12],[1,\"\\n \"],[18,2,null],[1,\"\\n\"],[13]],[\"&attrs\",\"&default\"],false,[\"div\",\"yield\"]]", + "moduleName": "ember-bootstrap/components/bs-dropdown/menu/divider.hbs", + "isStrictMode": false + }); /** - The `DS.NumberTransform` class is used to serialize and deserialize - numeric attributes on Ember Data record objects. This transform is - used when `number` is passed as the type parameter to the - [DS.attr](../../data#method_attr) function. - - Usage - - ```app/models/score.js - import DS from 'ember-data'; + Component for a dropdown menu divider. - export default DS.Model.extend({ - value: DS.attr('number'), - player: DS.belongsTo('player'), - date: DS.attr('date') - }); - ``` + See [Components.Dropdown](Components.Dropdown.html) for examples. - @class NumberTransform - @extends DS.Transform - @namespace DS + @class DropdownMenuDivider + @namespace Components + @extends Component + @public */ - exports.default = _transform.default.extend({ - deserialize: function deserialize(serialized) { - var transformed = void 0; - - if (empty(serialized)) { - return null; - } else { - transformed = Number(serialized); - - return isNumber(transformed) ? transformed : null; - } - }, - serialize: function serialize(deserialized) { - var transformed = void 0; - - if (empty(deserialized)) { - return null; - } else { - transformed = Number(deserialized); - - return isNumber(transformed) ? transformed : null; - } - } - }); + var _default = _exports.default = (0, _component.setComponentTemplate)(__COLOCATED_TEMPLATE__, (0, _templateOnly.default)()); }); -define("ember-data/-private/transforms/string", ["exports", "ember", "ember-data/transform"], function (exports, _ember, _transform) { +;define("ember-bootstrap/components/bs-dropdown/menu/item", ["exports", "@ember/component/template-only"], function (_exports, _templateOnly) { "use strict"; - Object.defineProperty(exports, "__esModule", { + Object.defineProperty(_exports, "__esModule", { value: true }); - - - var none = _ember.default.isNone; - + _exports.default = void 0; + 0; //eaimeta@70e063a35619d71f0,"@ember/component/template-only"eaimeta@70e063a35619d71f /** - The `DS.StringTransform` class is used to serialize and deserialize - string attributes on Ember Data record objects. This transform is - used when `string` is passed as the type parameter to the - [DS.attr](../../data#method_attr) function. - - Usage - - ```app/models/user.js - import DS from 'ember-data'; + Component for a dropdown menu item. - export default DS.Model.extend({ - isAdmin: DS.attr('boolean'), - name: DS.attr('string'), - email: DS.attr('string') - }); - ``` + See [Components.Dropdown](Components.Dropdown.html) for examples. - @class StringTransform - @extends DS.Transform - @namespace DS + @class DropdownMenuItem + @namespace Components + @extends Component + @public */ - exports.default = _transform.default.extend({ - deserialize: function deserialize(serialized) { - return none(serialized) ? null : String(serialized); - }, - serialize: function serialize(deserialized) { - return none(deserialized) ? null : String(deserialized); - } - }); + var _default = _exports.default = (0, _templateOnly.default)(); }); -define('ember-data/-private/utils', ['exports', 'ember'], function (exports, _ember) { - 'use strict'; +;define("ember-bootstrap/components/bs-dropdown/toggle", ["exports", "@ember/component", "@glimmer/component", "@ember/object", "@ember/template-factory"], function (_exports, _component, _component2, _object, _templateFactory) { + "use strict"; - Object.defineProperty(exports, "__esModule", { + Object.defineProperty(_exports, "__esModule", { value: true }); - exports.getOwner = exports.modelHasAttributeOrRelationshipNamedType = undefined; - - - var get = _ember.default.get; - + _exports.default = void 0; + var _class; + 0; //eaimeta@70e063a35619d71f0,"@glimmer/component",0,"@ember/object",0,"@ember/template-factory",0,"@ember/component"eaimeta@70e063a35619d71f + function _applyDecoratedDescriptor(i, e, r, n, l) { var a = {}; return Object.keys(n).forEach(function (i) { a[i] = n[i]; }), a.enumerable = !!a.enumerable, a.configurable = !!a.configurable, ("value" in a || a.initializer) && (a.writable = !0), a = r.slice().reverse().reduce(function (r, n) { return n(i, e, r) || r; }, a), l && void 0 !== a.initializer && (a.value = a.initializer ? a.initializer.call(l) : void 0, a.initializer = void 0), void 0 === a.initializer && (Object.defineProperty(i, e, a), a = null), a; } + const __COLOCATED_TEMPLATE__ = (0, _templateFactory.createTemplateFactory)( /* - Check if the passed model has a `type` attribute or a relationship named `type`. - - @method modelHasAttributeOrRelationshipNamedType - @param modelClass - */ - function modelHasAttributeOrRelationshipNamedType(modelClass) { - return get(modelClass, 'attributes').has('type') || get(modelClass, 'relationshipsByName').has('type'); - } + {{! @glint-nocheck }} + + {{yield}} + + */ + { + "id": "+vP1OMxI", + "block": "[[[11,3],[24,6,\"#\"],[16,0,[29,[\"dropdown-toggle \",[52,[30,1],\"nav-link\"]]]],[16,\"aria-expanded\",[30,0,[\"aria-expanded\"]]],[24,\"role\",\"button\"],[17,2],[4,[38,2],[\"keydown\",[30,0,[\"handleKeyDown\"]]],null],[4,[38,2],[\"click\",[30,0,[\"handleClick\"]]],null],[4,[38,3],[[30,3],\"toggle\"],null],[4,[38,4],[[30,4],\"toggle\"],null],[12],[1,\"\\n \"],[18,5,null],[1,\"\\n\"],[13]],[\"@inNav\",\"&attrs\",\"@registerChildElement\",\"@unregisterChildElement\",\"&default\"],false,[\"a\",\"if\",\"on\",\"did-insert\",\"will-destroy\",\"yield\"]]", + "moduleName": "ember-bootstrap/components/bs-dropdown/toggle.hbs", + "isStrictMode": false + }); - /* - ember-container-inject-owner is a new feature in Ember 2.3 that finally provides a public - API for looking items up. This function serves as a super simple polyfill to avoid - triggering deprecations. + /** + Anchor element that triggers the parent dropdown to open. + Use [Components.DropdownButton](Components.DropdownButton.html) if you want a button instead of an anchor tag. + + See [Components.Dropdown](Components.Dropdown.html) for examples. + + @class DropdownToggle + @namespace Components + @extends Component + @publicø */ - function getOwner(context) { - var owner = void 0; - - if (_ember.default.getOwner) { - owner = _ember.default.getOwner(context); - } else if (context.container) { - owner = context.container; + let DropdownToggle = _exports.default = (_class = class DropdownToggle extends _component2.default { + /** + * @property inNav + * @type {boolean} + * @private + */ + get inNav() { + return this.args.inNav ?? false; } - - if (owner && owner.lookupFactory && !owner._lookupFactory) { - // `owner` is a container, we are just making this work - owner._lookupFactory = owner.lookupFactory; - owner.register = function () { - var registry = owner.registry || owner._registry || owner; - - return registry.register.apply(registry, arguments); - }; + get 'aria-expanded'() { + return this.args.isOpen ? 'true' : 'false'; } - return owner; - } - - exports.modelHasAttributeOrRelationshipNamedType = modelHasAttributeOrRelationshipNamedType; - exports.getOwner = getOwner; -}); -define('ember-data/-private/utils/parse-response-headers', ['exports'], function (exports) { - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - exports.default = parseResponseHeaders; - var CLRF = '\r\n'; - - function parseResponseHeaders(headersString) { - var headers = Object.create(null); + /** + * When clicking the toggle this action is called. + * + * @event onClick + * @param {*} value + * @public + */ - if (!headersString) { - return headers; + handleClick(e) { + e.preventDefault(); + this.args.onClick?.(); } - - var headerPairs = headersString.split(CLRF); - - headerPairs.forEach(function (header) { - var _header$split = header.split(':'), - field = _header$split[0], - value = _header$split.slice(1); - - field = field.trim(); - value = value.join(':').trim(); - - if (value) { - headers[field] = value; - } - }); - - return headers; - } + handleKeyDown(e) { + this.args.onKeyDown(e); + } + }, (_applyDecoratedDescriptor(_class.prototype, "handleClick", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "handleClick"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "handleKeyDown", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "handleKeyDown"), _class.prototype)), _class); + (0, _component.setComponentTemplate)(__COLOCATED_TEMPLATE__, DropdownToggle); }); -define('ember-data/adapter', ['exports', 'ember'], function (exports, _ember) { - 'use strict'; +;define("ember-bootstrap/components/bs-form", ["exports", "@ember/component", "@glimmer/component", "@ember/object", "@ember/debug", "@ember/utils", "@ember/runloop", "ember-bootstrap/utils/decorators/arg", "@glimmer/tracking", "ember-ref-bucket", "@ember/template-factory"], function (_exports, _component, _component2, _object, _debug, _utils, _runloop, _arg, _tracking, _emberRefBucket, _templateFactory) { + "use strict"; - Object.defineProperty(exports, "__esModule", { + Object.defineProperty(_exports, "__esModule", { value: true }); - exports.default = _ember.default.Object.extend({ + _exports.default = void 0; + var _dec, _class, _descriptor, _descriptor2, _descriptor3, _descriptor4, _descriptor5, _descriptor6, _descriptor7, _descriptor8, _descriptor9; + 0; //eaimeta@70e063a35619d71f0,"@glimmer/component",0,"@ember/object",0,"@ember/debug",0,"@ember/utils",0,"@ember/runloop",0,"@embroider/macros",0,"ember-bootstrap/utils/decorators/arg",0,"@glimmer/tracking",0,"ember-ref-bucket",0,"@ember/template-factory",0,"@ember/component"eaimeta@70e063a35619d71f + function _initializerDefineProperty(e, i, r, l) { r && Object.defineProperty(e, i, { enumerable: r.enumerable, configurable: r.configurable, writable: r.writable, value: r.initializer ? r.initializer.call(l) : void 0 }); } + function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } + function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } + function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } + function _applyDecoratedDescriptor(i, e, r, n, l) { var a = {}; return Object.keys(n).forEach(function (i) { a[i] = n[i]; }), a.enumerable = !!a.enumerable, a.configurable = !!a.configurable, ("value" in a || a.initializer) && (a.writable = !0), a = r.slice().reverse().reduce(function (r, n) { return n(i, e, r) || r; }, a), l && void 0 !== a.initializer && (a.value = a.initializer ? a.initializer.call(l) : void 0, a.initializer = void 0), void 0 === a.initializer && (Object.defineProperty(i, e, a), a = null), a; } + function _initializerWarningHelper(r, e) { throw Error("Decorating class property failed. Please ensure that transform-class-properties is enabled and runs after the decorators transform."); } + const __COLOCATED_TEMPLATE__ = (0, _templateFactory.createTemplateFactory)( + /* + {{! @glint-nocheck }} + {{!-- template-lint-disable no-invalid-interactive --}} +
+ {{yield + (hash + element=(component (ensure-safe-component (bs-default @elementComponent (component "bs-form/element"))) + model=this.model + formLayout=this.formLayout + horizontalLabelGridClass=this.horizontalLabelGridClass + showAllValidations=this.showAllValidations + _disabled=@disabled + _readonly=@readonly + onChange=this.elementChanged + _onChange=this.resetSubmissionState + ) + isSubmitting=this.isSubmitting + isSubmitted=this.isSubmitted + isRejected=this.isRejected + model=this.model + resetSubmissionState=this.resetSubmissionState + submit=this.doSubmit + submitButton=(component (ensure-safe-component (bs-default @submitButtonComponent (component "bs-button"))) + type="primary" + state=this.submitButtonState + _disabled=this.isSubmitting + attrTypePrivateWorkaround="submit" + ) + ) + }} +
+ + */ + { + "id": "QFf3O6KO", + "block": "[[[11,\"form\"],[16,\"novalidate\",[30,0,[\"hasValidator\"]]],[16,0,[30,0,[\"layoutClass\"]]],[17,1],[4,[38,1],[\"keypress\",[30,0,[\"handleKeyPress\"]]],null],[4,[38,1],[\"submit\",[30,0,[\"handleSubmit\"]]],null],[4,[38,2],[\"formElement\"],[[\"debugName\",\"bucket\"],[\"create-ref\",[30,0]]]],[12],[1,\"\\n \"],[18,6,[[28,[37,4],null,[[\"element\",\"isSubmitting\",\"isSubmitted\",\"isRejected\",\"model\",\"resetSubmissionState\",\"submit\",\"submitButton\"],[[50,[28,[37,6],[[28,[37,7],[[30,2],[50,\"bs-form/element\",0,null,null]],null]],null],0,null,[[\"model\",\"formLayout\",\"horizontalLabelGridClass\",\"showAllValidations\",\"_disabled\",\"_readonly\",\"onChange\",\"_onChange\"],[[30,0,[\"model\"]],[30,0,[\"formLayout\"]],[30,0,[\"horizontalLabelGridClass\"]],[30,0,[\"showAllValidations\"]],[30,3],[30,4],[30,0,[\"elementChanged\"]],[30,0,[\"resetSubmissionState\"]]]]],[30,0,[\"isSubmitting\"]],[30,0,[\"isSubmitted\"]],[30,0,[\"isRejected\"]],[30,0,[\"model\"]],[30,0,[\"resetSubmissionState\"]],[30,0,[\"doSubmit\"]],[50,[28,[37,6],[[28,[37,7],[[30,5],[50,\"bs-button\",0,null,null]],null]],null],0,null,[[\"type\",\"state\",\"_disabled\",\"attrTypePrivateWorkaround\"],[\"primary\",[30,0,[\"submitButtonState\"]],[30,0,[\"isSubmitting\"]],\"submit\"]]]]]]]],[1,\"\\n\"],[13],[1,\"\\n\"]],[\"&attrs\",\"@elementComponent\",\"@disabled\",\"@readonly\",\"@submitButtonComponent\",\"&default\"],false,[\"form\",\"on\",\"create-ref\",\"yield\",\"hash\",\"component\",\"ensure-safe-component\",\"bs-default\"]]", + "moduleName": "ember-bootstrap/components/bs-form.hbs", + "isStrictMode": false + }); + /** + Render a form with the appropriate Bootstrap layout class (see `formLayout`). + Allows setting a `model` that nested `Components.FormElement`s can access, and that can provide form validation (see below) + + You can use whatever markup you like within the form. + However, to benefit from features such as automatic form markup, validations and validation markup, use `Components.FormElement` + as nested components. See below for an example. + + ### Submitting the form + + The form yields a `submitButton` component, which is a preconfigured `` with `@type="primary"` and `type="submit"`. + The button is disabled while a form submission is pending. Additionally, the button state is bound to the form submission state. + + ```hbs + + Submit + + ``` + + When the form is submitted (e.g. by clicking the submit button), the event will be intercepted and the `onSubmit` action + will be sent to the controller or parent component. + In case the form supports validation (see "Form validation" below), the `onBefore` action is called (which allows you to + do e.g. model data normalization), then the available validation rules are evaluated, and if those fail, the `onInvalid` + action is sent instead of `onSubmit`. + + ### Use with Components.FormElement + + When using `Components.FormElement`s with their `property` set to property names of the form's validation enabled + `model`, you gain some additional powerful features: + * the appropriate Bootstrap markup for the given `formLayout` and the form element's `controlType` is automatically generated + * markup for validation states and error messages is generated based on the model's validation (if available), when submitting the form + with an invalid validation, or when focusing out of invalid inputs + + ```handlebars + + + + + Submit + + ``` + + See the [Components.FormElement](Components.FormElement.html) API docs for further information. + + ### Form validation + + All version of ember-bootstrap beginning from 0.7.0 do not come with built-in support for validation engines anymore. + Instead, support is added usually by additional Ember addons, for example: + + * [ember-bootstrap-validations](https://github.com/kaliber5/ember-bootstrap-validations): adds support for [ember-validations](https://github.com/DockYard/ember-validations) + * [ember-bootstrap-cp-validations](https://github.com/offirgolan/ember-bootstrap-cp-validations): adds support for [ember-cp-validations](https://github.com/offirgolan/ember-cp-validations) + * [ember-bootstrap-changeset-validations](https://github.com/kaliber5/ember-bootstrap-changeset-validations): adds support for [ember-changeset](https://github.com/poteto/ember-changeset) + + To add your own validation support, you have to: + + * extend this component, setting `hasValidator` to true if validations are available (by means of a computed property for example), and implementing the `validate` method + * extend the [Components.FormElement](Components.FormElement.html) component and implement the `setupValidations` hook or simply override the `errors` property to add the validation error messages to be displayed + + When validation fails, the appropriate Bootstrap markup is added automatically, i.e. the error classes are applied and + the validation messages are shown for each form element. In case the validation library supports it, also warning messages + are shown. See the [Components.FormElement](Components.FormElement.html) documentation for further details. + + See the above-mentioned addons for examples. + + The `novalidate` HTML attribute is set by default for forms that have validation. + + ### Submission state + + A `isSubmitting` property is yielded, which is `true` after submit has been triggered and before the Promise returned + by `onSubmit` is fulfilled. It could be used to show a loading spinner instead of the form while it's submitting for example: + + ```hbs + + {{#if form.isSubmitting}} + + Logging in... + {{else}} + + + Login + {{/if}} + + ``` + + Additionaly `isSubmitted` and `isRejected` properties are yielded. `isSubmitted` is `true` if last submission was successful. + `isRejected` is `true` if last submission was rejected due to validation errors or by an action bound to `onSubmit` event, returning a rejected promise. + It could be used for visual feedback about last submission: + + ```hbs + + + Save + + + ``` + + The submission state is reset as soon as any value of a form element changes. Additionally, it can be reset programmatically by + calling the yielded `resetSubmissionState` function. + + *Note that only invoking the component in a template as shown above is considered part of its public API. Extending from it (subclassing) is generally not supported, and may break at any time.* + + @class Form + @namespace Components + @extends Ember.Component + @public + */ + let Form = _exports.default = (_dec = (0, _emberRefBucket.ref)('formElement'), (_class = class Form extends _component2.default { /** - If you would like your adapter to use a custom serializer you can - set the `defaultSerializer` property to be the name of the custom - serializer. - Note the `defaultSerializer` serializer has a lower priority than - a model specific serializer (i.e. `PostSerializer`) or the - `application` serializer. - ```app/adapters/django.js - import DS from 'ember-data'; - export default DS.Adapter.extend({ - defaultSerializer: 'django' - }); - ``` - @property defaultSerializer - @type {String} - */ - defaultSerializer: '-default', + * Bootstrap form class name (computed) + * + * @property layoutClass + * @type string + * @readonly + * @protected + * + */ + get layoutClass() { + let layout = this.formLayout; + { + return null; + } + } /** - The `findRecord()` method is invoked when the store is asked for a record that - has not previously been loaded. In response to `findRecord()` being called, you - should query your persistence layer for a record with the given ID. The `findRecord` - method should return a promise that will resolve to a JavaScript object that will be - normalized by the serializer. - Here is an example `findRecord` implementation: - ```app/adapters/application.js - import Ember from 'ember'; - import DS from 'ember-data'; - export default DS.Adapter.extend({ - findRecord(store, type, id, snapshot) { - return new Ember.RSVP.Promise(function(resolve, reject) { - Ember.$.getJSON(`/${type.modelName}/${id}`).then(function(data) { - resolve(data); - }, function(jqXHR) { - reject(jqXHR); - }); - }); - } - }); - ``` - @method findRecord - @param {DS.Store} store - @param {DS.Model} type - @param {String} id - @param {DS.Snapshot} snapshot - @return {Promise} promise - */ - findRecord: null, + * Set a model that this form should represent. This serves several purposes: + * + * * child `Components.FormElement`s can access and bind to this model by their `property` + * * when the model supports validation by using the [ember-validations](https://github.com/dockyard/ember-validations) mixin, + * child `Components.FormElement`s will look at the validation information of their `property` and render their form group accordingly. + * Moreover, the form's `submit` event handler will validate the model and deny submitting if the model is not validated successfully. + * + * `` yields the form's model as `form` property: + * + * ```hbs + * + * {{! this.formModel === form.model }} + * + * ``` + * + * @property model + * @type object + * @public + */ + get model() { + return this.args.model ?? {}; + } /** - The `findAll()` method is used to retrieve all records for a given type. - Example - ```app/adapters/application.js - import Ember from 'ember'; - import DS from 'ember-data'; - export default DS.Adapter.extend({ - findAll(store, type, sinceToken) { - let query = { since: sinceToken }; - return new Ember.RSVP.Promise(function(resolve, reject) { - Ember.$.getJSON(`/${type.modelName}`, query).then(function(data) { - resolve(data); - }, function(jqXHR) { - reject(jqXHR); - }); - }); - } - }); - ``` - @method findAll - @param {DS.Store} store - @param {DS.Model} type - @param {String} sinceToken - @param {DS.SnapshotRecordArray} snapshotRecordArray - @return {Promise} promise - */ - findAll: null, + * Set the layout of the form to either "vertical", "horizontal" or "inline". See http://getbootstrap.com/css/#forms-inline and http://getbootstrap.com/css/#forms-horizontal + * + * @property formLayout + * @type string + * @public + */ /** - This method is called when you call `query` on the store. - Example - ```app/adapters/application.js - import Ember from 'ember'; - import DS from 'ember-data'; - export default DS.Adapter.extend({ - query(store, type, query) { - return new Ember.RSVP.Promise(function(resolve, reject) { - Ember.$.getJSON(`/${type.modelName}`, query).then(function(data) { - resolve(data); - }, function(jqXHR) { - reject(jqXHR); - }); - }); - } - }); - ``` - @method query - @param {DS.Store} store - @param {DS.Model} type - @param {Object} query - @param {DS.AdapterPopulatedRecordArray} recordArray - @return {Promise} promise - */ - query: null, + * @property elementComponent + * @type {String} + * @private + */ /** - The `queryRecord()` method is invoked when the store is asked for a single - record through a query object. - In response to `queryRecord()` being called, you should always fetch fresh - data. Once found, you can asynchronously call the store's `push()` method - to push the record into the store. - Here is an example `queryRecord` implementation: - Example - ```app/adapters/application.js - import Ember from 'ember'; - import DS from 'ember-data'; - export default DS.Adapter.extend(DS.BuildURLMixin, { - queryRecord(store, type, query) { - return new Ember.RSVP.Promise(function(resolve, reject) { - Ember.$.getJSON(`/${type.modelName}`, query).then(function(data) { - resolve(data); - }, function(jqXHR) { - reject(jqXHR); - }); - }); - } - }); - ``` - @method queryRecord - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {Object} query - @return {Promise} promise - */ - queryRecord: null, + * @property submitButtonComponent + * @type {String} + * @private + */ /** - If the globally unique IDs for your records should be generated on the client, - implement the `generateIdForRecord()` method. This method will be invoked - each time you create a new record, and the value returned from it will be - assigned to the record's `primaryKey`. - Most traditional REST-like HTTP APIs will not use this method. Instead, the ID - of the record will be set by the server, and your adapter will update the store - with the new ID when it calls `didCreateRecord()`. Only implement this method if - you intend to generate record IDs on the client-side. - The `generateIdForRecord()` method will be invoked with the requesting store as - the first parameter and the newly created record as the second parameter: - ```javascript - import DS from 'ember-data'; - import { v4 } from 'uuid'; - export default DS.Adapter.extend({ - generateIdForRecord(store, inputProperties) { - return v4(); - } - }); - ``` - @method generateIdForRecord - @param {DS.Store} store - @param {DS.Model} type the DS.Model class of the record - @param {Object} inputProperties a hash of properties to set on the - newly created record. - @return {(String|Number)} id - */ - generateIdForRecord: null, + * `isSubmitting` is `true` after `submit` event has been triggered and until Promise returned by `onSubmit` is + * fulfilled. If `validate` returns a Promise that one is also taken into consideration. + * + * If multiple concurrent submit events are fired, it stays `true` until all submit events have been fulfilled. + * + * @property isSubmitting + * @type {Boolean} + * @readonly + * @private + */ + get isSubmitting() { + return this.pendingSubmissions > 0; + } /** - Proxies to the serializer's `serialize` method. - Example - ```app/adapters/application.js - import DS from 'ember-data'; - export default DS.Adapter.extend({ - createRecord(store, type, snapshot) { - let data = this.serialize(snapshot, { includeId: true }); - let url = `/${type.modelName}`; - // ... - } - }); - ``` - @method serialize - @param {DS.Snapshot} snapshot - @param {Object} options - @return {Object} serialized snapshot - */ - serialize: function serialize(snapshot, options) { - return snapshot.serialize(options); - }, - + * `isSubmitted` is `true` if last submission was successful. + * A change to any form element resets its value to `false`. + * + * If not using `Components.FormElement`, `resetSubmissionState` action must be triggered on each change to reset + * form's submission state. + * + * @property isSubmitted + * @type {Boolean} + * @private + */ /** - Implement this method in a subclass to handle the creation of - new records. - Serializes the record and sends it to the server. - Example - ```app/adapters/application.js - import Ember from 'ember'; - import DS from 'ember-data'; - export default DS.Adapter.extend({ - createRecord(store, type, snapshot) { - let data = this.serialize(snapshot, { includeId: true }); - return new Ember.RSVP.Promise(function(resolve, reject) { - Ember.$.ajax({ - type: 'POST', - url: `/${type.modelName}`, - dataType: 'json', - data: data - }).then(function(data) { - Ember.run(null, resolve, data); - }, function(jqXHR) { - jqXHR.then = null; // tame jQuery's ill mannered promises - Ember.run(null, reject, jqXHR); - }); - }); - } - }); - ``` - @method createRecord - @param {DS.Store} store - @param {DS.Model} type the DS.Model class of the record - @param {DS.Snapshot} snapshot - @return {Promise} promise - */ - createRecord: null, + * State of the form expressed as state values expected by ``. + * + * @property submitButtonState + * @type {String} + * @private + */ + get submitButtonState() { + if (this.isSubmitting) { + return 'pending'; + } + if (this.isSubmitted) { + return 'fulfilled'; + } + if (this.isRejected) { + return 'rejected'; + } + return 'default'; + } /** - Implement this method in a subclass to handle the updating of - a record. - Serializes the record update and sends it to the server. - The updateRecord method is expected to return a promise that will - resolve with the serialized record. This allows the backend to - inform the Ember Data store the current state of this record after - the update. If it is not possible to return a serialized record - the updateRecord promise can also resolve with `undefined` and the - Ember Data store will assume all of the updates were successfully - applied on the backend. - Example - ```app/adapters/application.js - import Ember from 'ember'; - import DS from 'ember-data'; - export default DS.Adapter.extend({ - updateRecord(store, type, snapshot) { - let data = this.serialize(snapshot, { includeId: true }); - let id = snapshot.id; - return new Ember.RSVP.Promise(function(resolve, reject) { - Ember.$.ajax({ - type: 'PUT', - url: `/${type.modelName}/${id}`, - dataType: 'json', - data: data - }).then(function(data) { - Ember.run(null, resolve, data); - }, function(jqXHR) { - jqXHR.then = null; // tame jQuery's ill mannered promises - Ember.run(null, reject, jqXHR); - }); - }); - } - }); - ``` - @method updateRecord - @param {DS.Store} store - @param {DS.Model} type the DS.Model class of the record - @param {DS.Snapshot} snapshot - @return {Promise} promise - */ - updateRecord: null, + * Count of pending submissions. + * + * @property pendingSubmissions + * @type {Integer} + * @private + */ /** - Implement this method in a subclass to handle the deletion of - a record. - Sends a delete request for the record to the server. - Example - ```app/adapters/application.js - import Ember from 'ember'; - import DS from 'ember-data'; - export default DS.Adapter.extend({ - deleteRecord(store, type, snapshot) { - let data = this.serialize(snapshot, { includeId: true }); - let id = snapshot.id; - return new Ember.RSVP.Promise(function(resolve, reject) { - Ember.$.ajax({ - type: 'DELETE', - url: `/${type.modelName}/${id}`, - dataType: 'json', - data: data - }).then(function(data) { - Ember.run(null, resolve, data); - }, function(jqXHR) { - jqXHR.then = null; // tame jQuery's ill mannered promises - Ember.run(null, reject, jqXHR); - }); - }); - } - }); - ``` - @method deleteRecord - @param {DS.Store} store - @param {DS.Model} type the DS.Model class of the record - @param {DS.Snapshot} snapshot - @return {Promise} promise - */ - deleteRecord: null, + * If true, after successful validation and upon submitting the form, all current element validations will be hidden. + * If the form remains visible, the user would have to focus out of elements of submit the form again for the + * validations to show up again, as if a fresh new form component had been rendered. + * + * @property hideValidationsOnSubmit + * @type {Boolean} + * @default false + * @public + */ /** - By default the store will try to coalesce all `fetchRecord` calls within the same runloop - into as few requests as possible by calling groupRecordsForFindMany and passing it into a findMany call. - You can opt out of this behaviour by either not implementing the findMany hook or by setting - coalesceFindRequests to false. - @property coalesceFindRequests - @type {boolean} - */ - coalesceFindRequests: true, + * If set to true the `readonly` property of all yielded form elements will be set, making their form controls read-only. + * + * @property readonly + * @type boolean + * @default false + * @public + */ /** - The store will call `findMany` instead of multiple `findRecord` - requests to find multiple records at once if coalesceFindRequests - is true. - ```app/adapters/application.js - import Ember from 'ember'; - import DS from 'ember-data'; - export default DS.Adapter.extend({ - findMany(store, type, ids, snapshots) { - return new Ember.RSVP.Promise(function(resolve, reject) { - Ember.$.ajax({ - type: 'GET', - url: `/${type.modelName}/`, - dataType: 'json', - data: { filter: { id: ids.join(',') } } - }).then(function(data) { - Ember.run(null, resolve, data); - }, function(jqXHR) { - jqXHR.then = null; // tame jQuery's ill mannered promises - Ember.run(null, reject, jqXHR); - }); - }); - } - }); - ``` - @method findMany - @param {DS.Store} store - @param {DS.Model} type the DS.Model class of the records - @param {Array} ids - @param {Array} snapshots - @return {Promise} promise - */ - findMany: null, + * If set to true the `disabled` property of all yielded form elements will be set, making their form controls disabled. + * + * @property disabled + * @type boolean + * @default false + * @public + */ /** - Organize records into groups, each of which is to be passed to separate - calls to `findMany`. - For example, if your api has nested URLs that depend on the parent, you will - want to group records by their parent. - The default implementation returns the records as a single group. - @method groupRecordsForFindMany - @param {DS.Store} store - @param {Array} snapshots - @return {Array} an array of arrays of records, each of which is to be - loaded separately by `findMany`. - */ - groupRecordsForFindMany: function groupRecordsForFindMany(store, snapshots) { - return [snapshots]; - }, - + * Validate hook which will return a promise that will either resolve if the model is valid + * or reject if it's not. This should be overridden to add validation support. + * + * @method validate + * @param {Object} model + * @param {HTMLFormElement} form + * @return {Promise} + * @public + */ + validate(model, form) {} // eslint-disable-line no-unused-vars /** - This method is used by the store to determine if the store should - reload a record from the adapter when a record is requested by - `store.findRecord`. - If this method returns `true`, the store will re-fetch a record from - the adapter. If this method returns `false`, the store will resolve - immediately using the cached record. - For example, if you are building an events ticketing system, in which users - can only reserve tickets for 20 minutes at a time, and want to ensure that - in each route you have data that is no more than 20 minutes old you could - write: - ```javascript - shouldReloadRecord(store, ticketSnapshot) { - let lastAccessedAt = ticketSnapshot.attr('lastAccessedAt'); - let timeDiff = moment().diff(lastAccessedAt, 'minutes'); - if (timeDiff > 20) { - return true; - } else { - return false; - } - } - ``` - This method would ensure that whenever you do `store.findRecord('ticket', - id)` you will always get a ticket that is no more than 20 minutes old. In - case the cached version is more than 20 minutes old, `findRecord` will not - resolve until you fetched the latest version. - By default this hook returns `false`, as most UIs should not block user - interactions while waiting on data update. - Note that, with default settings, `shouldBackgroundReloadRecord` will always - re-fetch the records in the background even if `shouldReloadRecord` returns - `false`. You can override `shouldBackgroundReloadRecord` if this does not - suit your use case. - @since 1.13.0 - @method shouldReloadRecord - @param {DS.Store} store - @param {DS.Snapshot} snapshot - @return {Boolean} - */ - shouldReloadRecord: function shouldReloadRecord(store, snapshot) { - return false; - }, + * @property _showAllValidations + * @type boolean + * @default undefined + * @private + */ + get showAllValidations() { + return this.showValidations ?? this._showAllValidations; + } + set showAllValidations(showAllValidations) { + this._showAllValidations = showAllValidations; + } /** - This method is used by the store to determine if the store should - reload all records from the adapter when records are requested by - `store.findAll`. - If this method returns `true`, the store will re-fetch all records from - the adapter. If this method returns `false`, the store will resolve - immediately using the cached records. - For example, if you are building an events ticketing system, in which users - can only reserve tickets for 20 minutes at a time, and want to ensure that - in each route you have data that is no more than 20 minutes old you could - write: - ```javascript - shouldReloadAll(store, snapshotArray) { - let snapshots = snapshotArray.snapshots(); - return snapshots.any((ticketSnapshot) => { - let lastAccessedAt = ticketSnapshot.attr('lastAccessedAt'); - let timeDiff = moment().diff(lastAccessedAt, 'minutes'); - if (timeDiff > 20) { - return true; - } else { - return false; - } - }); - } - ``` - This method would ensure that whenever you do `store.findAll('ticket')` you - will always get a list of tickets that are no more than 20 minutes old. In - case a cached version is more than 20 minutes old, `findAll` will not - resolve until you fetched the latest versions. - By default this methods returns `true` if the passed `snapshotRecordArray` - is empty (meaning that there are no records locally available yet), - otherwise it returns `false`. - Note that, with default settings, `shouldBackgroundReloadAll` will always - re-fetch all the records in the background even if `shouldReloadAll` returns - `false`. You can override `shouldBackgroundReloadAll` if this does not suit - your use case. - @since 1.13.0 - @method shouldReloadAll - @param {DS.Store} store - @param {DS.SnapshotRecordArray} snapshotRecordArray - @return {Boolean} - */ - shouldReloadAll: function shouldReloadAll(store, snapshotRecordArray) { - return !snapshotRecordArray.length; - }, + * Controls visibility of validation errors. If `null` (default) validation errors are shown after user + * interactions like form submission, focus out event of input fields etc. If `true` all validation errors are shown + * immediately independently of user interactions. If `false` validation errors are not shown in any case (but + * prevent form submission if form is invalid). + * + * @property showValidations + * @type Boolean|null + * @default null + * @public + */ + /** + * Action is called before the form is validated (if possible) and submitted. + * + * @event onBefore + * @param { Object } model The form's `model` + * @public + */ /** - This method is used by the store to determine if the store should - reload a record after the `store.findRecord` method resolves a - cached record. - This method is *only* checked by the store when the store is - returning a cached record. - If this method returns `true` the store will re-fetch a record from - the adapter. - For example, if you do not want to fetch complex data over a mobile - connection, or if the network is down, you can implement - `shouldBackgroundReloadRecord` as follows: - ```javascript - shouldBackgroundReloadRecord(store, snapshot) { - let connection = window.navigator.connection; - if (connection === 'cellular' || connection === 'none') { - return false; - } else { - return true; - } - } - ``` - By default this hook returns `true` so the data for the record is updated - in the background. - @since 1.13.0 - @method shouldBackgroundReloadRecord - @param {DS.Store} store - @param {DS.Snapshot} snapshot - @return {Boolean} - */ - shouldBackgroundReloadRecord: function shouldBackgroundReloadRecord(store, snapshot) { - return true; - }, + * Action is called when submit has been triggered and the model has passed all validations (if present). + * + * @event onSubmit + * @param { Object } model The form's `model` + * @param { Object } result The returned result from the validate method, if validation is available + * @public + */ + /** + * Action is called when validation of the model has failed. + * + * @event onInvalid + * @param { Object } model The form's `model` + * @param { Object } error + * @public + */ /** - This method is used by the store to determine if the store should - reload a record array after the `store.findAll` method resolves - with a cached record array. - This method is *only* checked by the store when the store is - returning a cached record array. - If this method returns `true` the store will re-fetch all records - from the adapter. - For example, if you do not want to fetch complex data over a mobile - connection, or if the network is down, you can implement - `shouldBackgroundReloadAll` as follows: - ```javascript - shouldBackgroundReloadAll(store, snapshotArray) { - let connection = window.navigator.connection; - if (connection === 'cellular' || connection === 'none') { - return false; - } else { - return true; - } + * Submit handler that will send the default action ("action") to the controller when submitting the form. + * + * If there is a supplied `model` that supports validation (`hasValidator`) the model will be validated before, and + * only if validation is successful the default action will be sent. Otherwise, an "invalid" action will be sent, and + * all the `showValidation` property of all child `Components.FormElement`s will be set to true, so error state and + * messages will be shown automatically. + * + * @method submit + * @private + */ + submitHandler(e, throwValidationErrors = true) { + if (e) { + e.preventDefault(); + } + if (this.preventConcurrency && this.isSubmitting) { + return Promise.resolve(); + } + let model = this.model; + this.pendingSubmissions++; + this.args.onBefore?.(model); + return Promise.resolve().then(() => { + return this.hasValidator ? this.validate(model, this._element) : null; + }).then(record => { + if (this.args.hideValidationsOnSubmit === true) { + this.showAllValidations = false; + } + return Promise.resolve().then(() => { + return this.args.onSubmit?.(model, record); + }).then(() => { + if (this.isDestroyed) { + return; + } + this.isSubmitted = true; + }).catch(error => { + if (this.isDestroyed) { + return; + } + this.isRejected = true; + throw error; + }).finally(() => { + if (this.isDestroyed) { + return; + } + this.pendingSubmissions--; + + // reset forced hiding of validations + if (this.showAllValidations === false) { + (0, _runloop.next)(() => this.showAllValidations = undefined); + } + }); + }, error => { + return Promise.resolve().then(() => { + return this.args.onInvalid?.(model, error); + }).finally(() => { + if (this.isDestroyed) { + return; + } + this.showAllValidations = true; + this.isRejected = true; + this.pendingSubmissions = this.pendingSubmissions - 1; + if (throwValidationErrors) { + throw error; + } + }); + }); + } + handleSubmit(event) { + this.submitHandler(event, false); + } + handleKeyPress(event) { + let code = event.keyCode || event.which; + if (code === 13 && this.args.submitOnEnter) { + this.submitHandler(); } - ``` - By default this method returns `true`, indicating that a background reload - should always be triggered. - @since 1.13.0 - @method shouldBackgroundReloadAll - @param {DS.Store} store - @param {DS.SnapshotRecordArray} snapshotRecordArray - @return {Boolean} - */ - shouldBackgroundReloadAll: function shouldBackgroundReloadAll(store, snapshotRecordArray) { + } + constructor() { + super(...arguments); + /** + * @property _element + * @type null | HTMLFormElement + * @private + */ + _initializerDefineProperty(this, "_element", _descriptor, this); + _initializerDefineProperty(this, "formLayout", _descriptor2, this); + /** + * Check if validating the model is supported. This needs to be implemented by another addon. + * + * @property hasValidator + * @type boolean + * @readonly + * @protected + */ + /** + * The Bootstrap grid classes for form labels. This is used by the `Components.FormElement` class as a default for the + * whole form. + * + * @property horizontalLabelGridClass + * @type string + * @default 'col-md-4' + * @public + */ + _initializerDefineProperty(this, "horizontalLabelGridClass", _descriptor3, this); + _initializerDefineProperty(this, "isSubmitted", _descriptor4, this); + /** + * `isRejected` is `true` if last submission was rejected. + * A submission is considered as rejected if form is invalid as well as if `onSubmit` rejects. + * A change to any form element resets its value to `false`. + * + * If not using `Components.FormElement`, `resetSubmissionState` action must be triggered on each change to reset + * form's submission state. + * + * @property isRejected + * @type {Boolean} + * @private + */ + _initializerDefineProperty(this, "isRejected", _descriptor5, this); + _initializerDefineProperty(this, "pendingSubmissions", _descriptor6, this); + /** + * If set to true pressing enter will submit the form, even if no submit button is present + * + * @property submitOnEnter + * @type boolean + * @default false + * @public + */ + /** + * Controls if `onSubmit` action is fired concurrently. If `true` submitting form multiple + * times will not trigger `onSubmit` action if a Promise returned by previous submission is + * not settled yet. + * + * Dropping a submission also prevents rerunning validation and `onBefore` hook. + * + * @property preventConcurrency + * @type Boolean + * @default true + * @public + */ + _initializerDefineProperty(this, "preventConcurrency", _descriptor7, this); + _initializerDefineProperty(this, "_showAllValidations", _descriptor8, this); + _initializerDefineProperty(this, "showValidations", _descriptor9, this); + let formLayout = this.formLayout; + (true && !(['vertical', 'horizontal', 'inline'].indexOf(formLayout) >= 0) && (0, _debug.assert)(`Invalid formLayout property given: ${formLayout}`, ['vertical', 'horizontal', 'inline'].indexOf(formLayout) >= 0)); + } + elementChanged(value, model, property) { + (true && !((0, _utils.isPresent)(model) && (0, _utils.isPresent)(property)) && (0, _debug.assert)("You cannot use the form element's default onChange action for form elements if not using a model or setting the value directly on a form element. You must add your own onChange action to the form element in this case!", (0, _utils.isPresent)(model) && (0, _utils.isPresent)(property))); + if (typeof model.set === 'function') { + model.set(property, value); + } else { + (0, _object.set)(model, property, value); + } + } + resetSubmissionState() { + this.isSubmitted = false; + this.isRejected = false; + } + doSubmit() { + return this.submitHandler(); + } + }, (_descriptor = _applyDecoratedDescriptor(_class.prototype, "_element", [_dec], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return null; + } + }), _applyDecoratedDescriptor(_class.prototype, "model", [_tracking.cached], Object.getOwnPropertyDescriptor(_class.prototype, "model"), _class.prototype), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "formLayout", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return 'vertical'; + } + }), _descriptor3 = _applyDecoratedDescriptor(_class.prototype, "horizontalLabelGridClass", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return 'col-md-4'; + } + }), _descriptor4 = _applyDecoratedDescriptor(_class.prototype, "isSubmitted", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return false; + } + }), _descriptor5 = _applyDecoratedDescriptor(_class.prototype, "isRejected", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return false; + } + }), _descriptor6 = _applyDecoratedDescriptor(_class.prototype, "pendingSubmissions", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return 0; + } + }), _descriptor7 = _applyDecoratedDescriptor(_class.prototype, "preventConcurrency", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { return true; } - }); + }), _descriptor8 = _applyDecoratedDescriptor(_class.prototype, "_showAllValidations", [_tracking.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return undefined; + } + }), _descriptor9 = _applyDecoratedDescriptor(_class.prototype, "showValidations", [_arg.default], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return null; + } + }), _applyDecoratedDescriptor(_class.prototype, "handleSubmit", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "handleSubmit"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "handleKeyPress", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "handleKeyPress"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "elementChanged", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "elementChanged"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "resetSubmissionState", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "resetSubmissionState"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "doSubmit", [_object.action], Object.getOwnPropertyDescriptor(_class.prototype, "doSubmit"), _class.prototype)), _class)); + (0, _component.setComponentTemplate)(__COLOCATED_TEMPLATE__, Form); }); -define('ember-data/adapters/errors', ['exports', 'ember', 'ember-data/-private/debug', 'ember-data/-private/features'], function (exports, _ember, _debug, _features) { - 'use strict'; +;define("ember-bootstrap/components/bs-form/element", ["exports", "@ember/component", "@glimmer/component", "@glimmer/tracking", "@ember/object", "@ember/debug", "@ember/utils", "@ember/array", "@ember/application", "@ember/object/internals", "ember-ref-bucket", "ember-bootstrap/components/bs-form/element/control/input", "ember-bootstrap/components/bs-form/element/control/checkbox", "ember-bootstrap/components/bs-form/element/control/textarea", "ember-bootstrap/components/bs-form/element/control/radio", "ember-bootstrap/components/bs-form/element/control/switch", "ember-bootstrap/utils/decorators/arg", "tracked-toolbox", "@ember/template-factory"], function (_exports, _component, _component2, _tracking, _object, _debug, _utils, _array, _application, _internals, _emberRefBucket, _input, _checkbox, _textarea, _radio, _switch, _arg, _trackedToolbox, _templateFactory) { + "use strict"; - Object.defineProperty(exports, "__esModule", { + Object.defineProperty(_exports, "__esModule", { value: true }); - exports.ServerError = exports.ConflictError = exports.NotFoundError = exports.ForbiddenError = exports.UnauthorizedError = exports.AbortError = exports.TimeoutError = exports.InvalidError = undefined; - exports.AdapterError = AdapterError; - exports.errorsHashToArray = errorsHashToArray; - exports.errorsArrayToHash = errorsArrayToHash; - - - var EmberError = _ember.default.Error; - - var SOURCE_POINTER_REGEXP = /^\/?data\/(attributes|relationships)\/(.*)/; - var SOURCE_POINTER_PRIMARY_REGEXP = /^\/?data/; - var PRIMARY_ATTRIBUTE_KEY = 'base'; + _exports.default = void 0; + var _dec, _class, _descriptor, _descriptor2, _descriptor3, _descriptor4, _descriptor5, _descriptor6, _descriptor7, _descriptor8, _descriptor9, _descriptor10; + 0; //eaimeta@70e063a35619d71f0,"@glimmer/component",0,"@glimmer/tracking",0,"@ember/object",0,"@ember/debug",0,"@ember/utils",0,"@ember/array",0,"@ember/application",0,"@ember/object/internals",0,"ember-ref-bucket",0,"ember-bootstrap/components/bs-form/element/control/input",0,"ember-bootstrap/components/bs-form/element/control/checkbox",0,"ember-bootstrap/components/bs-form/element/control/textarea",0,"ember-bootstrap/components/bs-form/element/control/radio",0,"ember-bootstrap/components/bs-form/element/control/switch",0,"ember-bootstrap/utils/decorators/arg",0,"tracked-toolbox",0,"@ember/template-factory",0,"@ember/component"eaimeta@70e063a35619d71f + function _initializerDefineProperty(e, i, r, l) { r && Object.defineProperty(e, i, { enumerable: r.enumerable, configurable: r.configurable, writable: r.writable, value: r.initializer ? r.initializer.call(l) : void 0 }); } + function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } + function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } + function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } + function _applyDecoratedDescriptor(i, e, r, n, l) { var a = {}; return Object.keys(n).forEach(function (i) { a[i] = n[i]; }), a.enumerable = !!a.enumerable, a.configurable = !!a.configurable, ("value" in a || a.initializer) && (a.writable = !0), a = r.slice().reverse().reduce(function (r, n) { return n(i, e, r) || r; }, a), l && void 0 !== a.initializer && (a.value = a.initializer ? a.initializer.call(l) : void 0, a.initializer = void 0), void 0 === a.initializer && (Object.defineProperty(i, e, a), a = null), a; } + function _initializerWarningHelper(r, e) { throw Error("Decorating class property failed. Please ensure that transform-class-properties is enabled and runs after the decorators transform."); } + const __COLOCATED_TEMPLATE__ = (0, _templateFactory.createTemplateFactory)( + /* + {{! @glint-nocheck }} + {{!-- template-lint-disable no-invalid-interactive --}} +
+ {{#component + (ensure-safe-component + (bs-default + @layoutComponent + (if + (bs-contains (array "checkbox" "switch") this.controlType) + (if + (bs-eq @formLayout "inline") + (component "bs-form/element/layout/inline/checkbox" controlType=this.controlType) + (if + (bs-eq @formLayout "horizontal") + (component "bs-form/element/layout/horizontal/checkbox" controlType=this.controlType) + (component "bs-form/element/layout/vertical/checkbox" controlType=this.controlType) + ) + ) + (if + (bs-eq @formLayout "inline") + (component "bs-form/element/layout/inline") + (if + (bs-eq @formLayout "horizontal") + (component "bs-form/element/layout/horizontal") + (component "bs-form/element/layout/vertical") + ) + ) + ) + ) + ) + hasLabel=(if @label true false) + formElementId=this.formElementId + horizontalLabelGridClass=@horizontalLabelGridClass + errorsComponent=(component (ensure-safe-component (bs-default @errorsComponent (component "bs-form/element/errors"))) + messages=this.validationMessages + show=this.showValidationMessages + showMultipleErrors=this.showMultipleErrors + ) + feedbackIconComponent=(component (ensure-safe-component (bs-default @feedbackIconComponent (component "bs-form/element/feedback-icon"))) + iconName=@iconName + show=this.hasFeedback + ) + labelComponent=(component + (ensure-safe-component + (bs-default + @labelComponent + (if + (bs-eq this.controlType "radio") + (component "bs-form/element/legend") + (component "bs-form/element/label") + ) + ) + ) + label=@label + invisibleLabel=@invisibleLabel + formElementId=this.formElementId + controlType=this.controlType + formLayout=@formLayout + size=@size + ) + helpTextComponent=(if @helpText + (component (ensure-safe-component (bs-default @helpTextComponent (component "bs-form/element/help-text"))) + text=@helpText + id=this.ariaDescribedBy + ) + ) + }} + {{! + Ember does not allow to access a variable with `@` in template if its name start with an underscore. + `@_disabled` and `@_readonly` are affected by this. As a work-a-round we access them on `this.args`. + }} + {{!-- template-lint-disable no-args-paths --}} + {{#let + (component + (ensure-safe-component + (bs-default + @controlComponent + this.controlComponent + ) + ) + value=this.value + id=this.formElementId + type=this.controlType + label=@label + disabled=this.args._disabled + readonly=this.args._readonly + required=@required + options=@options + optionLabelPath=@optionLabelPath + ariaDescribedBy=(if @helpText this.ariaDescribedBy) + onChange=this.doChange + validationType=this.validation + size=@size + ) as |Control|}} + {{!-- template-lint-enable no-args-paths --}} + {{#if (has-block)}} + {{yield + (hash + value=this.value + setValue=this.doChange + id=this.formElementId + validation=this.validation + control=Control + ) + }} + {{else}} + + {{/if}} + {{/let}} + {{/component}} +
+ + */ + { + "id": "IQhH0eUO", + "block": "[[[11,0],[16,0,[29,[[27],\" \",[52,[28,[37,2],[[30,1],\"vertical\"],null],\"mb-3\"],\" \",[52,[28,[37,2],[[30,1],\"horizontal\"],null],\"row mb-3\"]]]],[17,2],[4,[38,3],[\"mainNode\"],[[\"debugName\",\"bucket\"],[\"create-ref\",[30,0]]]],[4,[38,4],[\"focusout\",[30,0,[\"showValidationOnHandler\"]]],null],[4,[38,4],[\"change\",[30,0,[\"showValidationOnHandler\"]]],null],[4,[38,4],[\"input\",[30,0,[\"showValidationOnHandler\"]]],null],[4,[38,5],[[30,0,[\"handleShowAllValidationsChange\"]],[30,0,[\"showAllValidations\"]]],null],[12],[1,\"\\n\"],[46,[28,[37,7],[[28,[37,8],[[30,3],[52,[28,[37,9],[[28,[37,10],[\"checkbox\",\"switch\"],null],[30,0,[\"controlType\"]]],null],[52,[28,[37,2],[[30,1],\"inline\"],null],[50,\"bs-form/element/layout/inline/checkbox\",0,null,[[\"controlType\"],[[30,0,[\"controlType\"]]]]],[52,[28,[37,2],[[30,1],\"horizontal\"],null],[50,\"bs-form/element/layout/horizontal/checkbox\",0,null,[[\"controlType\"],[[30,0,[\"controlType\"]]]]],[50,\"bs-form/element/layout/vertical/checkbox\",0,null,[[\"controlType\"],[[30,0,[\"controlType\"]]]]]]],[52,[28,[37,2],[[30,1],\"inline\"],null],[50,\"bs-form/element/layout/inline\",0,null,null],[52,[28,[37,2],[[30,1],\"horizontal\"],null],[50,\"bs-form/element/layout/horizontal\",0,null,null],[50,\"bs-form/element/layout/vertical\",0,null,null]]]]],null]],null],null,[[\"hasLabel\",\"formElementId\",\"horizontalLabelGridClass\",\"errorsComponent\",\"feedbackIconComponent\",\"labelComponent\",\"helpTextComponent\"],[[52,[30,4],true,false],[30,0,[\"formElementId\"]],[30,5],[50,[28,[37,7],[[28,[37,8],[[30,6],[50,\"bs-form/element/errors\",0,null,null]],null]],null],0,null,[[\"messages\",\"show\",\"showMultipleErrors\"],[[30,0,[\"validationMessages\"]],[30,0,[\"showValidationMessages\"]],[30,0,[\"showMultipleErrors\"]]]]],[50,[28,[37,7],[[28,[37,8],[[30,7],[50,\"bs-form/element/feedback-icon\",0,null,null]],null]],null],0,null,[[\"iconName\",\"show\"],[[30,8],[30,0,[\"hasFeedback\"]]]]],[50,[28,[37,7],[[28,[37,8],[[30,9],[52,[28,[37,2],[[30,0,[\"controlType\"]],\"radio\"],null],[50,\"bs-form/element/legend\",0,null,null],[50,\"bs-form/element/label\",0,null,null]]],null]],null],0,null,[[\"label\",\"invisibleLabel\",\"formElementId\",\"controlType\",\"formLayout\",\"size\"],[[30,4],[30,10],[30,0,[\"formElementId\"]],[30,0,[\"controlType\"]],[30,1],[30,11]]]],[52,[30,12],[50,[28,[37,7],[[28,[37,8],[[30,13],[50,\"bs-form/element/help-text\",0,null,null]],null]],null],0,null,[[\"text\",\"id\"],[[30,12],[30,0,[\"ariaDescribedBy\"]]]]]]]],[[\"default\"],[[[[44,[[50,[28,[37,7],[[28,[37,8],[[30,14],[30,0,[\"controlComponent\"]]],null]],null],0,null,[[\"value\",\"id\",\"type\",\"label\",\"disabled\",\"readonly\",\"required\",\"options\",\"optionLabelPath\",\"ariaDescribedBy\",\"onChange\",\"validationType\",\"size\"],[[30,0,[\"value\"]],[30,0,[\"formElementId\"]],[30,0,[\"controlType\"]],[30,4],[30,0,[\"args\",\"_disabled\"]],[30,0,[\"args\",\"_readonly\"]],[30,15],[30,16],[30,17],[52,[30,12],[30,0,[\"ariaDescribedBy\"]]],[30,0,[\"doChange\"]],[30,0,[\"validation\"]],[30,11]]]]],[[[41,[48,[30,19]],[[[1,\" \"],[18,19,[[28,[37,14],null,[[\"value\",\"setValue\",\"id\",\"validation\",\"control\"],[[30,0,[\"value\"]],[30,0,[\"doChange\"]],[30,0,[\"formElementId\"]],[30,0,[\"validation\"]],[30,18]]]]]],[1,\"\\n\"]],[]],[[[1,\" \"],[8,[30,18],null,null,null],[1,\"\\n\"]],[]]]],[18]]]],[]]]]],[13],[1,\"\\n\"]],[\"@formLayout\",\"&attrs\",\"@layoutComponent\",\"@label\",\"@horizontalLabelGridClass\",\"@errorsComponent\",\"@feedbackIconComponent\",\"@iconName\",\"@labelComponent\",\"@invisibleLabel\",\"@size\",\"@helpText\",\"@helpTextComponent\",\"@controlComponent\",\"@required\",\"@options\",\"@optionLabelPath\",\"Control\",\"&default\"],false,[\"div\",\"if\",\"bs-eq\",\"create-ref\",\"on\",\"did-update\",\"component\",\"ensure-safe-component\",\"bs-default\",\"bs-contains\",\"array\",\"let\",\"has-block\",\"yield\",\"hash\"]]", + "moduleName": "ember-bootstrap/components/bs-form/element.hbs", + "isStrictMode": false + }); /** - A `DS.AdapterError` is used by an adapter to signal that an error occurred - during a request to an external API. It indicates a generic error, and - subclasses are used to indicate specific error states. The following - subclasses are provided: - - - `DS.InvalidError` - - `DS.TimeoutError` - - `DS.AbortError` - - `DS.UnauthorizedError` - - `DS.ForbiddenError` - - `DS.NotFoundError` - - `DS.ConflictError` - - `DS.ServerError` + Subclass of `Components.FormGroup` that adds automatic form layout markup and form validation features. - To create a custom error to signal a specific error state in communicating - with an external API, extend the `DS.AdapterError`. For example if the - external API exclusively used HTTP `503 Service Unavailable` to indicate - it was closed for maintenance: + ### Form layout - ```app/adapters/maintenance-error.js - import DS from 'ember-data'; + The appropriate Bootstrap markup for the given `formLayout` and `controlType` is automatically generated to easily + create forms without coding the default Bootstrap form markup by hand: - export default DS.AdapterError.extend({ message: "Down for maintenance." }); + ```handlebars + + + + + + ``` - This error would then be returned by an adapter's `handleResponse` method: - - ```app/adapters/application.js - import DS from 'ember-data'; - import MaintenanceError from './maintenance-error'; - - export default DS.JSONAPIAdapter.extend({ - handleResponse(status) { - if (503 === status) { - return new MaintenanceError(); - } + ### Control types - return this._super(...arguments); - } - }); - ``` + The following control types are supported out of the box: - And can then be detected in an application and used to send the user to an - `under-maintenance` route: + * Inputs (simple `text`, or any other HTML5 supported input types like `password`, `email` etc.) + * Checkbox (single) + * Radio Button (group) + * Textarea + * Switch (BS4 Only) - ```app/routes/application.js - import Ember from 'ember'; - import MaintenanceError from '../adapters/maintenance-error'; + #### Radio Buttons - export default Ember.Route.extend({ - actions: { - error(error, transition) { - if (error instanceof MaintenanceError) { - this.transitionTo('under-maintenance'); - return; - } + For a group of mutually exclusive radio buttons to work, you must supply the `options` property with an array of + options, each of which will be rendered with an appropriate radio button and its label. It can be either a simple array + of strings or objects. In the latter case, you would have to set `optionLabelPath` to the property, that contains the + label on these objects. - // ...other error handling logic - } - } - }); + ```hbs + + + ``` - @class AdapterError - @namespace DS - */ - function AdapterError(errors) { - var message = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'Adapter operation failed'; - - this.isAdapterError = true; - EmberError.call(this, message); - - this.errors = errors || [{ - title: 'Adapter Error', - detail: message - }]; - } - - var extendedErrorsEnabled = false; - if (true) { - extendedErrorsEnabled = true; - } - - function extendFn(ErrorClass) { - return function () { - var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, - defaultMessage = _ref.message; - - return extend(ErrorClass, defaultMessage); - }; - } - - function extend(ParentErrorClass, defaultMessage) { - var ErrorClass = function ErrorClass(errors, message) { - (0, _debug.assert)('`AdapterError` expects json-api formatted errors array.', Array.isArray(errors || [])); - ParentErrorClass.call(this, errors, message || defaultMessage); - }; - ErrorClass.prototype = Object.create(ParentErrorClass.prototype); - - if (extendedErrorsEnabled) { - ErrorClass.extend = extendFn(ErrorClass); - } - - return ErrorClass; - } - - AdapterError.prototype = Object.create(EmberError.prototype); - - if (extendedErrorsEnabled) { - AdapterError.extend = extendFn(AdapterError); - } - - /** - A `DS.InvalidError` is used by an adapter to signal the external API - was unable to process a request because the content was not - semantically correct or meaningful per the API. Usually this means a - record failed some form of server side validation. When a promise - from an adapter is rejected with a `DS.InvalidError` the record will - transition to the `invalid` state and the errors will be set to the - `errors` property on the record. - - For Ember Data to correctly map errors to their corresponding - properties on the model, Ember Data expects each error to be - a valid json-api error object with a `source/pointer` that matches - the property name. For example if you had a Post model that - looked like this. - - ```app/models/post.js - import DS from 'ember-data'; + The default layout for radios is stacked, but Bootstrap's inline layout is also supported using the `inline` property + of the yielded control component: - export default DS.Model.extend({ - title: DS.attr('string'), - content: DS.attr('string') - }); + ```hbs + + + + + ``` - To show an error from the server related to the `title` and - `content` properties your adapter could return a promise that - rejects with a `DS.InvalidError` object that looks like this: + #### Custom controls - ```app/adapters/post.js - import Ember from 'ember'; - import DS from 'ember-data'; + Apart from the standard built-in browser controls (see the `controlType` property), you can use any custom control simply + by invoking the component with a block template. Use whatever control you might want, for example a `` + component (from the [ember-pikaday addon](https://github.com/adopted-ember-addons/ember-pikaday)): - export default DS.RESTAdapter.extend({ - updateRecord() { - // Fictional adapter that always rejects - return Ember.RSVP.reject(new DS.InvalidError([ - { - detail: 'Must be unique', - source: { pointer: '/data/attributes/title' } - }, - { - detail: 'Must not be blank', - source: { pointer: '/data/attributes/content'} - } - ])); - } - }); + ```hbs + + + + + ``` - Your backend may use different property names for your records the - store will attempt extract and normalize the errors using the - serializer's `extractErrors` method before the errors get added to - the the model. As a result, it is safe for the `InvalidError` to - wrap the error payload unaltered. + The component yields a hash with the following properties: + * `control`: the component that would be used for rendering the form control based on the given `controlType` + * `id`: id to be used for the form control, so it matches the labels `for` attribute + * `value`: the value of the form element + * `setValue`: function to change the value of the form element + * `validation`: the validation state of the element, `null` if no validation is to be shown, otherwise 'success', 'error' or 'warning' - @class InvalidError - @namespace DS - */ - var InvalidError = exports.InvalidError = extend(AdapterError, 'The adapter rejected the commit because it was invalid'); - - /** - A `DS.TimeoutError` is used by an adapter to signal that a request - to the external API has timed out. I.e. no response was received from - the external API within an allowed time period. + If you just want to customize the existing control component, you can use the aforementioned yielded `control` component + to customize that existing component: - An example use case would be to warn the user to check their internet - connection if an adapter operation has timed out: + ```hbs + + + + + + ``` - ```app/routes/application.js - import Ember from 'ember'; - import DS from 'ember-data'; + If you are using the custom control quite often, you should consider writing an integration plugin like + [`ember-bootstrap-power-select`](https://github.com/kaliber5/ember-bootstrap-power-select). + To do so, you need to provide a component `{{bs-form/element/control/my-custom-control}}` which extends + [`Components.FormElementControl`](Components.FormElementControl.html). - const { TimeoutError } = DS; + ### Form validation - export default Ember.Route.extend({ - actions: { - error(error, transition) { - if (error instanceof TimeoutError) { - // alert the user - alert('Are you still connected to the internet?'); - return; - } + In the following example the control elements of the three form elements value will be bound to the properties + (given by `property`) of the form's `model`, which in this case is its controller (see `model=this`): - // ...other error handling logic - } - } - }); + ```handlebars + + + + + Submit + ``` - @class TimeoutError - @namespace DS - */ - var TimeoutError = exports.TimeoutError = extend(AdapterError, 'The adapter operation timed out'); - - /** - A `DS.AbortError` is used by an adapter to signal that a request to - the external API was aborted. For example, this can occur if the user - navigates away from the current page after a request to the external API - has been initiated but before a response has been received. - - @class AbortError - @namespace DS - */ - var AbortError = exports.AbortError = extend(AdapterError, 'The adapter operation was aborted'); - - /** - A `DS.UnauthorizedError` equates to a HTTP `401 Unauthorized` response - status. It is used by an adapter to signal that a request to the external - API was rejected because authorization is required and has failed or has not - yet been provided. + By using this indirection in comparison to directly binding the `value` property, you get the benefit of automatic + form validation, given that your `model` has a supported means of validating itself. + See [Components.Form](Components.Form.html) for details on how to enable form validation. - An example use case would be to redirect the user to a log in route if a - request is unauthorized: + In the example above the `model` was our controller itself, so the control elements were bound to the appropriate + properties of our controller. A controller implementing validations on those properties could look like this: - ```app/routes/application.js + ```js import Ember from 'ember'; - import DS from 'ember-data'; - - const { UnauthorizedError } = DS; - - export default Ember.Route.extend({ - actions: { - error(error, transition) { - if (error instanceof UnauthorizedError) { - // go to the sign in route - this.transitionTo('login'); - return; + import EmberValidations from 'ember-validations'; + + export default Ember.Controller.extend(EmberValidations,{ + email: null, + password: null, + rememberMe: false, + validations: { + email: { + presence: true, + format: { + with: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/ } - - // ...other error handling logic + }, + password: { + presence: true, + length: { minimum: 6, maximum: 10} + }, + comments: { + length: { minimum: 5, maximum: 20} } } }); ``` - @class UnauthorizedError - @namespace DS - */ - var UnauthorizedError = exports.UnauthorizedError = extendedErrorsEnabled ? extend(AdapterError, 'The adapter operation is unauthorized') : null; - - /** - A `DS.ForbiddenError` equates to a HTTP `403 Forbidden` response status. - It is used by an adapter to signal that a request to the external API was - valid but the server is refusing to respond to it. If authorization was - provided and is valid, then the authenticated user does not have the - necessary permissions for the request. - - @class ForbiddenError - @namespace DS - */ - var ForbiddenError = exports.ForbiddenError = extendedErrorsEnabled ? extend(AdapterError, 'The adapter operation is forbidden') : null; - - /** - A `DS.NotFoundError` equates to a HTTP `404 Not Found` response status. - It is used by an adapter to signal that a request to the external API - was rejected because the resource could not be found on the API. - - An example use case would be to detect if the user has entered a route - for a specific model that does not exist. For example: - - ```app/routes/post.js - import Ember from 'ember'; - import DS from 'ember-data'; - - const { NotFoundError } = DS; + If the `showValidation` property is `true` (which is automatically the case if a `focusOut` event is captured from the + control element or the containing `Components.Form` was submitted with its `model` failing validation) and there are + validation errors for the `model`'s `property`, the appropriate Bootstrap validation markup (see + http://getbootstrap.com/css/#forms-control-validation) is applied: - export default Ember.Route.extend({ - model(params) { - return this.get('store').findRecord('post', params.post_id); - }, - - actions: { - error(error, transition) { - if (error instanceof NotFoundError) { - // redirect to a list of all posts instead - this.transitionTo('posts'); - } else { - // otherwise let the error bubble - return true; - } - } - } - }); - ``` + * `validation` is set to 'error', which will set the `has-error` CSS class + * the `errorIcon` feedback icon is displayed if `controlType` is a text field + * the validation messages are displayed as Bootstrap `help-block`s in BS3 and `form-control-feedback` in BS4 - @class NotFoundError - @namespace DS - */ - var NotFoundError = exports.NotFoundError = extendedErrorsEnabled ? extend(AdapterError, 'The adapter could not find the resource') : null; - - /** - A `DS.ConflictError` equates to a HTTP `409 Conflict` response status. - It is used by an adapter to indicate that the request could not be processed - because of a conflict in the request. An example scenario would be when - creating a record with a client generated id but that id is already known - to the external API. + The same applies for warning messages, if the used validation library supports this. (Currently only + [ember-cp-validations](https://github.com/offirgolan/ember-cp-validations)) - @class ConflictError - @namespace DS - */ - var ConflictError = exports.ConflictError = extendedErrorsEnabled ? extend(AdapterError, 'The adapter operation failed due to a conflict') : null; - - /** - A `DS.ServerError` equates to a HTTP `500 Internal Server Error` response - status. It is used by the adapter to indicate that a request has failed - because of an error in the external API. + As soon as the validation is successful again... - @class ServerError - @namespace DS - */ - var ServerError = exports.ServerError = extendedErrorsEnabled ? extend(AdapterError, 'The adapter operation failed due to a server error') : null; - - /** - Convert an hash of errors into an array with errors in JSON-API format. + * `validation` is set to 'success', which will set the `has-success` CSS class + * the `successIcon` feedback icon is displayed if `controlType` is a text field + * the validation messages are removed - ```javascript - import DS from 'ember-data'; + In case you want to display some error or warning message that is independent of the model's validation, for + example to display a failure message on a login form after a failed authentication attempt (so not coming from + the validation library), you can use the `customError` or `customWarning` properties to do so. - const { errorsHashToArray } = DS; + ### HTML attributes - let errors = { - base: 'Invalid attributes on saving this record', - name: 'Must be present', - age: ['Must be present', 'Must be a number'] - }; + To set HTML attributes on the control element provided by this component when using the modern angle bracket invocation, + you can pass them to the yielded `control` component: - let errorsArray = errorsHashToArray(errors); - // [ - // { - // title: "Invalid Document", - // detail: "Invalid attributes on saving this record", - // source: { pointer: "/data" } - // }, - // { - // title: "Invalid Attribute", - // detail: "Must be present", - // source: { pointer: "/data/attributes/name" } - // }, - // { - // title: "Invalid Attribute", - // detail: "Must be present", - // source: { pointer: "/data/attributes/age" } - // }, - // { - // title: "Invalid Attribute", - // detail: "Must be a number", - // source: { pointer: "/data/attributes/age" } - // } - // ] + ```hbs + + + + + ... + ``` - @method errorsHashToArray + @class FormElement + @namespace Components + @extends Components.FormGroup @public - @namespace - @for DS - @param {Object} errors hash with errors as properties - @return {Array} array of errors in JSON-API format */ - function errorsHashToArray(errors) { - var out = []; - - if (_ember.default.isPresent(errors)) { - Object.keys(errors).forEach(function (key) { - var messages = _ember.default.makeArray(errors[key]); - for (var i = 0; i < messages.length; i++) { - var title = 'Invalid Attribute'; - var pointer = '/data/attributes/' + key; - if (key === PRIMARY_ATTRIBUTE_KEY) { - title = 'Invalid Document'; - pointer = '/data'; - } - out.push({ - title: title, - detail: messages[i], - source: { - pointer: pointer - } - }); - } - }); + let FormElement = _exports.default = (_dec = (0, _emberRefBucket.ref)('mainNode'), (_class = class FormElement extends _component2.default { + /** + * The value of the control element is bound to this property: + * + * ```hbs + * + * ``` + * + * Note two things: + * * the binding is uni-directional (DDAU), so you would have to use the `onChange` action to subscribe to changes. + * * you lose the ability to validate this form element by directly binding to its value. It is recommended + * to use the `property` feature instead. + * + * @property value + * @public + */ + get value() { + (true && !((0, _utils.isBlank)(this.args.property) || (0, _utils.isBlank)(this.args.value)) && (0, _debug.assert)('You can not set both property and value on a form element', (0, _utils.isBlank)(this.args.property) || (0, _utils.isBlank)(this.args.value))); + if (this.args.property && this.args.model) { + return (0, _object.get)(this.args.model, this.args.property); + } + return this.args.value; } - return out; - } + /** + The property name of the form element's `model` (by default the `model` of its parent `Components.Form`) that this + form element should represent. The control element's value will automatically be bound to the model property's + value. + Using this property enables form validation on this element. + @property property + @type string + @public + */ - /** - Convert an array of errors in JSON-API format into an object. - - ```javascript - import DS from 'ember-data'; - - const { errorsArrayToHash } = DS; - - let errorsArray = [ - { - title: 'Invalid Attribute', - detail: 'Must be present', - source: { pointer: '/data/attributes/name' } - }, - { - title: 'Invalid Attribute', - detail: 'Must be present', - source: { pointer: '/data/attributes/age' } - }, - { - title: 'Invalid Attribute', - detail: 'Must be a number', - source: { pointer: '/data/attributes/age' } - } - ]; - - let errors = errorsArrayToHash(errorsArray); - // { - // "name": ["Must be present"], - // "age": ["Must be present", "must be a number"] - // } - ``` - - @method errorsArrayToHash - @public - @namespace - @for DS - @param {Array} errors array of errors in JSON-API format - @return {Object} - */ - function errorsArrayToHash(errors) { - var out = {}; + /** + * The model used for validation. Defaults to the parent `Components.Form`'s `model` + * + * @property model + * @public + */ - if (_ember.default.isPresent(errors)) { - errors.forEach(function (error) { - if (error.source && error.source.pointer) { - var key = error.source.pointer.match(SOURCE_POINTER_REGEXP); + /** + * Show a help text next to the control + * + * @property helpText + * @type {string} + * @public + */ - if (key) { - key = key[2]; - } else if (error.source.pointer.search(SOURCE_POINTER_PRIMARY_REGEXP) !== -1) { - key = PRIMARY_ATTRIBUTE_KEY; - } + /** + * Only if there is a validator, this property makes all errors to be displayed at once + * inside a scrollable container. + * + * @default false + * @property showMultipleErrors + * @public + * @type {Boolean} + */ - if (key) { - out[key] = out[key] || []; - out[key].push(error.detail || error.title); - } - } - }); + /** + * @property hasErrors + * @type boolean + * @readonly + * @private + */ + get hasErrors() { + return Array.isArray(this.errors) && this.errors.length > 0; } - return out; - } -}); -define('ember-data/adapters/json-api', ['exports', 'ember', 'ember-data/adapters/rest', 'ember-data/-private/features', 'ember-data/-private/debug'], function (exports, _ember, _rest, _features, _debug) { - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); + /** + * The array of warning messages from the `model`'s validation. + * + * @property warnings + * @type array + * @protected + */ + // This shouldn't be an argument. It's only an argument because tests rely on + // setting it as an argument. See https://github.com/kaliber5/ember-bootstrap/issues/1338 + // for details. + /** + * @property hasWarnings + * @type boolean + * @readonly + * @private + */ + get hasWarnings() { + return Array.isArray(this.warnings) && this.warnings.length > 0; + } - /** - The `JSONAPIAdapter` is the default adapter used by Ember Data. It - is responsible for transforming the store's requests into HTTP - requests that follow the [JSON API](http://jsonapi.org/format/) - format. - - ## JSON API Conventions - - The JSONAPIAdapter uses JSON API conventions for building the url - for a record and selecting the HTTP verb to use with a request. The - actions you can take on a record map onto the following URLs in the - JSON API adapter: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Action - - HTTP Verb - - URL -
- `store.findRecord('post', 123)` - - GET - - /posts/123 -
- `store.findAll('post')` - - GET - - /posts -
- Update `postRecord.save()` - - PATCH - - /posts/123 -
- Create `store.createRecord('post').save()` - - POST - - /posts -
- Delete `postRecord.destroyRecord()` - - DELETE - - /posts/123 -
- - ## Success and failure - - The JSONAPIAdapter will consider a success any response with a - status code of the 2xx family ("Success"), as well as 304 ("Not - Modified"). Any other status code will be considered a failure. - - On success, the request promise will be resolved with the full - response payload. - - Failed responses with status code 422 ("Unprocessable Entity") will - be considered "invalid". The response will be discarded, except for - the `errors` key. The request promise will be rejected with a - `DS.InvalidError`. This error object will encapsulate the saved - `errors` value. - - Any other status codes will be treated as an adapter error. The - request promise will be rejected, similarly to the invalid case, - but with an instance of `DS.AdapterError` instead. - - ### Endpoint path customization - - Endpoint paths can be prefixed with a `namespace` by setting the - namespace property on the adapter: - - ```app/adapters/application.js - import DS from 'ember-data'; - - export default DS.JSONAPIAdapter.extend({ - namespace: 'api/1' - }); - ``` - Requests for the `person` model would now target `/api/1/people/1`. - - ### Host customization - - An adapter can target other hosts by setting the `host` property. - - ```app/adapters/application.js - import DS from 'ember-data'; - - export default DS.JSONAPIAdapter.extend({ - host: 'https://api.example.com' - }); - ``` - - Requests for the `person` model would now target - `https://api.example.com/people/1`. - - @since 1.13.0 - @class JSONAPIAdapter - @constructor - @namespace DS - @extends DS.RESTAdapter - */ - /* global heimdall */ - /** - @module ember-data - */ + /** + * Show a custom error message that does not come from the model's validation. Will be immediately shown, regardless + * of any user interaction (i.e. no `focusOut` event required) + * + * @property customError + * @type string + * @public + */ - var JSONAPIAdapter = _rest.default.extend({ - defaultSerializer: '-json-api', + /** + * @property hasCustomError + * @type boolean + * @readonly + * @private + */ + get hasCustomError() { + return (0, _utils.isPresent)(this.args.customError); + } - ajaxOptions: function ajaxOptions(url, type, options) { - var hash = this._super.apply(this, arguments); + /** + * Show a custom warning message that does not come from the model's validation. Will be immediately shown, regardless + * of any user interaction (i.e. no `focusOut` event required). If the model's validation has an error then the error + * will be shown in place of this warning. + * + * @property customWarning + * @type string + * @public + */ - if (hash.contentType) { - hash.contentType = 'application/vnd.api+json'; - } + /** + * @property hasCustomWarning + * @type boolean + * @readonly + * @private + */ + get hasCustomWarning() { + return (0, _utils.isPresent)(this.args.customWarning); + } - var beforeSend = hash.beforeSend; - hash.beforeSend = function (xhr) { - xhr.setRequestHeader('Accept', 'application/vnd.api+json'); - if (beforeSend) { - beforeSend(xhr); - } - }; + /** + * Property for size styling, set to 'lg', 'sm' or 'xs' (the latter only for BS3) + * + * @property size + * @type String + * @public + */ - return hash; - }, + /** + * The array of validation messages (either errors or warnings) from either custom error/warnings or , if we are showing model validation messages, the model's validation + * + * @property validationMessages + * @type array + * @private + */ + get validationMessages() { + if (this.hasCustomError) { + return (0, _array.A)([this.args.customError]); + } + if (this.hasErrors && this.showModelValidation) { + return (0, _array.A)(this.errors); + } + if (this.hasCustomWarning) { + return (0, _array.A)([this.args.customWarning]); + } + if (this.hasWarnings && this.showModelValidation) { + return (0, _array.A)(this.warnings); + } + return null; + } + /** + * @property hasValidationMessages + * @type boolean + * @readonly + * @private + */ + get hasValidationMessages() { + return Array.isArray(this.validationMessages) && this.validationMessages.length > 0; + } /** - By default the JSONAPIAdapter will send each find request coming from a `store.find` - or from accessing a relationship separately to the server. If your server supports passing - ids as a query string, you can set coalesceFindRequests to true to coalesce all find requests - within a single runloop. - For example, if you have an initial payload of: - ```javascript - { - data: { - id: 1, - type: 'post', - relationship: { - comments: { - data: [ - { id: 1, type: 'comment' }, - { id: 2, type: 'comment' } - ] - } - } - } - } - ``` - By default calling `post.get('comments')` will trigger the following requests(assuming the - comments haven't been loaded before): - ``` - GET /comments/1 - GET /comments/2 - ``` - If you set coalesceFindRequests to `true` it will instead trigger the following request: - ``` - GET /comments?filter[id]=1,2 - ``` - Setting coalesceFindRequests to `true` also works for `store.find` requests and `belongsTo` - relationships accessed within the same runloop. If you set `coalesceFindRequests: true` - ```javascript - store.findRecord('comment', 1); - store.findRecord('comment', 2); - ``` - will also send a request to: `GET /comments?filter[id]=1,2` - Note: Requests coalescing rely on URL building strategy. So if you override `buildURL` in your app - `groupRecordsForFindMany` more likely should be overridden as well in order for coalescing to work. - @property coalesceFindRequests - @type {boolean} - */ - coalesceFindRequests: false, + * Set a validating state for async validations + * + * @property isValidating + * @type boolean + * @default false + * @protected + */ - findMany: function findMany(store, type, ids, snapshots) { - if ((0, _features.default)('ds-improved-ajax') && !this._hasCustomizedAjax()) { - return this._super.apply(this, arguments); - } else { - var url = this.buildURL(type.modelName, ids, snapshots, 'findMany'); - return this.ajax(url, 'GET', { data: { filter: { id: ids.join(',') } } }); + /** + * If `true` form validation markup is rendered (requires a validatable `model`). + * + * @property showValidation + * @type boolean + * @default false + * @private + */ + get showValidation() { + return this.showOwnValidation || this.showAllValidations || this.hasCustomError || this.hasCustomWarning; + } + + /** + * @property showOwnValidation + * @type boolean + * @default false + * @private + */ + + /* + * Resets `showOwnValidation` if `@showAllValidations` argument is changed to `false`. + * Must be called whenever `@showAllValidations` argument changes. + */ + handleShowAllValidationsChange() { + if (this.args.showAllValidations === false) { + this.showOwnValidation = false; } - }, - pathForType: function pathForType(modelName) { - var dasherized = _ember.default.String.dasherize(modelName); - return _ember.default.String.pluralize(dasherized); - }, - updateRecord: function updateRecord(store, type, snapshot) { - if ((0, _features.default)('ds-improved-ajax') && !this._hasCustomizedAjax()) { - return this._super.apply(this, arguments); - } else { - var data = {}; - var serializer = store.serializerFor(type.modelName); + } - serializer.serializeIntoHash(data, type, snapshot, { includeId: true }); + /** + * @property showModelValidations + * @type boolean + * @readonly + * @private + */ + get showModelValidation() { + return this.showOwnValidation || this.showAllValidations; + } - var url = this.buildURL(type.modelName, snapshot.id, snapshot, 'updateRecord'); + /** + * @property showValidationMessages + * @type boolean + * @readonly + * @private + */ + get showValidationMessages() { + return this.showValidation && this.hasValidationMessages; + } - return this.ajax(url, 'PATCH', { data: data }); - } - }, - _hasCustomizedAjax: function _hasCustomizedAjax() { - if (this.ajax !== JSONAPIAdapter.prototype.ajax) { - (0, _debug.deprecate)('JSONAPIAdapter#ajax has been deprecated please use. `methodForRequest`, `urlForRequest`, `headersForRequest` or `dataForRequest` instead.', false, { - id: 'ds.json-api-adapter.ajax', - until: '3.0.0' + /** + * Event or list of events which enable form validation markup rendering. + * Supported events: ['focusout', 'change', 'input'] + * + * @property showValidationOn + * @type string|array + * @default ['focusout'] + * @public + */ + + /** + * @property _showValidationOn + * @type array + * @readonly + * @private + */ + get _showValidationOn() { + let showValidationOn = this.showValidationOn; + (true && !((0, _array.isArray)(showValidationOn) || (0, _utils.typeOf)(showValidationOn) === 'string') && (0, _debug.assert)('showValidationOn must be a String or an Array', (0, _array.isArray)(showValidationOn) || (0, _utils.typeOf)(showValidationOn) === 'string')); + if ((0, _array.isArray)(showValidationOn)) { + return showValidationOn.map(type => { + return type.toLowerCase(); }); - return true; } + if (typeof showValidationOn.toString === 'function') { + return [showValidationOn.toLowerCase()]; + } + return []; + } - if (this.ajaxOptions !== JSONAPIAdapter.prototype.ajaxOptions) { - (0, _debug.deprecate)('JSONAPIAdapterr#ajaxOptions has been deprecated please use. `methodForRequest`, `urlForRequest`, `headersForRequest` or `dataForRequest` instead.', false, { - id: 'ds.json-api-adapter.ajax-options', - until: '3.0.0' - }); - return true; + /** + * @method showValidationOnHandler + * @param {Event} event + * @private + */ + showValidationOnHandler({ + target, + type + }) { + // Should not do anything if + if ( + // validations should not be shown for this event type or + this._showValidationOn.indexOf(type) === -1 || + // validation should not be shown for this event target + (0, _array.isArray)(this.doNotShowValidationForEventTargets) && this.doNotShowValidationForEventTargets.length > 0 && this._element && [...this._element.querySelectorAll(this.doNotShowValidationForEventTargets.join(','))].some(el => el.contains(target))) { + return; } + this.showOwnValidation = true; + } - return false; + /** + * Controls if validation should be shown for specified event targets. + * + * It expects an array of query selectors. If event target is a children of an event that matches + * these selectors, an event triggered for it will not trigger validation errors to be shown. + * + * By default, events fired on elements inside an input group are skipped. + * + * If `null` or an empty array is passed validation errors are shown for all events regardless + * of event target. + * + * @property doNotShowValidationForEventTargets + * @type ?array + * @public + */ + + /** + * The validation ("error" (BS3)/"danger" (BS4), "warning", or "success") or null if no validation is to be shown. Automatically computed from the + * model's validation state. + * + * @property validation + * @readonly + * @type string + * @private + */ + get validation() { + const shouldShowValidationState = this.showModelValidation && this.hasValidator && !this.isValidating && !this.args._disabled; + if ( /* custom errors should be always shown */ + this.hasCustomError || ( /* validation error should be shown in preference to warnings */ + shouldShowValidationState && this.hasErrors)) { + return 'error'; + } + if ( /* custom warning should be always shown unless there is a validation error */ + this.hasCustomWarning || shouldShowValidationState && this.hasWarnings) { + return 'warning'; + } + if (shouldShowValidationState) { + return 'success'; + } + return null; } - }); - if ((0, _features.default)('ds-improved-ajax')) { + /** + * The form layout used for the markup generation (see http://getbootstrap.com/css/#forms): + * + * * 'horizontal' + * * 'vertical' + * * 'inline' + * + * Defaults to the parent `form`'s `formLayout` property. + * + * @property formLayout + * @type string + * @default 'vertical' + * @public + */ - JSONAPIAdapter.reopen({ - methodForRequest: function methodForRequest(params) { - if (params.requestType === 'updateRecord') { - return 'PATCH'; - } + /** + * The Bootstrap grid classes for form labels within a horizontal layout form. Defaults to the value of the same + * property of the parent form. The corresponding grid classes for form controls are automatically computed. + * + * @property horizontalLabelGridClass + * @type string + * @public + */ - return this._super.apply(this, arguments); - }, - dataForRequest: function dataForRequest(params) { - var requestType = params.requestType, - ids = params.ids; + /** + * ID for input field and the corresponding label's "for" attribute + * + * @property formElementId + * @type string + * @private + */ + get formElementId() { + return `${this._elementId}-field`; + } + /** + * ID of the helpText, used for aria-describedby attribute of the control element + * + * @property ariaDescribedBy + * @type string + * @private + */ + get ariaDescribedBy() { + return `${this._elementId}-help`; + } - if (requestType === 'findMany') { - return { - filter: { id: ids.join(',') } - }; - } + /** + * @property layoutComponent + * @type {String} + * @private + */ - if (requestType === 'updateRecord') { - var store = params.store, - type = params.type, - snapshot = params.snapshot; + /** + * @property controlComponent + * @private + */ + get controlComponent() { + let owner = (0, _application.getOwner)(this); + let componentClass = owner.resolveRegistration(`component:bs-form/element/control/${this.controlType}`); + if (componentClass) { + return componentClass; + } + if (this.controlType === 'checkbox') { + return _checkbox.default; + } else if (this.controlType === 'textarea') { + return _textarea.default; + } else if (this.controlType === 'radio') { + return _radio.default; + } else if (this.controlType === 'switch') { + return _switch.default; + } else { + return _input.default; + } + } - var data = {}; - var serializer = store.serializerFor(type.modelName); + /** + * @property errorsComponent + * @type {String} + * @private + */ - serializer.serializeIntoHash(data, type, snapshot, { includeId: true }); + /** + * @property feedbackIconComponent + * @type {String} + * @private + */ - return data; - } + /** + * @property labelComponent + * @type {String} + * @private + */ - return this._super.apply(this, arguments); - }, - headersForRequest: function headersForRequest() { - var headers = this._super.apply(this, arguments) || {}; + /** + * @property helpTextComponent + * @type {String} + * @private + */ - headers['Accept'] = 'application/vnd.api+json'; + /** + * Setup validation properties. This method acts as a hook for external validation + * libraries to overwrite. In case of failed validations the `errors` property should contain an array of error messages. + * + * @method setupValidations + * @private + */ - return headers; - }, - _requestToJQueryAjaxHash: function _requestToJQueryAjaxHash() { - var hash = this._super.apply(this, arguments); + /** + * The action is called whenever the input value is changed, e.g. by typing text + * + * @event onChange + * @param {String} value The new value of the form control + * @param {Object} model The form element's model + * @param {String} property The value of `property` + * @public + */ - if (hash.contentType) { - hash.contentType = 'application/vnd.api+json'; - } + /** + * Private duplicate of onChange event used for internal state handling between form and it's elements. + * + * @event _onChange + * @private + */ - return hash; - } - }); + constructor() { + super(...arguments); + /** + * @property _element + * @type null | HTMLElement + * @private + */ + _initializerDefineProperty(this, "_element", _descriptor, this); + /** + * Text to display within a `